我现在面临一个位涉及弱和强性能的困惑。 为了简便起见,我将不包括整个代码。
我创建它返回一个UIView对象的类的便利方法,以及我实现它在一个UIView类别作为替代子类。
@implementation UIView (CSMonthView)
+ (UIView *)monthViewFromDateArray:(NSArray *)arrayOfAllShiftsAndEvents withNibOwner:(id)owner selectedDate:(NSDate *)selectedDate withCompletionHandler:(void(^)(CSCalendarButton *selectedButton))block
{ // .. do some stuff
// Create an instance of UIView
UIView *monthView = [[UIView alloc] initWithFrame:CGRectMake(0, 0, 320.0, 200.0)];
// Create UIButtons and set the passed down 'owner' value, as the target for an
// action event.
// Add UIButton as subviews to monthView....
return monthView;
}
我要指出的是,方法内我没有什么指向monthView。
现在的“主人”,这是一个名为CSCalendarViewController类的实现里面,我通过调用类方便的方法创建上述的UIView并将其分配给名为_monthView一个UIView财产。
@interface CSCalendarViewController : UIViewController
@property (weak, nonatomic) UIView *monthView;
@end
@implementation CSCalendarViewController
__weak CSCalendarViewController *capturedSelf = self;
// Create the current month buttons and populate with values.
_monthView = [UIView monthViewFromDateArray:_arrayOfAllShiftsAndEvents withNibOwner:self selectedDate:_selectedDate withCompletionHandler:^(CSCalendarButton *selectedButton) {
capturedSelf.selectedButton = selectedButton;
[capturedSelf.selectedButton setSelected:YES];
}
现在我的困惑是这样的。 即使我定义的属性“monthView”弱“monthView”犹抱到返回的UIView的价值。
如果我继续前进,做这样的事情:
_monthView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 200.0)];
编译器会发出警告(因为它应该)说:“分配对象保持弱变量”。
为什么我没有得到同样的错误消息时,我给你“monthView”以从类方法返回的UIView?
我没有深刻的认识,当谈到弧前的内存管理,我想我失去了一些东西明显。 谢谢。
“monthView”犹抱到返回的UIView的价值。
它不会很长。 这个问题说明了ARC的基本工作原理,以及它是如何翻译的传统保留/释放方法,而不是一个全新的内存管理系统。
ARC前
ARC之前,有没有弱或强的概念,而是指保留和分配。 分配给变量并没有什么引用计数,它是由开发人员来管理它。
现在,关于内存管理政策,方法名称以“黄金”,“新”,“复制”,或“mutableCopy”,将返回一个对象保留( 文档 )。 这意味着,在分配给一个变量,开发商并不需要明确保留(他们不得不明确地释放或自动释放):
// Will have a retain count of 1 here
var = [NSString alloc] initWithString:@"Test"];
// Will have a retain count of 2 here
var = [[NSString alloc] initWithString:@"Test"] retain]
// Will have a retain count of 1 here, but will be released later on automatically
var = [[NSString alloc] initWithString:@"Test"] autorelease];
// Will have a retain count of 0 here, and will be released before it reaches the variable!
var = [[NSString alloc] initWithString:@"Test"] release];
没有这样的命名方法,建议他们返回一个自动释放的对象。 开发者需要说些什么明确的,以保持对象周围长:
// Will have a retain count of 1 here, but will be released later on automatically
var = [NSString stringWithString:@"Test"];
// Will have a retain count of 1 here
var = [[NSString alloc] initWithString:@"Test"] retain]
// Will have a retain count of 1 here, but will be released twice later on (Over-released!)
var = [[NSString alloc] initWithString:@"Test"] autorelease];
// Will have a retain count of 0 here, and will be released again later on (Over-released!)
var = [[NSString stringWithString:@"Test"] release];
ARC + MRC
ARC消除释放和保留的这种不必要的需求,而是决定如何处理基于变量将被分配到的类型的内存管理做。 这并不意味着改变了内存管理模式; 它仍然是所有保留和引擎盖下释放。 因此,如何影响你? 为了简便起见,这个答案只考虑到疲软的变量。
分配到弱变量并没有对对象的保留计数任何东西。 让我们看一个实际的例子来解释:
__weak UIView* monthView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 200.0)];
由于(在现实中,ARCness后面)此函数返回一个保留的对象,但弱变量不影响保留计数,编译器已发现的最早的点,以释放对象,以防止内存泄漏; 在配置! 因此,它会被翻译成以下,而导致错误:
UIView* monthView = [[[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 200.0)] release];
现在,关于monthViewFromDateArray:
这是在暗示编译器(由于其名称),这样它会返回一个自动释放的对象( 文件 )。 因为编译器知道一个autoreleased对象将在运行循环(当自动释放池被排干)被自动释放以后,它不会插入release
呼叫像以前一样。 因此,分配给弱变量是不是一个问题,但它是唯一真正有效的它的使用范围之内。
假设我们有方法
+(UIView*) create {
return [[UIView alloc] init];
}
编译时,它被转换为这
+(UIView*) create {
return [[[UIView alloc] init] autorelease];
}
现在这里:
UIView* __weak view;
//warning here
view = [[UIView alloc] init]; //1
view = [AppDelegate create]; //2
第一行被转换成这样的:
tempVar = [[UIView alloc] init];
storeWeak(tempVar, &view); //view = tempVar and marked as weak
[view release]; //view is nil after this because retain count == 0 (assignment to nil is done in release internally)
第二行:
tempVar = [MyClass create];
[tempVar retainAutoreleasedReturnValue];
storeWeak(tempVar, &view); //view = tempVar and marked as weak
[release tempVar]; //view is not nil because tempVar is autoreleased later
如果我们有这样的代码:
@autoreleasepool {
view = [[UIView alloc] init];
//view is nil here
view = [AppDelegate create];
//view equals to the return value
}
//view becomes nil here because [AppDelegate create] return value is released
您可以通过查看反汇编代码看到这一切。
文章来源: objective c class method returned value, assigned to weak/strong properties