1、iPhone开发如何兼容iPad?
需要有两套UI布局,但是考虑到iPad版本一般需要支持横屏,所以工作量还是蛮大的,而且不容易协调,导致整个项目的迭代遇到很多问题,无法正式发布产品。综上,如果时间紧急,那么可以考虑迭代+一套代码维护。如果是大项目,从零开发,那么需要分项目+共享库的架构开始设计,最终决策取决于你自己对项目的进度把控以及需求裁减。
2、项目开发中如何进行性能优化?
可以用instruments来查看哪些地方需要优化,详情请点击下面网址。http://www.open-open.com/lib/view/open1423124822545.html
具体优化方案:
我要给出的建议将分为三个不同的等级: 入门级、 中级和进阶级:
入门级(这是些你一定会经常用在你app开发中的建议)
- 1. 用ARC管理内存
- ARC是和iOS5一起发布的,它避免了最常见的也就是经常是由于我们忘记释放内存所造成的内存泄露。它自动为你管理ratain和release的过程,所以你就不必去手动干预了。
- 2. 在正确的地方使用reuseIdentifier
- 3. 尽可能少得使Views的透明色渲染
- 4. 避免庞大的XIB
- 如果你不得不XIB的话,使他们尽量简单。尝试为每个Controller配置一个单独的XIB,尽可能把一个View Controller的view层次结构分散到单独的XIB中去。
- 需要注意的是,当你加载一个XIB的时候所有内容都被放在了内存里,包括任何图片。如果有一个不会即刻用到的view,你这就是在浪费宝贵的内存资源了。Storyboards就是另一码事儿了,storyboard仅在 需要时实例化一个view controller.
- 5. 不要阻塞主线程
- 永远不要使主线程承担过多,因为UIKit在主线程上做的所有工作,渲染,管理触摸反应,回应输入等都需要在它上面完成。
- 大部分阻碍主线程的情形是你的app在做一些牵涉到读写外部资源的I/O操作,比如存储或者网络。你可以使用多线程进行一步存储或者加载。
- 6. 在Image Views中调整图片大小
如果要在UIImageView中显示一个来自bundle的图片,你应保证图片的大小和UIImageView的大小相同。在运行中缩放图片是很耗费资源的,特别是UIImageView嵌套在UIScrollView中的情况下。
如果图片是从远端服务加载的你不能控制图片大小,比如在下载前调整到合适大小的话,你可以在下载完成后,最好是用background thread,缩放一次,然后在UIImageView中使用缩放后的图片。
- 7. 学会选择对业务场景最合适的类或者对象
- 比如:Arrays: 有序的一组值。使用index来lookup很快,使用value lookup很慢, 插入/删除很慢。
- Dictionaries: 存储键值对。 用键来查找比较快。
- Sets: 无序的一组值。用值来查找很快,插入/删除很快。
- 8. 打开gzip压缩
大量app依赖于远端资源和第三方API,你可能会开发一个需要从远端下载的xml,json,html或者其他格式的app,减小文档的一个方式就是在服务器和你的app中打开gzip,好消息是iOS已经在NSURLConnection中默认支持了gzip,当然AFNetworking这些基于它的框架亦然。
中级(这些是你可能在一些相对复杂情况下可能用到的)
- 9. 重用和延迟加载Views
- 更多的View意味着更多的渲染,也就是更多的CPU和内存消耗,对于那种嵌套了很多view在UIScrollView里边的app更是如此。这里我们用到的技巧就是模仿UITableView和UICollectionView的操作,不要一次创建所有的subView,而是当需要时才创建,当他们完成了使命,把他们放进一个可重用的队列中。对于View有两种实现方法:1、创建并隐藏这个View当这个screen加载的时候,当需要时显示它;2、当需要时才创建。
- (每个方案都有其优缺点。
- 用第一种方案的话因为你需要一开始就创建一个view并保持它直到不再使用,这就会更加消耗内存。然而这也会使你的app操作更敏感因为当用户点击按钮的时候它只需要改变一下这个view的可见性。
- 第二种方案则相反-消耗更少内存,但是会在点击按钮的时候比第一种稍显卡顿。)
- 10. Cache, Cache, 还是Cache!
- NSURLCache,缓存所需要的,也就是那些不大可能改变但是需要经常读取的东西。
- 11. 权衡渲染方法
- 12. 处理内存警告
- 13. 重用大开销的对象
- 一些objects的初始化很慢,比如NSDateFormatter和NSCalendar。然而,你又不可避免地需要使用它们,比如从JSON或者XML中解析数据。
- 想要避免使用这个对象的瓶颈你就需要重用他们,可以通过添加属性到你的class里或者创建静态变量来实现。
- 注意如果你要选择第二种方法,对象会在你的app运行时一直存在于内存中,和单例(singleton)很相似。
- 下面的代码说明了使用一个属性来延迟加载一个date formatter. 第一次调用时它会创建一个新的实例,以后的调用则将返回已经创建的实例:
- 1
- 2
- 3
- 4
- 12
- // in your .h or inside a class extension
- @property (nonatomic, strong) NSDateFormatter *formatter;
- // inside the implementation (.m)
- // When you need, just use self.formatter
- - (NSDateFormatter *)formatter {
- if (! _formatter) {
- _formatter = [[NSDateFormatter alloc] init];
- _formatter.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy"; // twitter date format
- }
- return _formatter;
- }
- 还需要注意的是,其实设置一个NSDateFormatter的速度差不多是和创建新的一样慢的!所以如果你的app需要经常进行日期格式处理的话,你会从这个方法中得到不小的性能提升。
- 14. 使用Sprite Sheets(游戏开发中用到的)
- 15. 避免反复处理数据
- 许多应用需要从服务器加载功能所需的常为JSON或者XML格式的数据。在服务器端和客户端使用相同的数据结构很重要。在内存中操作数据使它们满足你的数据结构是开销很大的。
- 比如你需要数据来展示一个table view,最好直接从服务器取array结构的数据以避免额外的中间数据结构改变。
- 类似的,如果需要从特定key中取数据,那么就使用键值对的dictionary。
- 16. 选择正确的数据格式
- 从app和网络服务间传输数据有很多方案,最常见的就是JSON和XML。你需要选择对你的app来说最合适的一个。
- 解析JSON会比XML更快一些,JSON也通常更小更便于传输。从iOS5起有了官方内建的JSON deserialization 就更加方便使用了。
- 但是XML也有XML的好处,比如使用SAX 来解析XML就像解析本地文件一样,你不需像解析json一样等到整个文档下载完成才开始解析。当你处理很大的数据的时候就会极大地减低内存消耗和增加性能。
- 17. 正确地设定Background Images
- 在View里放背景图片就像很多其它iOS编程一样有很多方法:
- 使用UIColor的 colorWithPatternImage来设置背景色;
- 在view中添加一个UIImageView作为一个子View。
- 如果你使用全画幅的背景图,你就必须使用UIImageView因为UIColor的colorWithPatternImage是用来创建小的重复的图片作为背景的。这种情形下使用UIImageView可以节约不少的内存:
- 1
- // You could also achieve the same result in Interface Builder
- UIImageView *backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"background"]];
- [self.view addSubview:backgroundView];
- 1
- 如果你用小图平铺来创建背景,你就需要用UIColor的colorWithPatternImage来做了,它会更快地渲染也不会花费很多内存:
- 1
- self.view.backgroundColor = [UIColor colorWithPatternImage:[UIImage imageNamed:@"background"]];
- 18. 减少使用Web特性
- UIWebView很有用,用它来展示网页内容或者创建UIKit很难做到的动画效果是很简单的一件事。
- 但是你可能有注意到UIWebView并不像驱动Safari的那么快。这是由于以JIT compilation 为特色的Webkit的Nitro Engine的限制。
- 所以想要更高的性能你就要调整下你的HTML了。第一件要做的事就是尽可能移除不必要的javascript,避免使用过大的框架。能只用原生js就更好了。
- 另外,尽可能异步加载例如用户行为统计script这种不影响页面表达的javascript。
- 最后,永远要注意你使用的图片,保证图片的符合你使用的大小。使用Sprite sheet提高加载速度和节约内存。
- 19. 设定Shadow Path
- 如何在一个View或者一个layer上加一个shadow呢,QuartzCore框架是很多开发者的选择:
- 1
- 2
- 3
- #import <QuartzCore/QuartzCore.h>
- // Somewhere later ...
- UIView *view = [[UIView alloc] init];
- // Setup the shadow ...
- view.layer.shadowOffset = CGSizeMake(-1.0f, 1.0f);
- view.layer.shadowRadius = 5.0f;
- view.layer.shadowOpacity = 0.6;
- 看起来很简单,对吧。
- 可是,坏消息是使用这个方法也有它的问题… Core Animation不得不先在后台得出你的图形并加好阴影然后才渲染,这开销是很大的。
- 使用shadowPath的话就避免了这个问题:
- view.layer.shadowPath = [[UIBezierPath bezierPathWithRect:view.bounds] CGPath];
- 使用shadow path的话iOS就不必每次都计算如何渲染,它使用一个预先计算好的路径。但问题是自己计算path的话可能在某些View中比较困难,且每当view的frame变化的时候你都需要去update shadow path.
- 20. 优化你的Table View
- Table view需要有很好的滚动性能,不然用户会在滚动过程中发现动画的瑕疵。
- 为了保证table view平滑滚动,确保你采取了以下的措施:
- 1、正确使用`reuseIdentifier`来重用cells
- 2、尽量使所有的view opaque,包括cell自身
- 3、避免渐变,图片缩放,后台选人
- 4、缓存行高
- 5、如果cell内现实的内容来自web,使用异步加载,缓存请求结果
- 6、使用`shadowPath`来画阴影
- 7、减少subviews的数量
- 8、尽量不适用`cellForRowAtIndexPath:`,如果你需要用到它,只用一次然后缓存结果
- 9、使用正确的数据结构来存储数据
- 10、使用`rowHeight`, `sectionFooterHeight` 和 `sectionHeaderHeight`来设定固定的高,不要请求delegate
- 21. 选择正确的数据存储选项
- Apple在一般情况下建议使用Core Data
进阶级(这些建议只应该在你确信他们可以解决问题和得心应手的情况下采用)
- 22. 加速启动时间
- 23. 使用Autorelease Pool
- 24. 选择是否缓存图片
- 常见的从bundle中加载图片的方式有两种,一个是用`imageNamed`,二是用`imageWithContentsOfFile`,第一种比较常见一点。
- 既然有两种类似的方法来实现相同的目的,那么他们之间的差别是什么呢?
- `imageNamed`的优点是当加载时会缓存图片。`imageNamed`的文档中这么说:
- 这个方法用一个指定的名字在系统缓存中查找并返回一个图片对象如果它存在的话。如果缓存中没有找到相应的图片,这个方法从指定的文档中加载然后缓存并返回这个对象。
- 相反的,`imageWithContentsOfFile`仅加载图片。
- 下面的代码说明了这两种方法的用法:
- 1
- UIImage *img = [UIImage imageNamed:@"myImage"]; // caching
- // or
- UIImage *img = [UIImage imageWithContentsOfFile:@"myImage"]; // no caching
- 那么我们应该如何选择呢?
- 如果你要加载一个大图片而且是一次性使用,那么就没必要缓存这个图片,用`imageWithContentsOfFile`足矣,这样不会浪费内存来缓存它。
- 然而,在图片反复重用的情况下`imageNamed`是一个好得多的选择。
- 25. 尽量避免日期格式转换
- 如果你可以控制你所处理的日期格式,尽量选择Unix时间戳。你可以方便地从时间戳转换到NSDate:
1
2
3
- (NSDate*)dateFromUnixTimestamp:(NSTimeInterval)timestamp {
return [NSDate dateWithTimeIntervalSince1970:timestamp];
3、iOS9的新特性,iOS8到iOS9的适配问题。
1.iOS9网络适配_ATS:改用更安全的HTTPS
2.iOS9新特性_更灵活的后台定位
3.企业级分发
4.Bitcode
5.iOS9 URL Scheme 适配_引入白名单概念
6.iPad适配Slide Over 和 Split View
7.字体间隙变大导致 UI 显示异常
8.升级 Xcode7 后的崩溃与警告
i.iOS9 下使用 Masonry 会引起崩溃的一种情况
ii.Xcode 升级后,旧的状态栏的样式设置方式会引起警告
iii.Xcode7 在 debug 状态下也生成 .dSYM 文件引起的警告
iv.Xcode7 无法使用 8.x 系统的设备调试,一运行就报错 there is an intenal API error
v.使用了 HTML 的 iframe 元素可能导致无法从 Safari 跳转至 App
vi.iOS 9锁屏控制台会打印警告
vii.Xcode7 上传应用时提示 ITMS-90535 Unable to publish iOS app with xxx SDK 的问题
9.iOS国际化问题:当前设备语言字符串返回有变化