《Effective Objective-C 2.0编写高质量iOS与OS X代码的52个方法》

《Effective Objective-C 2.0编写高质量i

2019-01-28  本文已影响0人  Mr_WangZz

37. 理解 “块” 这一概念

实例:

    /*
     
     块(block)语法:
     return_type (^block_name) (parameters)
     
     */
    //1 全局块
//    void (^someBlock)(void) = ^ {
//        NSLog(@"这是一个块");
//    };
//
//    someBlock();
    //2 带参数
//    int (^intBlock) (int a, int b) = ^(int aaa, int bbb) {
//        return aaa + bbb;
//    };
//
//    NSLog(@"%d", intBlock(900, 98));

    //3 在声明它的范围里,所有变量都可为其捕获。
    int addi = 1000;
    int (^intBlock) (int a, int b) = ^(int aaa, int bbb) {
        return aaa + bbb + addi;
    };

    NSLog(@"%d", intBlock(900, 98));

    //4 内联块
    
    NSArray *array = @[@0, @1, @2, @3, @4, @5];
    __block NSInteger count = 0;
    [array enumerateObjectsUsingBlock:^(id  _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
        /*
         NSOrderedAscending     小于
         NSOrderedSame          等于
         NSOrderedDescending    大于
         */
        if ([obj compare:@2] == NSOrderedAscending) {
            count++;
        }
    }];
    NSLog(@"%ld", (long)count);
    
    
    //self 也是对象,块在捕获它时也会将其保留,所以一般block容易产生“保留循环”

全局块、栈块及堆块

//全局块: 由于运行该块所需的全部信息 都能在编译期确定,所以可以称为“全局块”。如下
void (^someBlock)() = ^ {
    NSLog(@"这是一个块");
};
    
//    //栈块
//    void (^block) ();
//
//    if (count == 2) {
//        block = ^{
//            NSLog(@"这是一个栈块");
//        };
//    }else {
//        block = ^{
//            NSLog(@"这是一个栈块");
//        };
//    }
//
//    block();//此处却在堆。不安全
    
//改良
//堆块
void (^block) ();
    
if (count == 2) {
    block = [^{
        NSLog(@"这是一个栈块");
    } copy];
}else {
    block = [^{
        NSLog(@"这是一个栈块");
    } copy];
}
    
block();//把块复制到堆,就安全了

要点总结

38. 为常用的块类型创建 typedef

//定义
typedef void(^EOCCompletionHandler)(NSData *data, NSError *error);
//做参数。
- (void)startWithCompletionHandler:(EOCCompletionHandler)completion;

要点总结

39. 用 handle 块降低代码分散程度

块,有时可以代替代理(委托)方法

要点总结

40. 用块引用其所属对象时不要出现保留环

避免保留环的封装方法

1:
_networkFetcher = [[EOCNetworkFetcher alloc] initWithUrl:[NSURL URLWithString:@"www.baidu.com"]];
[_networkFetcher startWithCompletionHandler:^(NSData *data, NSError *error) {
   
    _fetcherData = data;
    
    //避免保留环的方法1
    _networkFetcher = nil;
    
}];

2:
/** 避免保留环的方法2 */
- (void)p_requestCompleted {
    
    if (_handler) {
        _handler(_downloadData, nil);
    }
    self.handler = nil;
}

要点总结

41. 多用派发队列,少用同步锁

.h
{
    NSString *_someString;
}

- (NSString *)someString;
- (void)setSomeString:(NSString *)someString;


/*************************************/
.m
{
    dispatch_queue_t _queue;
}
- (instancetype)init {
    if (self = [super init]) {
        //_queue = dispatch_queue_create("EOC by Wzz", nil);
        _queue = dispatch_get_global_queue(0, 0);
    }
    return self;
}


- (NSString *)someString {

    __block NSString *localSomeString;

    dispatch_sync(_queue, ^{
        localSomeString = _someString;
    });

    return localSomeString;
}


- (void)setSomeString:(NSString *)someString {
    dispatch_barrier_async(_queue, ^{
//        [NSThread sleepForTimeInterval:3.0f];
        _someString = someString;
    });
    
}

要点总结

42. 多用GCD,少用 performSelector 系列方法

要点总结

43. 掌握GCD及操作队列的使用时机

使用 NSOperation 及 NSOperationQueue 的好处:

要点总结:

44. 通过Dispatch Group机制,根据系统资源状况来执行任务

要点总结:

45. 使用dispatch_once来执行只需执行一次的线程安全代码

要点总结

只需执行一次的线程安全代码: thread-safe single-code execution

46. 不要使用 dispatch_get_current_queue

要点总结

系列文章

上一篇下一篇

猜你喜欢

热点阅读