Objective-C Blocks:如果从指向self的弱指针调用,则可以在外部方法中修改self吗?

Objective-C Blocks:如果从指向self的弱指针调用,则可以在外部方法中修改self吗?,objective-c,memory-management,objective-c-blocks,Objective C,Memory Management,Objective C Blocks,您能从一个实例方法修改self吗?该实例方法是从块内的弱self指针调用的 -(void)someMethod:(AnotherClassName *)anObject { __weak MyClassName *weakSelf = self; [anObject requestSomethingWithCompletion:^{ [weakSelf updateSomething]; }]; } -(void)updateSomething {

您能从一个实例方法修改self吗?该实例方法是从块内的弱self指针调用的

-(void)someMethod:(AnotherClassName *)anObject {

    __weak MyClassName *weakSelf = self;

    [anObject requestSomethingWithCompletion:^{
        [weakSelf updateSomething];
    }];
}

-(void)updateSomething {
    self.something = @"update"; // Will this cause a memory leak?
}
因此,基本上我是从我所在的同一个类中调用实例方法,但我是从弱指针调用实例方法,然后更改
self

根据这一点,在块内如何调用
self
上的方法,但不清楚我是否可以在该方法中直接修改
self

如果你知道答案是基于你以前读过的东西,请包括来源


谢谢

您可以修改属性和调用方法。不会有内存泄漏

但是您的块现在不是线程安全的。如果
requestSomethingWithCompletion
将异步运行block,则在块执行期间可以释放类(
self
),并且
weakSelf
将变为零。这可能会导致问题(取决于块的功能)。避免这种情况的最佳做法是按照以下方式编写

-(void)someMethod:(AnotherClassName *)anObject {

    __weak MyClassName *weakSelf = self;

    [anObject requestSomethingWithCompletion:^{
        MyClassName *strongSelf = weakSelf;
        [strongSelf updateSomething];
    }
}

-(void)updateSomething {
    self.something = @"update"; // No leaks here!
}

您可以修改属性和调用方法。不会有内存泄漏

但是您的块现在不是线程安全的。如果
requestSomethingWithCompletion
将异步运行block,则在块执行期间可以释放类(
self
),并且
weakSelf
将变为零。这可能会导致问题(取决于块的功能)。避免这种情况的最佳做法是按照以下方式编写

-(void)someMethod:(AnotherClassName *)anObject {

    __weak MyClassName *weakSelf = self;

    [anObject requestSomethingWithCompletion:^{
        MyClassName *strongSelf = weakSelf;
        [strongSelf updateSomething];
    }
}

-(void)updateSomething {
    self.something = @"update"; // No leaks here!
}

挑剔但重要的区别:您不是在“修改”
self
,也不是在“更改”
self
——其中
self
是指向对象(而不是对象本身)的指针。相反,您将方法发送到self指向的对象,并可能修改该对象。这种区别对于理解块中涉及对象指针时的细微之处很重要;)@CouchDeveloper不会调用属性的setter,或者更具体地说发送消息
[self-setSomething:@“update”]
来修改self指向的对象?好的,我想我现在明白了。类本身可以实现自己的setter,这可能会修改基础实例变量,也可能不会修改self。setter属性可能会修改对象,但是self本身,它是指向该对象的指针,保持不变。事实上,如果一个块捕获了指向任何对象(不仅仅是自身)的强指针,它就不能“修改”该指针,例如:
obj=anotherObject在块中会发出类似“无法修改变量'obj'”之类的编译器错误。Korey,整个主题更复杂,注释中无法进行彻底的解释。我最近写了一个可能也会有帮助的答案:挑剔但重要的区别:你不是在“修改”
self
,也不是在“改变”
self
——其中
self
是指向对象的指针(而不是对象本身)。相反,您将方法发送到self指向的对象,并可能修改该对象。这种区别对于理解块中涉及对象指针时的细微之处很重要;)@CouchDeveloper不会调用属性的setter,或者更具体地说发送消息
[self-setSomething:@“update”]
来修改self指向的对象?好的,我想我现在明白了。类本身可以实现自己的setter,这可能会修改基础实例变量,也可能不会修改self。setter属性可能会修改对象,但是self本身,它是指向该对象的指针,保持不变。事实上,如果一个块捕获了指向任何对象(不仅仅是自身)的强指针,它就不能“修改”该指针,例如:
obj=anotherObject在块中会发出类似“无法修改变量'obj'”之类的编译器错误。Korey,整个主题更复杂,注释中无法进行彻底的解释。我最近写了一个答案,这可能也会有所帮助:实际上,弱指针的实现方式保证了在OP的情况下,您不需要担心self是否已被释放。在这种情况下,解除弱指针的引用(意味着使用弱指针)将返回一个
nil
值,并且可以安全地将消息发送到
nil
。然而,您建议的习惯用法实际上是首选的,因为它实际上避免了这样一些微妙的问题,即当对弱指针进行多次解引用时,首先返回一个对象,然后再返回
nil
——因为它同时被删除了。再次获取强指针可以安全地保留该对象。您的代码与OP的代码完全相同。请参阅“在对对象左值执行左值到右值转换时发生读取。对于_弱对象,当前指针对象将被保留,然后在当前完整表达式的末尾被释放。这必须根据赋值和指针对象的最终释放自动执行。”实际上,弱指针的实现方式保证了在OP的情况下,您不必担心self是否已被释放。在这种情况下,解除弱指针的引用(意味着使用弱指针)将返回一个
nil
值,并且可以安全地将消息发送到
nil
。然而,您建议的习惯用法实际上是首选的,因为它实际上避免了这样一些微妙的问题,即当对弱指针进行多次解引用时,首先返回一个对象,然后再返回
nil
——因为它同时被删除了。再次获取强指针可以安全地保留该对象。您的代码与OP的代码完全相同。请参阅“在对对象左值执行左值到右值转换时发生读取。对于_弱对象,当前指针对象将保留,然后在当前完整表达式的末尾释放。这必须根据赋值和最终释放原子执行。”