【问题标题】:Generic typeof for weak self references弱自引用的泛型 typeof
【发布时间】:2012-06-09 04:17:29
【问题描述】:

我正在尝试找出一种方法来使用 typeof 创建对 self 的弱引用,以便在块中使用以避免保留循环。

当我第一次读到这个时,似乎约定是使用__block typeof(self) bself = self;,它可以编译,但使用__block 来避免保留循环不再起作用,应该使用__weak

但是__weak typeof(self) bself = self; 会导致错误:

类型“typeof (self)”(又名“TUAccountsViewController *const __strong”)已经设置了保留属性

有没有办法使用typeof 或其他调用来一般地创建对self 的弱引用?

【问题讨论】:

  • 使用 typeof 来确定类型的动机是什么,而不是明确地使用类 (TUAccountsViewController) 名称?
  • 我想做一个通用的定义,它可以适用于当前的 self 实例。这一切都始于这个提交和讨论:github.com/kgn/BBlock/commit/…

标签: objective-c cocoa automatic-ref-counting objective-c-blocks weak-references


【解决方案1】:

在最新的clang版本苹果clang版本4.0(tags/Apple/clang-421.1.48)(基于LLVM 3.1svn),即Xcode 4.4+__typeof__((__typeof__(self))self) 技巧不再需要了。 __weak typeof(self) bself = self; 行将编译得很好。

【讨论】:

  • 嗯 - 我刚刚发现我需要 Xcode 4.6.1 中的“_ _ typeof(self) _ _”(减去空格)
【解决方案2】:

这行得通!

__typeof__(o) __weak

我在我的 BBlock 项目中定义为 BBlockWeakSelf,可以这样使用:

BBlockWeakSelf wself = self;

https://github.com/kgn/BBlock/blob/master/BBlock.h

根据 Aleph7 的回复进行了编辑。

【讨论】:

  • 这是正确的做法:__typeof__(self) __weak wself = self; 请注意,在类型为 "technically incorrect" 之前有 __weak。
  • keegan3d:您能否编辑您的答案以反映 Alephs 的评论?他说的是对的。
【解决方案3】:

正确的做法是

__weak ActualClassName* weakSelf = self;

除了将不可移植的元语言添加到代码中之外,宏只会让人不清楚变量实际上是什么,以及您实际使用它做什么。

如果您需要比 ActualClassName 提供的更通用的类版本,则不再处理 self,因为定义了 self 的位置,定义了 self 的类。

在这些情况下,您应该使用继承树中最接近的基类名称,NSObject 或更好,而不是 id,例如

__weak MyBaseClassName* weakObject = object;

【讨论】:

    【解决方案4】:

    通用弱自身参考(无需导入 + 代码段)


    根据我的经验,要走的路是使用:

    __typeof__(self) __weak weakSelf = self;

    Note how the ownership qualifier belongs in front of the actual variable.

    使用它时发生的事情非常明显,并且可以在 Xcode 中将其制成方便的代码 sn-p,这使得在需要它的任何项目或类中使用它变得更加容易。 (我用“ws”作为sn-p的补全快捷键)

    嗯..我这里需要一个弱引用..

    ws{return}

    完成。不需要在未来的项目中包含标题,只需使用 sn-p。


    Xcode 片段


    标题:Generic Weak Self Reference
    平台:All
    语言:Objective-C
    完成快捷方式:ws
    完成范围:Function or Method
    代码:__typeof__(self) __weak weakSelf = self;


    编辑:添加了关于基于 comments 和 Xcode Snippet Info 的所有权限定符位置的注释

    【讨论】:

    • 所有权限定符属于实际变量的前面。您可以在任何最新的 Apple 文档中看到这一点。例如:MyClass * __weak myWeakReference; MyClass * __unsafe_unretained myUnsafeReference; developer.apple.com/library/ios/releasenotes/ObjectiveC/…
    • @SteveM 正确。大多数人没有意识到这一点,因为编译器“原谅”了这种违规行为。在这个例子中,我们有TYPE | OWNERSHIP | VARIABLE NAME = VALUE;
    【解决方案5】:

    为什么不直接使用

    __weak id bself = self;
    

    【讨论】:

    • 我考虑过这一点,但仍需要强制转换才能访问对象上的任何属性,例如:Property 'isAddingAccount' not found on object of type '__weak id const'
    • 或者,如果您的对象有共同点,请声明具有此属性的协议并声明 __weak id bself = self;
    • 这些都是很好的建议,只是不像我希望的那样通用。但我想要的可能不存在……
    【解决方案6】:

    我觉得用这个就可以了:

    __weak __typeof(&*self)weakSelf = self;

    它引用了 AFNetworking 的 AFURLConnectionOperation.m 代码。

    【讨论】:

    • 没关系,并且对于较旧的clang版本可以进一步向后兼容,但是索引无法帮助您,而@Brane上面的建议将向您显示调用者/被调用者。如果你不建立一个 github 库,我会走那条路。
    【解决方案7】:

    你试过检查 C 语言方言吗?

    转到项目导航器 -> 项目 -> 目标 -> 构建设置

    那里寻找 C 语言方言。将其从 c11 更改为 GNU99。

    希望对你有帮助:)

    【讨论】:

      【解决方案8】:

      declareBlockSafe( self ) 然后 blk( self ) 在块内。 Self 可以是任何变量或实例变量。对属性和方法返回使用 declareBlockSafeAs。

      如果您导入 Mike Ash 出色的 MAZeroingWeakRef,也适用于非 ARC。 https://github.com/mikeash/MAZeroingWeakRef

      #if __has_feature(objc_arc)

      #define declareBlockSafe(__obj__) __weak typeof(__obj__) __tmpblk##__obj__ = __obj__
      #define blockSafe(__obj__) __tmpblk##__obj__
      #define blk(__obj__) blockSafe(__obj__)
      
      #define declareBlockSafeAs(__obj__, __name__) \
      __weak typeof((__obj__)) __tmpblk##__name__ = (__obj__)
      
      #else
      
      #define declareBlockSafe(__obj__) MAZeroingWeakRef *__tmpblk##__obj__ = [MAZeroingWeakRef refWithTarget:__obj__]
      #define blockSafe(__obj__) ((typeof(__obj__))__tmpblk##__obj__##.target)
      #define blk(__obj__) blockSafe(__obj__)
      
      #define declareBlockSafeAs(__obj__, __name__) \
      MAZeroingWeakRef *__tmpblk##__name__ = (__obj__)
      #endif
      

      对于 ARC,您真的不需要 blk(),只是为了让非 ARC 可以以相同的方式使用宏。

      【讨论】:

        【解决方案9】:

        我有这个宏

        #define weaken(object) __typeof__(self) __weak weakSelf = object
        

        我就是这样用的

        weaken(self);
        //The block referencing weakSelf goes here
        

        【讨论】:

          【解决方案10】:

          __unsafe_unretained 呢?这不如 __weak 安全,但这是我唯一能想到的。另外,为什么要使用 typeof()?

          【讨论】:

          • 我想创建一个通用的define,它可以适用于self 的当前实例。这一切都始于这个提交和讨论:github.com/kgn/BBlock/commit/…
          • 不幸的是__unsafe_unretained 产生了同样的错误:类型'typeof (self)'(又名'TUAccountsViewController *const __strong')已经设置了保留属性跨度>
          • 这在 NSObject 类别中有效吗? -(instancetype)weakReference { __weak id obj = self;返回对象; }
          • 这似乎可以解决问题!我的定义是这样的:#define BBlockWeakSelf __weak typeof([self weakReference]),它的用法是这样的:BBlockWeakSelf wself = self;。完整代码在这里:github.com/kgn/BBlock/commit/…
          • 这在调试中有效,但在发布存档时会出现此错误:4. Running pass 'Aggressive Dead Code Elimination' on function '@"\01-[NSObject(BBlockWeakReference) weakReference]"'。完全错误:cl.ly/102r1D1b0x4304240c3X
          猜你喜欢
          • 2022-01-26
          • 1970-01-01
          • 2012-01-11
          • 1970-01-01
          • 1970-01-01
          • 2015-08-28
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多