目标c类方法返回值,分配给弱/强属性 [英] objective c class method returned value, assigned to weak/strong properties

查看:100
本文介绍了目标c类方法返回值,分配给弱/强属性的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我面对一个涉及弱和强的属性的混乱。为了简洁起见,我不会包括整个代码。



我创建了一个类方便的方法,它返回一个UIView对象,并在UIView类别中实现它替代子类化。

  @implementation UIView(CSMonthView)

+(UIView *)monthViewFromDateArray: (NSArray *)arrayOfAllShiftsAndEvents withNibOwner:(id)owner selectedDate:(NSDate *)selectedDate withCompletionHandler:(void(^)(CSCalendarButton * selectedButton))block
{// ..做一些东西
//创建一个UIView的实例
UIView * monthView = [[UIView alloc] initWithFrame:CGRectMake(0,0,320.0,200.0)];

//创建UIButtons并将传递的owner值设置为
//操作事件的目标。

//将UIButton作为子视图添加到monthView ....

return monthView;
}



我应该注意的是,在方法里面没有指向monthView的东西。



现在在'owner'的实现中,这是一个名为CSCalendarViewController的类,我通过调用类方便方法创建上面的UIView,并将它分配给UIView属性称为_monthView。

  @interface CSCalendarViewController:UIViewController 

@property(weak,nonatomic)UIView * monthView ;

@end


@implementation CSCalendarViewController


__weak CSCalendarViewController * capturedSelf = self;
//创建当前月份按钮并使用值填充。
_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)]; 

编译器给出一个警告(应该说)将保留对象赋给弱变量。 / p>

当我将'monthView'赋给从类方法返回的UIView时,为什么没有得到同样的错误信息?



对于ARC前的内存管理我没有深入的理解,我想我缺少一些明显的东西。感谢。

解决方案


'monthView'仍然保留返回的UIView的值。 p>

它不会长。这个问题演示了ARC的基本工作原理,以及它是如何转换为传统的retain / release方法,而不是一个全新的内存管理系统。



/ h2>

在ARC之前,没有弱或强的概念,而是指保留和赋值。



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

  //这里的保留计数为1 
var = [NSString alloc] initWithString:@Test];

//这里的保留计数为2
var = [[NSString alloc] initWithString:@Test] retain]

//这里的保留计数为1,但会在以后自动释放
var = [[NSString alloc] initWithString:@Test] autorelease];

//此处的保留计数为0,并且在到达变量之前将被释放!
var = [[NSString alloc] initWithString:@Test] release];

没有命名约定的方法建议他们返回一个自动释放的对象。开发者需要明确地说明一些东西,以使对象保持更长时间:

  //这里的保留计数为1,但会在以后自动释放
var = [NSString stringWithString:@Test];

//这里的保留计数为1
var = [[NSString alloc] initWithString:@Test] retain]

//这里的保留计数为1,但是会被释放两次(过度释放!)
var = [[NSString alloc] initWithString:@Test] autorelease];

//此处的保留计数为0,稍后将再次释放(过量发布!)
var = [[NSString stringWithString:@Test] release] ;



ARC + MRC



不必要的释放和保留,而是基于将被分配给的变量的类型来决定对存储器管理做什么。这不意味着内存管理模型改变了;它仍然是所有保留和释放在引擎盖下。因此,这如何影响你?为了简洁起见,这个答案将只考虑弱变量。



分配给一个弱变量不会对对象的保留计数做任何事情。 strong>让我们看一个实例来解释:

  __ weak UIView * monthView = [[UIView alloc] initWithFrame:CGRectMake 0.0,320.0,200.0)]; 

因为(实际上,ARCness之后)返回一个保留对象, t影响保留计数,编译器发现最早点释放对象,以防止内存泄漏;分配!因此,它将被翻译为以下内容并导致错误:

  UIView * monthView = [[[UIView alloc] initWithFrame:CGRectMake(0.0,0.0,320.0,200.0)] release]; 

现在,关于 monthViewFromDateArray:这是建议编译器(由于其名称),它将返回一个自动释放对象(文档)。因为编译器知道自动释放对象将在运行循环中自动释放(当自动释放池被耗尽时),它不会像以前那样插入 release 调用。因此,对一个弱变量的赋值不是一个问题,但它只在它被使用的范围内真正有效。


I'm facing a bit of a confusion involving weak and strong properties. For the sake of brevity I won't include the entire code.

I created a class convenience method which returns a UIView object, and I implemented it in a UIView category as an alternative to subclassing.

@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;
}

I should note that inside the method I do not have anything pointing to monthView.

Now inside the implementation of the 'owner', which is a class called CSCalendarViewController, I create the above UIView by calling the class convenience method and assign it to a UIView property called _monthView.

@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];
        }

Now my confusion is this. Even though I defined the property 'monthView' as weak, 'monthView' still holds on to the value of the returned UIView.

If I go ahead and do something like this:

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

The compiler gives a warning (as it should) saying "Assigned retained object to weak variable".

Why am I not getting the same error message when I assign 'monthView' to the UIView that returns from the class method?

I don't have a deep understanding when it comes to pre-ARC memory management, and I think I'm missing something obvious. Thanks.

解决方案

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

It won't for long. This question demonstrates the underlying workings of ARC, and how it is a translation to the traditional retain/release methods, rather than a whole new memory management system.

Pre ARC

Before ARC, there was no concept of weak or strong, instead it referred to retain and assign. Assigning to variables did nothing to the reference count, it was up to the developer to manage it.

Now, in regards to the memory management policies, a method whose name begins with "alloc", "new", "copy", or "mutableCopy", will return a retained object (Documentation). This meant, on assignment to a variable, the developer didn't need to explicitly retain (they had to explicitly release, or autorelease):

// 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];

Methods that don't have that naming convention, suggest they return an autoreleased object. The developer needs to say something explicitly, to keep the object around longer:

// 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 removes this unnecessary need of releasing and retaining, and instead decides what to do with the memory management based on the type of variable it will be assigned to. This doesn't mean the memory management model changed; it is still all retain and release under the hood. As such, how does this affect you? For brevity, this answer will only take into account weak variables.

Assigning to a weak variable does not do anything with the retain count of the object. Lets see a practical example to explain:

__weak UIView* monthView = [[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 200.0)];

Because (in reality, behind the ARCness) this is returning a retained object, but weak variables don't affect the retain count, the compiler has found the earliest point to release the object in order to prevent a memory leak; on allocation! As such, it will be translated to the following, and cause an error:

UIView* monthView = [[[UIView alloc] initWithFrame:CGRectMake(0.0, 0.0, 320.0, 200.0)] release];

Now, in regards to monthViewFromDateArray:, this is suggesting to the compiler (due to its name), that it will return an autoreleased object (Documentation). Because the compiler is aware that an autoreleased object will be released automatically later on in the run loop (when the autorelease pool is drained), it will not insert a release call like before. As such, the assignment to a weak variable isn't an issue, but it's only really valid within the scope it's being used in.

这篇关于目标c类方法返回值,分配给弱/强属性的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆