【问题标题】:With ARC, how to correctly set a property with side effect?使用 ARC,如何正确设置具有副作用的属性?
【发布时间】:2011-11-09 02:25:37
【问题描述】:

我有一个使用自动引用计数的类。在课堂上,我有一个如下所述的属性。当我为班级设置提醒时,我希望改变按钮标题的副作用发生。

这是我的代码:

在.h文件中:

@property(nonatomic,strong)Reminder* reminder;

在 .m 文件中: @synthesize 提醒;

  -(void)setReminder:(Reminder *)reminder_
    {
//what else do I need to do here?
        reminder = reminder_;
         if(!reminder.useSound.boolValue)
        {
             onOffButton.title = NSLocalizedString(@"Off", @"Off title");

        }else
        {
            onOffButton.title = NSLocalizedString(@"On", @"On title");
        }
    }

我知道如果没有 ARC,我会做这样的事情:

-(void)setReminder:(Reminder *)reminder_

{

[reminder release];
reminder = [reminder_ retain];


     if(!reminder.useSound.boolValue)
    {
         onOffButton.title = NSLocalizedString(@"Off", @"Off title");

    }else
    {
        onOffButton.title = NSLocalizedString(@"On", @"On title");
    }
}

我是否需要在启用 ARC 的 setter 方法中执行任何其他操作以确保正确保留强变量?

【问题讨论】:

    标签: objective-c ios memory-management ios5 automatic-ref-counting


    【解决方案1】:

    您不需要为这样的副作用编写自己的 setter。使用KVO

    让拥有按钮的控制器观察这个对象的reminder属性:

    [reminderOwner addObserver:self
                    forKeyPath:@"reminder"
                       options:NSKeyValueObservingOptionNew
                       context:NULL];
    

    options argument 指定在进行观察时您希望传递的有关被观察对象状态的哪些信息。

    然后,只要此属性更改值,就会通知您的控制器(请注意,仅当以“键值兼容”方式设置属性时才会发生这种情况,最方便的方法是通过 setter 方法* - 更改 ivar直接不算)。

    你需要在你的控制器中实现observeValueForKeyPath:ofObject:change:context:

    - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
    {
        // Distinguish between observations if necessary; you can also
        // use the |object| argument for this.
        if( [keyPath isEqualToString:@"reminder"] ){
            // Update button text with contents of |change| dictionary
            Reminder * reminder = [change objectForKey:NSKeyValueChangeNewKey];
            if(!reminder.useSound.boolValue)
            {
                 onOffButton.title = NSLocalizedString(@"Off", @"Off title");
    
            }else
            {
                onOffButton.title = NSLocalizedString(@"On", @"On title");
            }
        }
    }
    

    哦,嗯,回答你的实际问题,我相信你的内存管理很好。 reminder 被合成为 __strong-qualified 变量,这意味着 ARC 将保留您放在那里的任何内容。


    *这就是为什么您听说不要在 initdealloc 中使用 setter。

    【讨论】:

    • 但是没有 KVO 和通过覆盖是否有可能?
    • 对不起,早上 5:07 编码时的措辞有误。有没有办法自己实现 setter 并且仍然让 ARC 进行内存管理?
    • 哦,我明白了。当然有; AFAIK 亚历克斯·斯通在他的第一个 sn-p 中提出的二传手是完全 ARC 正确的。 (我在答案末尾添加了一句话来表明这一点。)
    • 谢谢。在那种情况下,仅仅实现一个setter不是更干净吗?我的意思是,如果你在那里有重要的事情发生,你无论如何都会将字符串区分为不同的方法,并以 Alex 的方式实现它,你不必移除观察者等。以这种方式维护的代码也更少,没有丑陋的观察者在你眼中添加/删除代码。
    • 这是一个判断电话;当然,对于 Alex 的情况,将按钮更新直接放入 setter 会更有意义。我认为通常应该尽量避免将这种活动放入 setter 方法中,然而,KVO 是一个很好的工具。
    猜你喜欢
    • 1970-01-01
    • 2015-03-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2015-05-20
    • 1970-01-01
    相关资源
    最近更新 更多