1.子類初始化方法調(diào)用父類的副初始化方法---死循環(huán)
//代碼說明:Father繼承自NSObject,Children繼承自Father,在執(zhí)行了控制器MyVC中的代碼后,會(huì)發(fā)生什么?
@implementation Father
- (instancetype)initWithUrl:(NSString *)url title:(NSString *)title{
if (self = [super init]) {
NSLog(@"父111111111");
}
NSLog(@"父2222222222");
return self;
}
- (instancetype)initWithUrl:(NSString *)url{
NSLog(@"父333333333333");
return [self initWithUrl:url title:nil];
}
@implementation Children
- (instancetype)initWithUrl:(NSString *)url title:(NSString *)title{
if (self = [super initWithUrl:url]) {
NSLog(@"子44444444444");
}
NSLog(@"子5555555555");
return self;
}
@implementation MyVC
- (void)viewDidLoad {
[super viewDidLoad];
self.view.backgroundColor = [UIColor whiteColor];
Children *child = [[Children alloc]initWithUrl:@"http://www.baidu.com" title:@"標(biāo)題"];
}
// 代碼會(huì)按照:Children:[super initWithUrl:url] ---> Father: initWithUrl 這個(gè)順序循環(huán)執(zhí)行,不停打印“父333333333333”;
2.在dealloc方法中,將self作為參數(shù)傳遞出去----Crash
-(void)dealloc{
[self unsafeMethod:self];
// 因?yàn)楫?dāng)前已經(jīng)在self這個(gè)指針?biāo)赶虻膶?duì)象的銷毀階段,銷毀self所指向的對(duì)象已經(jīng)在所難免。如果在unsafeMethod:中把self放到了autorelease poll中,那么self會(huì)被retain住,計(jì)劃下個(gè)runloop周期在進(jìn)行銷毀。但是dealloc運(yùn)行結(jié)束后,self所指向的對(duì)象的內(nèi)存空間就直接被回收了,但是self這個(gè)指針還沒有銷毀(即沒有被置為nil),導(dǎo)致self變成了一個(gè)名副其實(shí)的野指針。
// 到了下一個(gè)runloop周期,因?yàn)閟elf所指向的對(duì)象已經(jīng)被銷毀,會(huì)因?yàn)榉欠ㄔL問而造成crash問題。
}
3.ios8及更早的版本中 通知的處理 可能導(dǎo)致Crash
//NSNotificationCenter在iOS8及更老的系統(tǒng)有一個(gè)多線程bug,selector執(zhí)行到一半可能會(huì)因?yàn)閟elf的銷毀而引起crash,解決的方案是在selector中使用weak_strong_dance。
- (void)onMultiThreadNotificationTrigged:(NSNotification *)notify {
__weak typeof(self) wself = self;
__strong typeof(self) sself = wself;
if (!sself) { return; }
[self doSomething];
}
4.官方推薦的一些規(guī)范
1.如果想要獲取window,不要使用view.window獲取。請(qǐng)使用[[UIApplication sharedApplication] keyWindow]。
2.在使用到 UIScrollView,UITableView,UICollectionView 的 Class 中,需要在 dealloc 方法里手動(dòng)的把對(duì)應(yīng)的 delegate, dataSouce 置為 nil。
3.UITableView使用self-sizing實(shí)現(xiàn)不等高cell時(shí),請(qǐng)?jiān)?cellForRowAtIndexPath: 中給cell設(shè)置數(shù)據(jù)。不要在 willDisplayCell: forRowAtIndexPath: 方法中給cell設(shè)置數(shù)據(jù)。
4.當(dāng)訪問一個(gè) CGRect 的 x, y, width, height 時(shí),應(yīng)該使用CGGeometry 函數(shù)代替直接訪問結(jié)構(gòu)體成員。
CGRect frame = self.view.frame;
CGFloat x = CGRectGetMinX(frame);
CGFloat y = CGRectGetMinY(frame);
CGFloat width = CGRectGetWidth(frame);
CGFloat height = CGRectGetHeight(frame);
反對(duì)這樣的寫法:
CGFloat x = frame.origin.x;
CGFloat y = frame.origin.y;
CGFloat width = frame.size.width;
CGFloat height = frame.size.height;