Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/93.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 为什么强属性的分配有效,而弱属性的分配无效?_Objective C_Ios_Automatic Ref Counting_Weak References - Fatal编程技术网

Objective c 为什么强属性的分配有效,而弱属性的分配无效?

Objective c 为什么强属性的分配有效,而弱属性的分配无效?,objective-c,ios,automatic-ref-counting,weak-references,Objective C,Ios,Automatic Ref Counting,Weak References,我在.h文件中声明了一个属性 @property (weak, nonatomic) UIPickerView *levelPicker; 在我的实现文件中合成为: @synthesize levelPicker = _levelPicker; 然后,我在同一个实现文件中有一个代码块,它执行以下操作: if (self.levelPicker == nil) { self.levelPicker = [[UIPickerView alloc] initWithFrame:CGRect

我在.h文件中声明了一个属性

@property (weak, nonatomic) UIPickerView *levelPicker;
在我的实现文件中合成为:

@synthesize levelPicker = _levelPicker;
然后,我在同一个实现文件中有一个代码块,它执行以下操作:

if (self.levelPicker == nil) {
    self.levelPicker = [[UIPickerView alloc] initWithFrame:CGRectZero];
    self.levelPicker.delegate = self;
    self.levelPicker.dataSource = self;
}
textField.inputView = self.levelPicker;
在这种情况下,self.\u levelPicker未设置为新的UIPickerView。也就是说,self.levelPicker=blah分配不起作用

但是,如果我将属性声明更改为:

@property (strong, nonatomic) UIPickerView *levelPicker;
然后一切按预期进行,并且将_levelPicker设置为新分配的UIPickerView


有人能告诉我为什么会这样吗?我以为我已经了解了参考资料是如何工作的,但我想我还有更多的东西要学。我读了一些其他相关的SO帖子,但我还是不太清楚。

好吧,简单的回答是作业确实有效

但是,由于它是一个弱引用,因此不会保留它,因为没有(其他)对选择器的强引用,并且它会自动设置为nil

必须至少有一个对任何对象的强引用,否则它不会被保留,在本例中不会保留

有关更多信息,请参阅苹果“过渡到ARC发行说明”中的“”

Ray Wenderlich在这方面创建了一个很棒的教程。

强限定符创建了一个所有者关系,可以阻止对象被解除分配,这与您以前在非ARC世界中所做的相同:

@property(retain) NSObject *obj;
虽然“弱”限定符不会创建所有者关系,因此对象将像以前一样被解除分配:

@property(assign) NSObject *obj;

在您的例子中,您需要第一个关系,因为您需要实例变量(_levelPicker)来保存新创建的UIPickerView实例。您确实执行了弱赋值,但不久就被解除分配。

正如@Inazfiger所说,您的对象至少需要一个强(保留)引用,否则它们将不会被保留

在本例中,您将选择器视图指定给
UITextField
inputView
属性。文本字段将保留选择器视图(我知道这一点,因为
UITextField
上的
inputView
属性是),但只有在您完成分配后。因此,如果您想坚持使用弱引用,则需要稍微重新排列代码,如下所示:

// Declare a temporary UIPickerView reference. By default, this is
// a strong reference - so tempPicker will be retained until this
// variable goes out of scope.
UIPickerView *tempPicker = [[UIPickerView alloc] initWithFrame:frame];

// Configure the picker
tempPicker.delegate = self;
tempPicker.dataSource = self;

// Assign the picker view to the text field's inputView property. This
// will increase the picker's retain count. Now it'll no longer be
// released when tempPicker goes out of scope.
textField.inputView = tempPicker;

// Finally, assign the same object to self.levelPicker - it won't
// go out of scope as long as it remains assigned to textField's
// inputView property, and textField itself remains retained.
self.levelPicker = tempPicker;

您不能跳过临时变量,在它超出范围之前直接将其分配给inputview吗?您可以编写
textField.inputview=[[UIPickerView alloc]initWithFrame:frame]
,然后直接配置textField.inputview,但在分配给属性(本例中为inputview)的情况下,我会尽量避免这样做有一个自定义的setter,其逻辑依赖于被分配对象的状态。这正是我想要的答案。谢谢,也谢谢@Inafziger。我想进一步的问题是:在这里使用弱引用有什么好处,还是应该使用强引用?这取决于您希望从这段代码中得到什么。如果您希望(正如我所怀疑的)levelPicker始终保持对该对象的引用,即使它目前没有在其他任何地方使用,那么您应该使用强引用。但当您不再需要它时,请确保将其设置为零(通常在viewDidUnload中)!