为什么在避免块保留周期时使用typeof()而不是对象类型?

ede*_*y05 4 objective-c

当其他ObjC开发人员打破保留周期时,我经常看到这段代码片段.

__weak typeof(self) weakSelf = self;
[someObject doThingWithCompletion:^{
    typeof(weakSelf) strongSelf = weakSelf;
    [strongSelf awesomeThingOne];
    [strongSelf moreAwesome];
}];
Run Code Online (Sandbox Code Playgroud)

为什么要使用typeof()宏?这是块的独特之处吗?

我最初的想法是,self类型可能不知道(这似乎大多不可能,但让我们假装......).如果类型是未知的,那么为什么不宣布weakSelfid:__weak id weakSelf = self;

我的第二个想法是它对子类化的防御,但这似乎不太可能导致问题.假设ObjTwo子类AwesomeObj并覆盖该awesomeThingOne方法.如果selfObjTwo或的实例,上面的假代码应该可以正常工作AwesomeObj.

nhg*_*rif 7

typeof()宏允许的几件事情.

首先,就个人而言,我已经创建了一个包含这类内容的代码片段.而不必输入:

__weak MyClass *weakSelf = self;
Run Code Online (Sandbox Code Playgroud)

每次我想要设置它,替换MyClass相应的类,我只能开始输入weakSelf,Xcode的自动完成将尝试提供我的这行代码:

__weak typeof(self) weakSelf = self;
Run Code Online (Sandbox Code Playgroud)

这种情况每次都有效.


另外,typeof()如果我们改变实际类型,using 会给我们一个显式类型并最小化要重写的代码.

id是不安全的,它不会让我们自动完成可用的方法和属性.毕竟,weakSelf现在是类型id而不是类型MyClass.

我们可以遇到与子类相同的问题,如果我只是默认MyClass,执行:

weak MyClass *weakSelf = self;
Run Code Online (Sandbox Code Playgroud)

不会给我自动填充实际MySubClass添加的方法/属性.selfMySubClass


并且使用typeof()并不仅限于块.我喜欢typeof()在类方法中使用.

通常,以下就足够了:

+ (instancetype)myInstance {
    return [[self alloc] init];
}
Run Code Online (Sandbox Code Playgroud)

作为instancetype[self alloc]负责获得正确的子类.

但是假设我们想要更复杂的东西:

+ (NSMutableArray *)arrayOfInstances;
Run Code Online (Sandbox Code Playgroud)

我们如何确保我们插入阵列的对象是正确的类型?

+ (NSMutableArray *)arrayOfInstances {
    NSMutableArray *instances = [NSMutableArray array];

    for (int i = 0; i < 10; ++i) {
        typeof([self alloc]) newObj = [[self alloc] init];
        newObj.someIntProperty = i;
        [instances addObject:newObj];
    }

    return instances;
}
Run Code Online (Sandbox Code Playgroud)

我们不想将其id用作类型newObj.我们想确定如果我们打电话:

[MyClass arrayOfInstances];
Run Code Online (Sandbox Code Playgroud)

我们得到一个MyClass对象数组,但如果我们调用:

[MySubClass arrayOfInstances];
Run Code Online (Sandbox Code Playgroud)

我们得到了一系列MySubClass对象等.


typeof()如果我们想要从定义我们对象的字典中实例化一个对象,我们也可以使用它们:

Class dynamicType = myDict[@"Class"];
typeof([dynamicType alloc]) myObject = [[dynamicType alloc] init];
myObject.foo = myDict[@"Foo"];
myObject.bar = myDict[@"Bar"];
Run Code Online (Sandbox Code Playgroud)