开发Tips收集-2016年01月

这些小Tips为本人近期读书笔记,收集来自网络开发者发布的技术文档,并非原创,共享的目的是为了扩散分享技术,共同进步。如有侵权不得转载等情况,请联系我告知,谢谢!

  • 你可以在 Gemfile 中指定 cocoapods gem 的使用版本。
    source 'https://rubygems.org'
    gem 'cocoapods', '0.39.0'
    当你更新了 Gemfile 文件并且自动安装了正确版本的 gem 后,确保团队的每个成员都运行一次 bundle install 这条命令。此后,只需要运行 bundle exec pod install 这条命令来安装新的 CocoaPods——这将会确保通过你在的 Gemfile 中指定 cocoapods gem 的版本后,pods 仍可以被正确的安装。
  • instrument调试后,发现没被释放的全是imageIO,差不多就知道了,把读图的方式,从UIImage imageNamed:@”“,改成imageWithContentsOfFile,就可以了。问题原因:imageNamed读取图片的方法,会缓存在内存中,所以较大的图片,还是用imageWithContentsOfFile。
    Tip1:.xcassets里的图片无法用imageWithContentsOfFile读取;
    Tip2:imageWithContentsOfFile读取图片需要加文件后缀名如png,jpg等;
  • 不要将旋转视作设备的移动。相反将其视为视图控制器尺寸的改变,因为从用户的角度来看,这才是真实发生的操作。
    • 资源文件瘦身:
      1. 减少图片和音频文件的大小
      2. 对于PNG图片,由于它内部保存了额外的分层和透明通道信息,统称为EXIF,所以它会比JPG图片大一些。App开发推荐使用PNG图片是因为XCode会在打包时压缩PNG图片的大小。
      3. 单色图片使用使用字体文件。关于字体文件的技术,也就是IconFont,网上有很多例子,同时适用于Andorid和iOS
      4. 使用.9图。之所周知.9图是Android的技术,能极大减小图片的体积,殊不知,iOS也有类似的实现方式。
      5. 动态下载表情包。把聊天时用到的表情图片,做成从服务器下载zip包的方式,而不是打包在App中。
      6. 清除不再使用的图片。
  • .a文件瘦身
    1. 冗余的类和方法。
    2. 相似度极高的代码片段
    3. 使用代码生成UI,而不是使用Xib或Storyboard。经过测试,对于同一个页面,使用代码而导致的.a文件增加的体积,大于Xib的体积。
    4. 使用Hybird方案来代替iOS原生代码。
    5. 编译选项的优化。比如说Strip Link Product设为Yes啊,Make Strings Read-Only设为Yes啊,去掉异常支持啊,都能减少包的大小。此外,经常检查LinkMap文件,也是控制瘦身的一个办法。
  • flatMap()与map()其实非常相似,map()的规则是T->U,而flatMap()的规则是T->U?,而且如果转换的结果是nil的话,flatMap()是不会将其添加到输出的array中的。 因此可以说flapMap()就好像你去使用map(),然后扁平化(faltten)地从结果中去除了那些nil的内容。
  • 事件(比如,触摸事件(touch event))都使用响应链来传递。响应链由响应者对象(Responder Objects,苹果官方术语)构成。UIView 和 UIViewController 都是响应者对象。这就意味着, UIView 和 UIViewController 都继承自 UIResponder
  • (void)prepareLayout; 第一次加载layout、刷新layout、以及- (BOOL)shouldInvalidateLayoutForBoundsChange:(CGRect)newBounds;这个方法返回yes时,会调用。实现该方法后应该调用[super prepareLayout]保证初始化正确。该方法用来准备一些布局所需要的信息。该方法和init方法相似,但该方法可能会被调用多次,所以一些不固定的计算(比如该计算和collectionView的尺寸相关),最好放在这里,以保证collectionView发生变化时,自定义CollectionView能做出正确的反应
  • KVC 机制是由一个协议 NSKeyValueCoding 定义的。NSObject 帮我们实现了这个协议,所以 KVC 核心的逻辑都在 NSObject 中,我们继承 NSObject 才能让我们的类获得 KVC 的能力。另外,因为 Swift 中的 Optional 机制,所以 valueForKey 方法返回的是一个 Optional 值,我们还需要对返回值做一次解包处理,才能得到实际的属性值。
  • UINavigationController介绍
    1. UINavigationController是导航控制器,它通过栈的方式控制当前显示在屏幕上的是哪个控制器。
    2. 它可以通过压入(push)和弹出(pop)来改变控制器的层次。
    3. 自动提供返回(Back)按钮,以回到上一个压入的控制器,不需要额外编程
    4. UINavigationController会提供控制器切换的动画效果
    5. UINavgationController通过栈的形式管理多个UIViewController(即多个界面)
    6. 可以管理当前在导航条(navigationBar)上的导航按钮
    7. UINavgationController为每个接受它管理的UIViewController自动添加UINavigationBar
  • 类似于画板这样画线条的需求直接用专有图层CAShapeLayer。CAShapeLayer是一个通过矢量图形而不是bitmap来绘制的图层子类。用CGPath来定义想要绘制的图形,CAShapeLayer会自动渲染。它可以完美替代我们的直接使用Core Graphics绘制layer,对比之下使用CAShapeLayer有以下优点:
    1. 渲染快速。CAShapeLayer使用了硬件加速,绘制同一图形会比用Core Graphics快很多。
    2. 高效使用内存。一个CAShapeLayer不需要像普通CALayer一样创建一个寄宿图形,所以无论有多大,都不会占用太多的内存。
    3. 不会被图层边界剪裁掉。
    4. 不会出现像素化。
  • 使用串行队列的优点:
    1. 能确保对一个共享资源进行串行化的访问,避免了竞态条件;
    2. 任务的执行顺序是可预知的;你向一个串行队列提交任务时,它们被执行的顺序与它们被提交的顺序相同;
    3. 你可以创建任意数量的串行队列;
  • 父视图通过tag取得子视图(viewWithTag)的顺序是深度优先,也就是先查看自己的第一个子视图,然后查看第一个子视图的所有子视图的tag值,直到第一个子视图下的所有子视图搜索完,再搜索自己第二个子视图,直到找到为止。找不到就返回nil
  • 继承定义了这个对象是什么,而特性则定义了这个对象能做什么
    更棒的消息是:一个类可以部署很多特性,也就是可以同时做很多事情,这是只从单一父类继承而来的子类所不可企及的,因为他们一次只能做一件事情。
  • 动画属性UIViewAnimationOptions说明
    1. 常规动画属性设置(可以同时选择多个进行设置)
      UIViewAnimationOptionLayoutSubviews:动画过程中保证子视图跟随运动。
      UIViewAnimationOptionAllowUserInteraction:动画过程中允许用户交互。
      UIViewAnimationOptionBeginFromCurrentState:所有视图从当前状态开始运行。
      UIViewAnimationOptionRepeat:重复运行动画。
      UIViewAnimationOptionAutoreverse :动画运行到结束点后仍然以动画方式回到初始点。
      UIViewAnimationOptionOverrideInheritedDuration:忽略嵌套动画时间设置。
      UIViewAnimationOptionOverrideInheritedCurve:忽略嵌套动画速度设置。
      UIViewAnimationOptionAllowAnimatedContent:动画过程中重绘视图(注意仅仅适用于转场动画)。
      UIViewAnimationOptionShowHideTransitionViews:视图切换时直接隐藏旧视图、显示新视图,而不是将旧视图从父视图移除(仅仅适用于转场动画)
      UIViewAnimationOptionOverrideInheritedOptions :不继承父动画设置或动画类型。
    2. 动画速度控制(可从其中选择一个设置)
      UIViewAnimationOptionCurveEaseInOut:动画先缓慢,然后逐渐加速。
      UIViewAnimationOptionCurveEaseIn :动画逐渐变慢。
      UIViewAnimationOptionCurveEaseOut:动画逐渐加速。
      UIViewAnimationOptionCurveLinear :动画匀速执行,默认值。
    3. 转场类型(仅适用于转场动画设置,可以从中选择一个进行设置,基本动画、关键帧动画不需要设置)
      UIViewAnimationOptionTransitionNone:没有转场动画效果。
      UIViewAnimationOptionTransitionFlipFromLeft :从左侧翻转效果。
      UIViewAnimationOptionTransitionFlipFromRight:从右侧翻转效果。
      UIViewAnimationOptionTransitionCurlUp:向后翻页的动画过渡效果。
      UIViewAnimationOptionTransitionCurlDown :向前翻页的动画过渡效果。
      UIViewAnimationOptionTransitionCrossDissolve:旧视图溶解消失显示下一个新视图的效果。
      UIViewAnimationOptionTransitionFlipFromTop :从上方翻转效果。
      UIViewAnimationOptionTransitionFlipFromBottom:从底部翻转效果。
  • 每当在UICollectionView显示它的subview之前调用scrollToItemAtIndexPath:atScrollPosition:Animated方法,UIKit就会报错。所以要解决它,就应该在viewController中,在你能确认CollectionView完全计算出其subview布局的地方去调用这个方法。比如在viewDidLayoutSubviews里调用就没有问题。
  • 设置缓存只需要:如果你已经使用 了 GET 请求,iOS 系统 SDK 已经帮你做好了缓存。你需要的仅仅是设置下内存缓存大小、磁盘缓存大小、以及缓存路径。甚至这两行代码不设置也是可以的,会有一个默认值。代码如下:
    NSURLCache *urlCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 diskCapacity:20 * 1024 * 1024 diskPath:nil];
    [NSURLCache setSharedURLCache:urlCache];
  • 在 LLDB 中输入 fr v -R foo,可以查看 foo 这个变量的内存构成。
  • 倘若一个标记为 lazy 的属性同时被多个线程修改时,且该属性还未进行初始化操作,那么将无法保证该属性仅被初始化一次。
  • 页面跳转必须在viewDidLoad和viewDidAppear之后才能进行