11.避免导致循环引用,通知,timer,KVO的及时remove
timer避免的方式是用GCD定时器。
1.UITableViewCells,UICollectionViewCells。甚至是UITableViewHeaderFooterViews设置正确的reuseIdentifier。
使用rowHeight, sectionFooterHeight和 sectionHeaderHeight来设定固定的高,不要请求delegate
2.假设你不得不XIB的话。使他们尽量简单。尝试为每一个Controller配置一个单独的XIB,尽可能把一个ViewController的view层次结构分散到单独的XIB中去。
须要注意的是,当你载入一个XIB的时候全部内容都被放在了内存里,包含不论什么图片。假设有一个不会即刻用到的view,你这就是在浪费宝贵的内存资源了。Storyboards就是还有一码事儿了。storyboard仅在须要时实例化一个viewcontroller.
3.不要堵塞主线程,应该尽量避免将其他处理放在主线程中,特别复杂的数据计算和网络请求等.
4.image相关
在Image Views中调整图片大小
假设要在UIImageView
中显示一个来自bundle的图片,你应保证图片的大小和UIImageView的大小同样。在执行中缩放图片是非常耗费资源的,特别是UIImageView
嵌套在UIScrollView
中的情况下。
对比opengles: 图片展示本质(解压缩)
CGContextRef spriteContext = CGBitmapContextCreate(spriteData, width, height, 8, width*4,CGImageGetColorSpace(spriteImage), kCGImageAlphaPremultipliedLast);
在CGContextRef上--> 将图片绘制出来
CGImageRef spriteImage = [UIImage imageNamed:fileName].CGImage;
CGContextDrawImage 使用的是Core Graphics框架,坐标系与UIKit 不一样。UIKit框架的原点在屏幕的左上角,Core Graphics框架的原点在屏幕的左下角。
CGContextDrawImage
参数1:绘图上下文
参数2:rect坐标
参数3:绘制的图片
CGRect rect = CGRectMake(0, 0, width, height);
使用默认方式绘制
CGContextDrawImage(spriteContext, rect, spriteImage);
选择是否缓存图片
UIImage *img = [UIImage imageNamed:@"myImage"];// caching
UIImage *img = [UIImage imageWithContentsOfFile:@"myImage"];// no caching
SDImage对图片的加载时候存本地,根据不同的情况判断
5.懒加载
6.动画尽量在layer上实现,渲染图片 opengl、metal的方式实现。
CALayer是图层,和界面展示相关
1.UIView相比CALayer最大的区别是UIView继承NSResponse,可以响应用户事件,而CALayer继承与NSObject不可以响应用户的响应事件。
2.UIView侧重对于显示内容的管理,CALayer侧重于对内容的绘制。
3.UIView和CALayer是相互依赖的关系。UIView的显示依赖于CALayer提供的内容。CALayer依赖UIView的容器来显示绘制的内用。
4.UIView来自CALayer,高于CALayer,是CALayer的高层实现与封装。UIView的所有特性来源于CALayer的支持。
7.处理内存警告
· 在app delegate中使用applicationDidReceiveMemoryWarning:
的方法
· 在你的自己定义UIViewController的子类(subclass)中覆盖didReceiveMemoryWarning
· 注冊并接收UIApplicationDidReceiveMemoryWarningNotification 的通知
8.比方NSDateFormatter和NSCalendar。须要重用他们 设置一个单例(设置属性很费性能相当于新建一个)。减少日期的转换。
@property (nonatomic, strong) NSDateFormatter *formatter;
- (NSDateFormatter *)formatter {
if(! _formatter) {
_formatter = [[NSDateFormatter alloc] init];
_formatter.dateFormat = @"EEE MMM dd HH:mm:ss Z yyyy";// twitter date format
}
return_formatter;
}
9. 降低使用Web特性
10. 选择正确的数据存储方式
Documents:保存应用运行时生成的需要持久化的数据,iTunes同步设备时** 会 备份该目录。例如,游戏应用可将游戏存档保存在该目录
tmp:保存应用运行时所需的临时数据,使用完毕后再将相应的文件从该目录删除。应用没有运行时,系统也可能会清除该目录下的文件。iTunes同步设备时 不会 备份该目录
Library/Caches:保存应用运行时生成的需要持久化的数据,iTunes同步设备时 不会 备份该目录。一般存储体积大、不需要备份的非重要数据
Library/Preference:保存应用的所有偏好设置,iOS的Settings(设置)应用 会 *在该目录中查找应用的设置信息。iTunes同步设备时 会 *备份该目录
NSUserDefaults(偏好设置是专门用来保存应用程序的配置信息的)
之前碰到个坑就是从服务器拿到数据部分用这种方式存储,服务器返回NSNull,我们这边也没有model层转,就直接存储了,导致app卡掉但并没有闪退之类,就是线程卡死的情况
plist(属性列表)
NSKeyedArchiver(对象归档)
需要实现copy协议
只有遵守了NSCoding或 NSSecureCoding(更为安全的归档协议)协议,并且实现了协议里归档与解归档的方法的的类创建的对象才能够进行归档
最好也实现以下NSCopying,NSCopying与NSCoding一起实现好处在于允许复制对象,使用数据模型对象时有较大的灵活性
iOS的嵌入式关系数据库SQLite3(FMDB - 表格形式)
// 获得Documents目录路径
NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
// 文件路径
NSString *filePath = [documentsPath stringByAppendingPathComponent:@"model.sqlite"];
// 实例化FMDataBase对象
_db = [FMDatabase databaseWithPath:filePath];
[_db open];
// 初始化数据表
NSString *personSql = @"CREATE TABLE 'person' ('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,'person_id' VARCHAR(255),'person_name' VARCHAR(255),'person_age' VARCHAR(255),'person_number'VARCHAR(255)) ";
NSString *carSql = @"CREATE TABLE 'car' ('id' INTEGER PRIMARY KEY AUTOINCREMENT NOT NULL ,'own_id' VARCHAR(255),'car_id' VARCHAR(255),'car_brand' VARCHAR(255),'car_price'VARCHAR(255)) ";
[_db executeUpdate:personSql];
[_db executeUpdate:carSql];
[_db executeUpdate:@"INSERT INTO person(person_id,person_name,person_age,person_number)VALUES(?,?,?,?)",maxID,person.name,@(person.age),@(person.number)];
[_db executeUpdate:@"DELETE FROM person WHERE person_id = ?",person.ID];
[_db executeUpdate:@"UPDATE 'person' SET person_name = ? WHERE person_id = ? ",person.name,person.ID];
[_db executeQuery:[NSString stringWithFormat:@"SELECT * FROM car where own_id = %@",person.ID]];
[_db close];