【问题标题】:Calling [self methodName] from inside a block?从块内调用 [self methodName]?
【发布时间】:2011-06-28 18:09:54
【问题描述】:

我刚刚遇到块,我认为它们正是我要寻找的,除了一件事:是否可以从块中调用方法 [self methodName]?

这就是我想要做的:

-(void)someFunction{
    Fader* fader = [[Fader alloc]init];

    void (^tempFunction)(void) = ^ {
        [self changeWindow:game]; 
        //changeWindow function is located in superclass
    };

    [fader setFunction:tempFunction];
}

我已经搜索了几天,但找不到任何证据表明这是可能的。

这完全有可能吗,还是我试图将块用于它们不适合的东西?

我使用块的原因是我创建了一个 Fader 类,并且我想存储一个块以在它完成淡出时执行。

谢谢

编辑: 好的,我在建议中添加了,但我仍然收到 EXC_BAD_ACCESS 错误...

-(void)someFunction{
    Fader* fader = [[Fader alloc]init];

    __block MyScreen* me = self;

    void (^tempFunction)(void) = ^ {
        [me changeWindow:game]; 
        //changeWindow function is located in superclass
    };

    [fader setFunction:tempFunction];
    [fader release];
}

也许我不允许给 fader 功能...?

【问题讨论】:

  • 接受的答案是过时的。请接受我的answer,不要用错误的语法混淆人们。

标签: objective-c self objective-c-blocks


【解决方案1】:

是的,你可以这样做。

但是请注意,该块将保留self。如果您最终将此块存储在 ivar 中,您可以轻松创建一个保留周期,这意味着两者都不会被释放。

要解决这个问题,您可以这样做:

- (void) someMethodWithAParameter:(id)aParameter {

  __block MySelfType *blocksafeSelf = self;
  void (^tempFunction)(void) = ^ {
      [blocksafeSelf changeWindow:game];
  };

  [self doSomethingWithBlock:tempFunction];

}

__block 关键字意味着(除其他外)所引用的对象将不会被保留。

【讨论】:

  • @Marty 确保按钮对象上的function 属性是copy 属性,而不是retain 属性。
  • 请注意,这样做确实会引入self 成为悬空指针并在selfdeallocd 之后调用块时导致RTE 的可能性。在 ARC 之前,您可以使用 Mike Ash 的 MAZeroingWeakRef 库在块内创建对 self 的安全引用。在 ARC 之后,在 iOS 5.0 及更高版本上,您可以使用额外的关键字 __weak 使您对 self 的引用成为归零弱引用。
  • “__block 关键字意味着(除其他外)被引用的对象不会被保留。” ARC有这种变化吗? "The inference rules apply equally to __block variables, which is a shift in semantics from non-ARC, where __block variables did not implicitly retain during capture."
  • @MobileMon 是的,因为self.someProperty = ...[self setSomeProperty:...] 相同。你仍然在块中捕获self,因此你仍然有一个强大的引用循环。
  • @JayQ。这取决于。如果您看到它被释放,那么您就可以了。在我的回答中,会有一个保留循环,因为“self”会强烈引用该块,但该块会强烈引用 self。这是一个保留周期,这意味着块和“自我”都不会被释放(因为他们都希望彼此保持活力)。如果您看到“自我”被释放,那么您没有保留周期。
【解决方案2】:

接受的答案是过时的。在这种情况下使用__block 会导致错误!

为避免此问题,最佳做法是捕获对self 引用,如下所示:

- (void)configureBlock {
    XYZBlockKeeper * __weak weakSelf = self;
    self.block = ^{
        [weakSelf doSomething];   // capture the weak reference
                                  // to avoid the reference cycle
    }
}

请查看Apple Documentation - Avoid Strong Reference Cycles when Capturing self 了解更多详情。

【讨论】:

  • "在这种情况下使用 __block 会导致错误!" - 请让我们知道什么样的错误。
  • 如果我在“doSomething”函数中有类似于“[self doStuff]”的东西怎么办?它可能会导致保留循环?还是不行?
  • @Cristik 保留周期。因为__block 可以让您访问块内部,但不会使其变弱。
  • @superpuccio 不是。该方法本身没有。只有对象,我们在块内保存
【解决方案3】:
__block CURRENTViewController *blocksafeSelf = self;

[homeHelper setRestAsCheckIn:strRestId :^(NSObject *temp) {
    [blocksafeSelf YOURMETHOD:params];
}];

【讨论】:

  • 这会被自动标记为“低质量”。您能否添加一些文字来解释代码以及它如何回答 OP 的问题?
【解决方案4】:

是否可以从块中调用方法 [self methodName]?

是的,为什么不呢。如果你的tempFunction 是一个实例方法,你可以这样做。被调用的方法应该是可访问的是唯一的限制。

【讨论】:

  • tempFunction 不是实例方法——它是一个块。
  • 我认为 Mahesh 的意思是“如果你的 tempFunction 在实例方法中......`
  • @bbum 真;这更有意义。
【解决方案5】:

考虑一下(我认为这是最佳做法)

@implementaion ViewController

- (void) viewDidLoad {
  __weak typeof(self) wself = self;
  [xxx doSomethingUsingBlock: ^{
    __strong typeof(wself) self = wself;
    [self anotherMessage];
  }];
}

@end

此外,您可以定义包装宏。

#define MakeWeakSelf __weak typeof(self) wself = self
#define MakeStrongSelf __strong typeof(wself) self = wself

【讨论】:

    【解决方案6】:

    我想知道你是否 [fader setFunction:tempFunction]; then 是同步的还是异步的。 块在MRR中压入stack.so,如果你不保留它,它会弹出。

    -(void)someFunction{
        Fader* fader = [[Fader alloc]init];
    
        void (^tempFunction)(void) = ^ {
            [self changeWindow:game]; 
            //changeWindow function is located in superclass
        };
    
        [fader setFunction:tempFunction];
        //if the tempFunction execute there will be right.
    }//there the tempFunction pop off
     //....some thing go on
     //execute the tempFunction will go wrong.
    

    【讨论】:

    • 在块内调用'self'会保留它。使用 __weak 或 __block 并在块内使用它之前创建对 self 的弱引用
    • 现在你可以使用weak or unowned
    猜你喜欢
    • 2011-11-18
    • 1970-01-01
    • 2018-10-07
    • 1970-01-01
    • 2019-12-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多