一、循環(huán)引用
1.第一種方式 weak+strong(最常用)
- (void)one{
__weak typeof(self) weakSelf = self;
self.block = ^{
__strong typeof(self) strongSelf = weakSelf;
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@",strongSelf.name); // self - nil name - nil
});
};
self.block();
}
2.第二種方式__block
- (void)two{
__block ViewController *vc = self; // vc 結(jié)構(gòu)體
self.block = ^{
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@",vc.name); // self - nil name - nil
vc = nil;
});
};
self.block();
}
3.第三種方式 傳參(效率最高)
self.blockVc = ^(ViewController *vc){
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(2 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
NSLog(@"%@",vc.name); // self - nil name - nil
});
};
self.blockVc(self);
二、強(qiáng)引用
- (void)initTimer {
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self.target selector:@selector(timerSel) userInfo:nil repeats:YES];
}
- (void)timerSel{
num++;
NSLog(@"num----> %d",num);
}
因?yàn)閞unloop -> timer -> target -> self 造成了強(qiáng)引用
1.簡陋的解決
-(void)viewWillDisappear:(BOOL)animated {
[self.timer invalidate];
self.timer = nil;
}
2.好一點(diǎn)的方式,但是不夠靈活
-(void)didMoveToParentViewController:(UIViewController *)parent{
if (parent == nil) {
[self.timer invalidate];
self.timer = nil;
}
NSLog(@"結(jié)束");
}
3.中間層
定義一個(gè)中間層
@interface YHTimerWapper : NSObject
- (instancetype)yh_initWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
- (void)yh_invalidate;
@end
@interface YHTimerWapper()
@property (nonatomic, weak) id target;
@property (nonatomic, assign) SEL aSelector;
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation YHTimerWapper
- (instancetype)yh_initWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo{
if (self == [super init]) {
self.target = aTarget;
self.aSelector = aSelector;
self.timer = [NSTimer scheduledTimerWithTimeInterval:ti target:self selector:@selector(timerSel) userInfo:userInfo repeats:yesOrNo];
}
return self;
}
- (void)timerSel{
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
// 讓編譯器出棧偷遗,恢復(fù)狀態(tài),繼續(xù)編譯后續(xù)的代碼兰吟!
if ([self.target respondsToSelector:self.aSelector]) {
[self.target performSelector:self.aSelector];
}
#pragma clang diagnostic pop
}
- (void)yh_invalidate{
[self.timer invalidate];
self.timer = nil;
}
使用
- (void)viewDidLoad {
[super viewDidLoad];
//中間層(RACKVOWapper)
// self -> timerWapper(在self的dealloc方法斷開) <-> timer <- runloop
self.timerWapper = [[YHTimerWapper alloc] yh_initWithTimeInterval:1 target:self selector:@selector(timerSel) userInfo:nil repeats:YES];
}
- (void)dealloc{
[self.timerWapper lg_invalidate];
}
4.使用block
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 repeats:YES block:^(NSTimer * _Nonnull timer) {
NSLog(@"num ");
}];
- (void)dealloc{
[self.timer invalidate];
self.timer = nil;
}
- NSProxy
是跟NSObject同級(jí)的類觅廓,加載迅速,消息轉(zhuǎn)發(fā)形式更加清晰
@interface YHProxy : NSProxy
+ (instancetype)proxyWithTransformObject:(id)object;
@end
@interface YHProxy()
@property (nonatomic, weak) id object;
@end
@implementation YHProxy
+ (instancetype)proxyWithTransformObject:(id)object{
YHProxy *proxy = [YHProxy alloc];
proxy.object = object;
return proxy;
}
// sel - imp -
// 消息轉(zhuǎn)發(fā) self.object
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel{
return [self.object methodSignatureForSelector:sel];
}
- (void)forwardInvocation:(NSInvocation *)invocation{
if (self.object) {
[invocation invokeWithTarget:self.object];
}
}
@end
使用
self.proxy = [YHProxy proxyWithTransformObject:self];
self.timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self.proxy selector:@selector(timerSel) userInfo:nil repeats:YES];
三服鹅、內(nèi)存泄漏檢查方式
1凳兵、靜態(tài)分析Analyze
2、instrument
3企软、MLeaksFinder(更方便)
4庐扫、dealloc
四、啟動(dòng)時(shí)間
- 啟動(dòng)分為2種: 冷啟動(dòng)和熱啟動(dòng)
- 啟動(dòng)的時(shí)間分為兩部分:main函數(shù)執(zhí)行之前、main函數(shù)?應(yīng)用啟動(dòng)完成
啟動(dòng)優(yōu)化建議
main函數(shù)之前
減少動(dòng)態(tài)庫形庭、合并一些動(dòng)態(tài)庫
減少Objc類铅辞、分類的數(shù)量、減少Selector數(shù)量
main函數(shù)?應(yīng)用啟動(dòng)完成
耗時(shí)操作碘勉,不要放在finishLaunching方法中動(dòng)態(tài)庫對(duì)啟動(dòng)時(shí)間的影響測試
iOS Dynamic Framework 對(duì)App啟動(dòng)時(shí)間影響實(shí)測
五巷挥、應(yīng)用瘦身
LinkMap查看文件大小
LSUnusedResources 查看未使用的文件
六、渲染
YYFpsLabel檢查渲染
異步渲染
七验靡、網(wǎng)絡(luò)層
防止多次重復(fù)請(qǐng)求