NSError **的一个小知识点

272 阅读1分钟
- (void)testUserName:(NSString *)username error:(NSError **)error {
    if (!username) {
        *error = [NSError errorWithDomain: NSURLErrorDomain code: -2000 userInfo: nil];
        return;
    }
    *error = nil;
    ...
}

静态分析代码时发现了一个提示 Potential null dereference. According to coding standards in 'Creating and Returning NSError Objects' the parameter may be null

如果 error = nil, *error 不应该也是 nil,对它赋值好像没啥问题哦

我们使用的时候 error 参数可能传 &error, 也可能传 nil

第一种使用方法

- (void)test {
    NSError *error;
    [self testUserName:nil error:&error];
    if (error) {
        
    }
}

第二种使用方法

- (void)testError1 {
    [self testUserName:nil error:nil];
}

- (void)testError2 {
    [self testUserName:@"Jack" error:nil];
}

其实第二种会直接崩溃。

崩溃原因是什么呢?

通过断点我们发现 error = nil 时, &error 却不是 nil, 打印*error 直接报错不能读取它的内存,所以对*error赋值会崩溃

(lldb) p error

(NSError *) nil

(lldb) p &error

(NSError **) 0x000000016ae550c8

(lldb) p *error

error: Couldn't apply expression side effects : Couldn't dematerialize a result variable: couldn't read its memory

所以我们在赋值 error 时需要判断是否为空,完整代码如下:

- (void)testUserName:(NSString *)username error:(NSError **)error {
    if (!username) {
        if (error != NULL) {
            *error = [NSError errorWithDomain: NSURLErrorDomain code: -2000 userInfo: nil];
        }
        return;
    }
    
    if (error != NULL) {
       *error = nil;
    }
    ...
}

其他文章

NSError ** 与 throws 的三个问题