【问题标题】:Property Polymorphism With Optional IBOutlet具有可选 IBOutlet 的属性多态性
【发布时间】:2014-12-29 15:53:48
【问题描述】:

我的 iOS 项目中有一个 UITableViewCells 的多态链(为问题而简化):

   ====================
  | BaseCellWithButton |
   ====================
            ^
            |
            |
 ========================
| BaseCellWithTwoButtons |
 ========================

BaseCellWithButton 有 1 个属性:

@property (nonatomic, strong) UIButton* button;

BaseCellWithTwoButtons 足够复杂,我想创建一个笔尖。我知道 IBOutlet 属性通常是(nonatomic, weak) IBOutlet ...,但我想将它声明为(nonatomic, strong) IBOutlet ...,以便我可以选择将它设置在一个 nib 的子类中,但如果没有,我可以在父类中实例化它。

这是一种不好的做法吗?有没有更好的方法来实现多态,同时允许子类创建一个 nib 并仍然重用父属性?

【问题讨论】:

    标签: ios objective-c oop memory-management properties


    【解决方案1】:

    您可以在BaseCellWithButton 类中将button 声明为IBOutlet,然后只需在任何子类中从xib 中连接按钮即可。

    我附上了示例文件,你可以将它添加到任何项目中,看看它是如何工作的。

    有基类和子类。

    如果您计划通过父类中的代码将其实例化,那么strong 参考也是最佳实践

    在基类中,声明了button,但它只在子类中连接到xib https://dl.dropboxusercontent.com/u/48223929/SubclassTableCellsExample.zip

    【讨论】:

    • 感谢您的回复。我知道我可以使用您所展示的子笔尖的父属性。我很好奇的是在父类中声明属性的正确方法,如果它将可选地连接到 IBOutlet。通常,如果是,则应将属性声明为“弱”。如果不是,则必须获得对该对象的强引用,因此使用“强”属性声明它。
    • 您可以有一个可选的强引用。强/弱无关(弱引用必须是可选的,但这在这里也无关紧要)
    • 对我来说太快了!重点是一样的——内存管理语义不会影响你在说什么。
    • 我认为声明对 IBOutlet 的弱引用或强引用没有问题 - 这取决于您。 Xcode 在某些情况下会为 IBOutlets 创建强引用(视图不是子视图,而是在同一个 nib 中)
    【解决方案2】:

    声明你的属性 weak 或 strong 的唯一显着区别在于为你合成的 setter。您习惯于看到 IBOutlets 很弱,因为它们通常是添加到其他视图的 UIView 子类。向另一个视图添加一个视图会将其放入一个数组(属于父视图的子视图数组),这会导致该数组在对象上放置一个保留。

    edit 感谢@nielsBot 的评论,当它们指向的对象被释放/释放时,弱指针也会自动设置为 nil,这曾经是我们使用时遇到的问题分配而不是弱。因此,如果您要使 IBOutlet 强,那么您仍然需要在您的拆卸方法之一中将该指针设置为 nil *

    考虑一下

    @interface someViewController()
    
    @property (weak, nonatomic) UIButton *weakButton1, *weakButton2;
    @property (strong, nonatomic) UIButton *strongButton1;
    
    @end
    
    
    
    
    @implementation someViewController
    
    -(void ) viewDidLoad{
    
    CGRect buttonRect = CGRectMake(20.0, 20.0, 250.0, 40.0 ) ;
    
    self.weakButton1 = [[UIButton alloc] initWithFrame: buttonRect ];
    
    //the following messages are passed to nil, because the weakButton1 pointer is weak,
    // with no other retains the button was nilled out immediately...
    // therefore we lose the button we created, it never make it to the view
    
    [self.weakButton1 addTarget:self action: @selector (buttonAction: ) forEvent:UIControlEventTouchUpInside];
    [self.view addSubView: self.weakButton1];
    
    /////////////////////////////////////
    
    self.strongButton1 = [[UIButton alloc] initWithFrame: buttonRect ];
    
    //this one on the other hand works no problem
    
    [self.strongButton1 addTarget:self action: @selector (buttonAction:) forEvent:UIControlEventTouchUpInside];
    [self.view addSubView: self.strongButton1];
    
    /////////////////////////////
    
    UIButton *tempButton = [[UIButton alloc] initWithFrame: buttonRect ];
    
    //button created into a scoped (temporary) pointer, which is strong by default, no problem...
    
    [tempButton addTarget:self action: @selector (buttonAction:) forEvent:UIControlEventTouchUpInside];
    [self.view addSubView: tempButton];
    
    //button is assigned to weak property AFTER it is added to view (which causes a retain), no problem
    self.weakButton2 = tempButton;
    
    ///////////////////////
    }
    @end
    

    【讨论】:

    • 我不认为这就是为什么网点通常被宣布为 weak。这样您就不必将所有对从 NIB 文件加载的对象的引用归零。 (因为只要所有者对象存在,这些对象就会维护对它们的引用)
    • 是的,没错。好吧,如果不是为什么网点设置为弱,那么这怎么可能,不是吗? :)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-18
    • 2011-08-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多