Objective c 目标C块作为异步回调&;错误访问

Objective c 目标C块作为异步回调&;错误访问,objective-c,ios,objective-c-blocks,Objective C,Ios,Objective C Blocks,我有一个严重的疑问。假设以下场景: 屏幕上有一个UIViewController 例如,应用程序使用块作为回调来启动后端调用 您使用“自我”代理,以防止保留循环 用户点击“后退”,并且UIViewController解除锁定 回调块迟早会执行>>错误访问 在iOS 4之前,我们通过设置的delegate属性设置为nil来处理这种情况。。。我不知道,不管你上什么课 但是现在。。。如何取消一个街区??。如果该块被发送到一个静态方法,而您无法清除该回调引用,该怎么办 在这种情况下,我们应该避免使用“自

我有一个严重的疑问。假设以下场景:

  • 屏幕上有一个
    UIViewController
  • 例如,应用程序使用块作为回调来启动后端调用
  • 您使用“自我”代理,以防止保留循环
  • 用户点击“后退”,并且
    UIViewController
    解除锁定
  • 回调块迟早会执行>>
    错误访问
  • 在iOS 4之前,我们通过设置的
    delegate
    属性设置为
    nil
    来处理这种情况。。。我不知道,不管你上什么课

    但是现在。。。如何取消一个街区??。如果该块被发送到一个静态方法,而您无法清除该回调引用,该怎么办

    在这种情况下,我们应该避免使用“自我”代理吗

    顺便说一句,所谓“自我”代理,我的意思是:

    __block typeof(self) bself = self;
    
    谢谢

    首先: 如果(且仅当)您避免使用
    self
    或直接访问块内IVAR的原因确实是保留周期,那么您应该处于如下情况

    client => objectA => blockWithWeakBackReference
    
    (其中
    =>
    表示“强烈引用”)

    在这种情况下,
    blockWithWeakBackReference
    只能由
    objectA
    调用,因此不存在错误访问的危险

    如果我正确理解了你的问题,你真正的意思是另一种情况:

    • objectA
      希望某个应用程序范围的服务在满足某个先决条件的情况下代表其执行块
    • 避免在块内部使用
      self
      ,因为您希望能够在执行块之前处理
      objectA
    这方面的一个示例可能是共享网络队列,该队列在请求由于某种原因完成加载时执行块

    在这种情况下,我建议简单地复制
    NSNotificationCenter
    addObserverForName:object:queue:usingBlock:
    的设计,让您的服务实现一对方法,如
    -(SomeTokenObjectType)addWorkerBlock:(void(^)(任何对您有意义的签名))
    -(void)cancelWorkerBlockWithToken:(SomeTokenObjectType)
    以便排队并取消回调块

    然后,使用此服务的所有对象都可以简单地拥有一个类型为
    NSMutableSet
    的ivar来存储每个排队块的令牌,并在其
    dealloc
    中枚举剩余令牌,用服务取消它们。

    “以防止保留周期。”


    但你真的有一个保留周期来防止吗?想想这个。块保留
    自身
    (视图控制器)。后端调用保留该块。但是,
    self
    在哪里保留块?

    一旦视图被释放,如何将静态块变量设置为NULL?你的意思是,拥有一个静态块变量(或类成员),并将其清除?我希望找到某种API来命名和杀死一个块。但是我没有意识到我可以成为一个班里的一员。那就简单多了。。。谢谢亚历克斯@AlexNichol,你能详细说明一下把这个块变量设为NULL吗?__块变量在哪里声明?如何声明?Thanks@bandejapaisa其想法是维护一个静态块变量,一旦对象被解除分配,就将其设置为NIL。这正是我要处理的场景Dany。非常感谢你的评论,我真的很感激。我要实现这个机制,我真的很喜欢它的样子!。已经有一段时间了,但我想为任何在这方面遇到障碍的人添加一点可能有趣的信息,以解决相关问题:在他那篇令人敬畏的文章中,Mike Ash以一种非常干净优雅的方式实现了这一机制,所以做一个伟大的艺术家,偷走他的方法;-)如果在(3)中不使用自代理,当前的UIViewController将被保留,直到从后端得到响应。这一点都不酷。如果用户点击“后退”,则应释放当前的viewController。“保留周期”部分取决于您的通信层。。。理论上,你是对的。如果代码编写得很好,就不应该有保留周期。然而,您将使用比实际需要更多的资源。@JorgeLeandroPerez:是的,它将保留到后端任务完成为止。但别这样,这没什么大不了的。当视图控制器弹出时,您并不知道它将被释放;由于各种原因,操作系统中的其他内容可能仍然保留。无论如何,除非有办法取消后端任务,否则后端任务必须保留它回调的内容。因此,您必须保留这个UIViewController,或者,如果您对这个视图控制器的内存使用非常严格,您可以让块保留一个(小的)虚拟代理对象,并且您的视图控制器可以是这个虚拟对象的委托,当它解除分配时,它将使委托为零。这是一个非常老的问题。我现在所做的只是你说的。除非在少数特定情况下,内存使用量很大。在这些情况下,我只存储活动的requestId,并在返回之前取消它们。谢谢你的帮助!