代码不规范容易造成的bug

1.子类初始化方法调用父类的副初始化方法---死循环

//代码说明:Father继承自NSObject,Children继承自Father,在执行了控制器MyVC中的代码后,会发生什么?

@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:@"标题"];
    }

// 代码会按照:Children:[super initWithUrl:url] ---> Father: initWithUrl  这个顺序循环执行,不停打印“父333333333333”;

2.在dealloc方法中,将self作为参数传递出去----Crash

-(void)dealloc{
    [self unsafeMethod:self];
    // 因为当前已经在self这个指针所指向的对象的销毁阶段,销毁self所指向的对象已经在所难免。如果在unsafeMethod:中把self放到了autorelease poll中,那么self会被retain住,计划下个runloop周期在进行销毁。但是dealloc运行结束后,self所指向的对象的内存空间就直接被回收了,但是self这个指针还没有销毁(即没有被置为nil),导致self变成了一个名副其实的野指针。
    // 到了下一个runloop周期,因为self所指向的对象已经被销毁,会因为非法访问而造成crash问题。
}

3.ios8及更早的版本中 通知的处理 可能导致Crash

//NSNotificationCenter在iOS8及更老的系统有一个多线程bug,selector执行到一半可能会因为self的销毁而引起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.官方推荐的一些规范

1.如果想要获取window,不要使用view.window获取。请使用[[UIApplication sharedApplication] keyWindow]。

2.在使用到 UIScrollView,UITableView,UICollectionView 的 Class 中,需要在 dealloc 方法里手动的把对应的 delegate, dataSouce 置为 nil。

3.UITableView使用self-sizing实现不等高cell时,请在 cellForRowAtIndexPath: 中给cell设置数据。不要在 willDisplayCell:  forRowAtIndexPath: 方法中给cell设置数据。

4.当访问一个 CGRect 的 x, y, width, height 时,应该使用CGGeometry 函数代替直接访问结构体成员。
CGRect frame = self.view.frame;
CGFloat x = CGRectGetMinX(frame);
CGFloat y = CGRectGetMinY(frame);
CGFloat width = CGRectGetWidth(frame);
CGFloat height = CGRectGetHeight(frame);

反对这样的写法:
CGFloat x = frame.origin.x;
CGFloat y = frame.origin.y;
CGFloat width = frame.size.width;
CGFloat height = frame.size.height;


你可能感兴趣的:(代码不规范容易造成的bug)