1.性能优化相关
instruments的使用
dSYM内存地址解析 对象啥名字
图像性能
减少view个数
减少使用opacity,半透明效果,或者不要把半透明加载一个变化的view上,因为不仅底层要更新,半透明效果也要更新。
栅格化restresize == true; cache它的layer bitmap那个图 下次就不用重绘了
offscreen-rendered离屏渲染
autolayout和绝对布局性能的插笔鹅仔view小于400subview基本忽略不计
轻量化住线程:图片预加载、coretext
性能优化重点:缓存 一般动画会消耗gpu(CoreAnimation OpenGL)多点cpu(CGGraghic)
imageNamed主线程占用挺高的
滑动30针就问题不大了 否则就要优化了
uikit的坐标系和CGContext是不一样的 一个原点在左上角 一个原点在左下角,所以就涉及到坐标转换。 矩阵变换。
一个文字是CTRun baseline 上部asent下部decent
缓存 空间换时间
性能优化 减少住线程任务 预加载
tableview享元模式
while(condition){
......
condition = 0;
}
线程交给runloop去做
SDWebImage 同一地址内容改变了 可以用图片md5加密做key。
imageNamed会自动给你cache 内存会升的比较快
autoreleasepool 延迟释放MRC retainCount == 0但没释放
系统的autor
runloop会创建一个 main函数的主runloop会创建一个 touch event时间循环 线程 结束的时候会销毁
文本太大 分段加载 类似tableview 线程 有线程栈 有大小 2m的话 内存/2就是最多创建的线程数
xib有磁盘加载到内存的过程 所以纯代码性能会比较好
内存的速度是磁盘的100倍+
2.下拉上拉刷新
//当你被添加到superView的时候或者从superView上移除的时候,都会调用willMoveToSuperview方法 (添加参数有值 移除没有)
- (void)willMoveToSuperview:(UIView *)newSuperview
if (self.scrollView.dragging) { //正在拖动的过程中
//注意:获取bundle里的图片方法
_arrowImageView =
[[UIImageView alloc] initWithImage:[UIImage imageWithContentsOfFile:[[NSBundle bundleWithPath:[[NSBundle mainBundle] pathForResource:@"MJRefresh" ofType:@"bundle"]] pathForResource:@"arrow@2x" ofType:@"png"]]];
_arrowImageView.tintColor = self.descriptionLable.textColor;
- (void)setPullingPercent:(CGFloat)pullingPercent {
[super setPullingPercent:pullingPercent];
NSArray *images = self.stateImages[@(EOCRefreshStateIdle)];
if (self.state != EOCRefreshStateIdle || images.count == 0) return;
// 停止动画
[self.gifImageView stopAnimating];
// 设置当前需要显示的图片
NSUInteger index = images.count * pullingPercent;
if (index >= images.count) index = images.count - 1;
self.gifImageView.image = images[index];
}
- (void)setState:(EOCRefreshState)state {
[super setState:state];
if (state == EOCRefreshStateRefreshing || state == EOCRefreshStatePulling) {
_gifImageView.animationImages = _stateImages[@(EOCRefreshStateRefreshing)];
_gifImageView.animationDuration = [_stateAnimationDurations[@(EOCRefreshStateRefreshing)] doubleValue];
[_gifImageView startAnimating];
} else if (state == EOCRefreshStateIdle) {
[_gifImageView stopAnimating];
}
}
0.框架要考虑三点
1.分层结构
2。可用性-》分类 初始化的实现-〉每一个方法
3.baseview:prepare方法(做准备工作) ->placeSubviews(修改子view的布局)-> viewWillMoveToSuperView来设置kvo之类的->kvo的监听方法(根据偏移量设置状态)->根据不同状态进行操作
上次刷新时间用NSUserdefault可以存 上次结束的时候存入(会造成多个tableview之间时间的混乱)
每个像素4个字节 动画用图片数组实现
backFooter AutoFooter
contentSize viewDidLoad里面不行 viewDidAppear里面可以 因为tableview的contentSize要数据都弄出来才确定
contentSize不准确 可以监听 一改变就重新赋值
self.originalInsets = self.scrollView.eoc_inset; //经验之谈:如果是你自己手动设置的contentInset,那么设置好了,立马就能够或得到这个值;如果是系统来给你提供的,比如naviagationController和scrollView结合导致的偏移,这个contentInset,就需要选择时机来获得了
///iOS 11 scrollView的contentInset
//adjustContentInsets = contentInset + safeAreaContentInsets
- (UIEdgeInsets)eoc_inset {
UIEdgeInsets insets = self.contentInset;
if (@available(iOS 11, *)) {
insets = self.adjustedContentInset;
}
return insets;
}
- (void)setEoc_insetT:(CGFloat)eoc_insetT
{
//右边是不是等于adjustContentInsets:safeAreaInset+contentInset
UIEdgeInsets inset = self.contentInset;
inset.top = eoc_insetT;
if (@available(iOS 11, *)) {
inset.top -= self.safeAreaInsets.top;
}
self.contentInset = inset;
}
self.view
self.window为nil说明还没有添加到界面上来 还没有添加进去
viewDidLoad里面view还没有添加到window上面self.view.superView == nil
2.本地数据储存
1.沙盒
2.bundle
3.归档KeyedArchiver
4.keychain
-->沙盒
NSString *filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSLog(@"%@", filePath);
documents {
大文件尽量不要存储在这个目录下(视频文件)如果不做任何处理,审核,检查出来,就被拒,
如果不想被拒 1 文件非备份操作设置 2 大文件转移目录
默认是备份的
}
#import <sys/xattr.h>
//非备份操作
- (BOOL)addSkipBackupAttributeToItemAtURL:(NSURL*)URL
{
const char* filePath = [[URL path] fileSystemRepresentation];
const char* attrName = "com.apple.MobileBackup";
u_int8_t attrValue = 1;
int result = setxattr(filePath, attrName, &attrValue, sizeof(attrValue), 0, 0);
return result == 0;
}
Library {
Caches 缓存 非备份
Preferences(默认是备份)(plist文件 NSUserDefaults)
}
默认的网络请求是有缓存的 保存在cache里
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[[NSUserDefaults standardUserDefaults] setObject:@"3" forKey:@"tow"];
[[NSUserDefaults standardUserDefaults] synchronize];//提交 防止文件还没写进去就有地方开始读了无数据
}
tmp(临时)
// app功能 清除缓存的功能 (1系统的文件, 2 自己创建)
大文件可以存放在document下并设置非备份 或者放在libraray的cache或者自己创一个
=======
boundle 资源, 不参与编译
黄色/蓝色(蓝色资源文件夹,不参与编译)
======
获取bundle内的图片
_imageView.image = [UIImage imageNamed:@"EOCBundle.bundle/11.png"];
// 用代码取路径
NSString *boudlePath = [[NSBundle mainBundle] pathForResource:@"EOCBundle" ofType:@"bundle"];
NSBundle *eocBoundle = [NSBundle bundleWithPath:boudlePath];
NSString *imagePath = [eocBoundle pathForResource:@"11" ofType:@"png"];
_imageView.image = [UIImage imageWithContentsOfFile:imagePath];
归档 遵循NSCoding协议。 加密解密
//归档 类似于编码
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeObject:self.age forKey:@"age"];
}
//解 读出来 生成一个对象
- (instancetype)initWithCoder:(NSCoder *)aDecoder{
EOCClass *eocClass = [EOCClass new];
eocClass.name = [aDecoder decodeObjectForKey:@"name"];
eocClass.age = [aDecoder decodeObjectForKey:@"age"];
return eocClass;
}
- (void)saveObject{
EOCClass *eocClass = [EOCClass new];
eocClass.name = @"eocClass";
eocClass.age = @"11";
//
NSData *eocData = [NSKeyedArchiver archivedDataWithRootObject:eocClass];
NSLog(@"data数据::%s", [eocData bytes]);
NSString *filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
filePath = [filePath stringByAppendingPathComponent:@"eocClass"];
[eocData writeToFile:filePath atomically:YES];
}
- (void)getObject{
NSString *filePath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
filePath = [filePath stringByAppendingPathComponent:@"eocClass"];
EOCClass *eocClass = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"%@, %@", eocClass.name, eocClass.age);
EOCClass *eocClassTwo = [eocClass copy];
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
[self getObject];
}
对象要考呗的话需要实现NSCopying协议
//// copy
- (id)copyWithZone:(nullable NSZone *)zone{
EOCClass *eocClass = [EOCClass new];
eocClass.name = self.name;
eocClass.age = self.age;
return eocClass;
}
网友评论