[iOS] __weak 和 WKWebView 在 relea

2018-11-08  本文已影响17人  BudSwift

__weak

因为在业务开发中的需求需要几个局部变量,考虑到:

先定义对象 XRow 的基本信息,内部有一个字典,用于保存 block 。

static NSString *const kBlockKey = @"kBlockKey";
@interface XRow : NSObject
@property (nonatomic, strong) NSMutableDictionary *value;
@end

@implementation XRow
- (NSMutableDictionary *)value {
    if (!_value) {
        _value = [NSMutableDictionary dictionaryWithCapacity:1];
    }
    
    return _value;
}

- (void)dealloc {
    NSLog(@"dealloc %@", self);
}

@end

接着定义测试的逻辑:

示例代码分三种情况测试如下:

@interface ViewController ()
@property (nonatomic, strong) NSMutableArray *array;
@end

@implementation ViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self test__block__weak_1];
    NSLog(@"tested");
}

- (void)testAssignWeak {
    __weak id obj = nil;
    __weak id obj2 = nil;
    __weak id obj3 = nil;
    obj = [self makeRow];
    obj2 = [self makeRow];
    obj3 = [[XRow alloc] init]; // 直接收到编译器警告
    NSLog(@"obj %@", obj);
    NSLog(@"obj2 %@", obj2);
}

- (void)test__block__weak_1 {
    __block __weak XRow *row1 = nil;
    __block __weak XRow *row2 = nil;
    
    void(^block)(void) = ^{
        // 处理 row1 row2 的一些逻辑
        NSLog(@"row1 %@ row2 %@", row1, row2);
    };
    
    row1 = [self makeRow];
    row1.value[kBlockKey] = block;
    
    row2 = [self makeRow];
    row2.value[kBlockKey] = block;
    
    [self.array addObject:row1];
    [self.array addObject:row2];
    NSLog(@"array -> %@", self.array);
}

- (void)test__block__weak_2 {
    __block XRow *row1 = nil;
    __block XRow *row2 = nil;
    
    // 这样 处理 在 block 内部是 nil,没有 __block 效果
    __weak typeof(XRow *) weakRow1 = row1;
    __weak typeof(XRow *) weakRow2 = row2;
    void(^block)(void) = ^{
        // 处理 row1 row2 的一些逻辑
        NSLog(@"row1 %@ row2 %@", weakRow1, weakRow2);
    };
    
    row1 = [self makeRow];
    row1.value[kBlockKey] = block;
    
    row2 = [self makeRow];
    row2.value[kBlockKey] = block;
    
    [self.array addObject:row1];
    [self.array addObject:row2];
    NSLog(@"array -> %@", self.array);
}

- (XRow *)makeRow {
    return [[XRow alloc] init];
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
    NSLog(@"touch to excute");
    for (XRow *some in self.array) {
        void(^block)(void) = some.value[kBlockKey];
        if (block) block();
    }
    [self.array removeAllObjects];
    NSLog(@"removed");
}

- (NSMutableArray *)array {
    if (!_array) {
        _array = [NSMutableArray arrayWithCapacity:2];
    }
    
    return _array;
}

@end

可以发现:

- (void)test__block__weak_3 {
    __block __weak XRow *row1 = nil;
    __block __weak XRow *row2 = nil;
    
    void(^block)(void) = ^{
        // 处理 row1 row2 的一些逻辑
        NSLog(@"row1 %@ row2 %@", row1, row2);
    };
    
    XRow *strong = nil;
    strong = [self makeRow];
    row1 = strong;
    row1.value[kBlockKey] = block;
    [self.array addObject:row1];
    // 使用一个强引用的局部变量
    //并在下一步失去 strong 的强引用之前立即装入数组进行强引用。
    
    strong = [self makeRow];
    row2 = strong;
    [self.array addObject:row2];
    row2.value[kBlockKey] = block;
    
    NSLog(@"array -> %@", self.array);
}

WKWebView

再基于 WKWebView 封装的控制器中,为 WebView 加载了一个自定义了 Post 请求体的 NSURLRequest 对象,这是接入一个第三方支付 URL 的场景,接入完成后,在 debug 模式下 各个系统和设备运行良好,但是在 release 模式下,iOS 8/9/10 的设备显示空白,提示错误

WKErrorDomain code 102 帧框加载失败

这种情况很可能是请求体传输不完整导致的,但是针对不同系统的差异原因在哪里,暂时无法直接解决。
间接的解决方法,使用 UIWebView,是的,使用 UIWebView 在 debug/ release 下均表现正常。

小结

不论怎么样,给测试同学的包一定要给 release 的,有些情况即便没有手动判断是否 DEBUG 宏也会表现异常,测试同学发现了异常的情况要引起重视。

PS:关于在 Xcode 切换 debug / release

上一篇下一篇

猜你喜欢

热点阅读