为什么在避免块保留循环时使用 typeof() 而不是对象类型? [英] Why use typeof() instead of the object type when avoiding block retain cycles?

查看:54
本文介绍了为什么在避免块保留循环时使用 typeof() 而不是对象类型?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

I have seen this code snippet frequently when other ObjC developer are breaking a retain cycle.

__weak typeof(self) weakSelf = self;
[someObject doThingWithCompletion:^{
    typeof(weakSelf) strongSelf = weakSelf;
    [strongSelf awesomeThingOne];
    [strongSelf moreAwesome];
}];

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

Why the use of the typeof() macro? Is this unique to blocks?

我最初的想法是 self 的类型可能未知(这似乎几乎不可能,但让我们假装......).如果类型未知,那么为什么不使用 id 声明 weakSelf:__weak id weakSelf = self;?

My initial thought is that self's type might not be known (that seems mostly impossible, but let's pretend...). If the type is unknown, then why not declare weakSelf with an id: __weak id weakSelf = self;?

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

My second thought is that it's defensive against subclassing, but that seems unlikely to cause an issue. Assume ObjTwo subclasses AwesomeObj and overrides the awesomeThingOne method. The fake code above should work just fine if self is an instance of ObjTwo or AwesomeObj.

推荐答案

typeof() 宏允许一些事情.

首先,就我个人而言,我已经用这种东西创建了一个代码片段.而不是必须输入:

First of all, personally, I've created a code snippet with this sort of thing. Instead of having to type out:

__weak MyClass *weakSelf = self;

每次我想设置它时,将 MyClass 替换为适当的类,我可以开始输入 weakSelf 并且 Xcode 的自动完成将尝试提供我的这行代码:

each and every time I want to set this up, substituting MyClass for the appropriate class, I can instead just start to type weakSelf and Xcode's autocomplete will try to offer my this line of code:

__weak typeof(self) weakSelf = self;

这每次都会奏效.

此外,使用 typeof() 为我们提供了一个显式类型,并在我们更改实际类型时最大限度地减少了要重写的代码.

Also, using typeof() gives us an explicit type and minimizes the code to rewrite if we ever change the actual type.

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

id is unsafe and it won't give us auto-completes on available methods and properties. After all, weakSelf is now of type id rather than of type MyClass.

如果我只是默认为 MyClass,我们可能会遇到与子类相同的问题,这样做:

And we can run into the same problem with subclasses where if I just default to MyClass, doing:

weak MyClass *weakSelf = self;

如果 self 实际上是 MySubClass,则不会自动完成 MySubClass 添加的方法/属性.

won't give me autocompletes on methods/properties that MySubClass added if self is actually MySubClass.

typeof() 的使用完全不限于块.我喜欢在类方法中使用 typeof().

And use of typeof() isn't at all limited to blocks. I like to use typeof() in class methods.

通常,以下内容就足够了:

Generally, the following is sufficient:

+ (instancetype)myInstance {
    return [[self alloc] init];
}

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

As instancetype and [self alloc] take care of getting the right subclass.

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

But suppose we want something more complex:

+ (NSMutableArray *)arrayOfInstances;

我们如何确保我们放入数组中的对象是正确的类型?

How can we make sure the objects we stick into the array are of the right type?

+ (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;
}

我们不想使用 id 作为 newObj 的类型.我们想确定的是,如果我们调用:

We wouldn't want to use id as the type for newObj. We want to be certain that if we call:

[MyClass arrayOfInstances];

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

We get an array of MyClass objects, but if we call:

[MySubClass arrayOfInstances];

我们得到一个 MySubClass 对象的数组,等等.

We get an array of MySubClass objects, etc.

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

We could also use typeof() if we wanted to instantiate an object from a dictionary that defined our object:

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

这篇关于为什么在避免块保留循环时使用 typeof() 而不是对象类型?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆