iphone - objective c 类方法返回值,分配给弱/强属性

标签 iphone objective-c cocoa-touch ios6 xcode4.5

我对弱属性和强属性有点困惑。为了简洁起见,我不会包含整个代码。

我创建了一个返回 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”定义为 weak,“monthView”仍然保留返回的 UIView 的值。

如果我继续做这样的事情:

    _monthView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 200.0)];

编译器发出警告(它应该如此)说“已将保留的对象分配给弱变量”。

当我将“monthView”分配给从类方法返回的 UIView 时,为什么我没有收到相同的错误消息?

对于 ARC 之前的内存管理,我没有深入的了解,而且我认为我遗漏了一些明显的东西。谢谢。

最佳答案

'monthView' still holds on to the value of the returned UIView.

不会太久。这个问题演示了 ARC 的底层工作原理,以及它如何转换为传统的保留/释放方法,而不是一个全新的内存管理系统。

弧前

在ARC之前,没有weak和strong的概念,而是指retain和assign。分配给变量对引用计数没有任何影响,这取决于开发人员来管理它。

现在,关于内存管理策略,名称以“alloc”、“new”、“copy”或“mutableCopy”开头的方法将返回一个保留对象(Documentation)。这意味着,在分配给变量时,开发人员不需要显式保留(他们必须显式释放或自动释放):

// 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:,这是向编译器(根据其名称)建议它将返回一个自动释放的对象 (Documentation)。因为编译器知道自动释放的对象稍后会在运行循环中自动释放(当自动释放池被耗尽时),所以它不会像以前那样插入 release 调用。因此,对弱变量的赋值不是问题,但它仅在其使用范围内才真正有效。

关于iphone - objective c 类方法返回值,分配给弱/强属性,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13729603/

相关文章:

ios - swift/ cocoa touch : How do I centre dynamically resized text in a UILabel?

ios - 对齐 UIToolBar 项目

iphone - 如何评估 GPS 信号强度? (苹果手机)

iphone - 是否可以使用 AVAudioPlayer 播放 mp3 文件的一部分?如果是,如何?

iphone - 如何访问 UINavigationController 中以前的 View 元素

objective-c - 重写setter方法并获取“xxx的本地声明隐藏实例变量”

ruby-on-rails - 我在哪里/如何在后端存储 iOS 设备 token ?

iphone - initWithTitle 导致执行不完整

iphone - 在ios中设置 "Do not backup flag"的URL是哪个?

ios - NSURL Connection sendAsynchronousRequest 如何保存响应?