objective-c:alloc vs synthesise / retain

时间:2011-04-27 12:25:06

标签: ios objective-c cocoa-touch alloc

我有一个初学者的问题。我想在代码的所有部分访问UIView(而不是单个方法/函数)。

因此我在@interface部分

中声明了它
UIView *calendarView;

然后@property (nonatomic, retain) UIView *calendarView。在@implementation中我有@synthesise calendarView

现在我想定义这个视图的框架并编写以下代码:

    CGRect calendarFrame = CGRectMake(170,     8, 200, 50);
calendarView = [[UIView alloc] initWithFrame:calendarFrame];

但我现在想知道我是否在做一些严重的错误,因为calendarView已经被保留和合成。当然,UIView alloc是多余的,甚至必然会让应用程序崩溃,因为我遇到了内存问题,对吗?

所以我虽然应该编写代码而不是前两行,但它只会产生CalendarView根本不显示的效果:

[calendarView setFrame:CGRectMake(170, 8, 200, 50)];

所以我的问题是,如果我真的需要在使用它之前分配视图?或者还有另一种解决方案吗?

5 个答案:

答案 0 :(得分:2)

只有在你拥有内存之后才能保留一个对象(即你已经分配了它)。所以下面给出的代码是正确的并且需要..

CGRect calendarFrame = CGRectMake(170,     8, 200, 50);
calendarView = [[UIView alloc] initWithFrame:calendarFrame];//you have alloc'ed once

现在您将此视图添加到parentView。例如,我在UIViewController实现中。

[self.view addSubView:calendarView];  //now only your retain takes place. //So now calenderView has to release twice..Once by you (since you alloced it) and once by viewcontroller (since it has retained it)...
[calendarView release];//we are releasing once but the object will not be removed from memory since it is retained by viewController..Our part in memory management is over..Now when this viewController get dealloced it releases 

您可以在整个UIViewController的实现中使用此calendarView ..

-(void)dealloc{
 [super dealloc];//should be last in dealloc..Now the entire controller will be dealloced along with the calenderView which is retained by viewController and the memory will be freed for future uses..
}

这些是一些有用的教程..比苹果的文档更容易理解。但是也阅读了Apple的文档..

http://ferasferas.wordpress.com/2010/12/05/introduction-to-memory-management-on-iphone/

http://iosdevelopertips.com/objective-c/memory-management.html

http://mauvilasoftware.com/iphone_software_development/2008/01/iphone-memory-management-a-bri.html

https://humblecoder.blogspot.com/2009/08/iphone-tutorial-memory-management.html

答案 1 :(得分:1)

合成属性实际上并不是为您实例化对象。你仍然需要你的alloc和init方法。

在上面的代码中,如果您想要使用该属性,则应该使用self.calendarView而不仅仅是calendarView。 (执行后者是绕过属性并直接使用实例变量,这通常不是您想要的,可能除了dealloc方法之外。)

你应该做出的最后一个改变:鉴于你的财产被标记为保留,它将处理你自己的对象。因此,您应该自动释放您放入其中的对象。试试这个:

self.calendarView = [[[UIView alloc] initWithFrame:calendarFrame] autorelease];

答案 2 :(得分:1)

除了可能的内存泄漏之外,你在第一个例子中实际上并没有做任何错误。您只是错误地认为您的calendarView已被保留,因为这是您定义属性的方式,这是不正确的。将您的财产定义为仅保留意味着当您致电self.calendarView = someotherview时,someotherview将被保留,calendarView中的旧值将被释放,而calendarView将被设置为someotherview。使用不带self的calendarView将不会为您提供任何内存管理规则,例如属性,这就是您的第一个示例正常的原因。您可能希望代码看起来更像这样。

CGRect calendarFrame = CGRectMake(170,     8, 200, 50);
self.calendarView = [[[UIView alloc] initWithFrame:calendarFrame] autorelease];

答案 3 :(得分:1)

是,

在使用UIView之前,你需要分配或从其他来源获取它(在dealloc中释放它,因为你保留它)。

使用以下

   CGRect calendarFrame = CGRectMake(170,     8, 200, 50);
self.calendarView = [[[UIView alloc] initWithFrame:calendarFrame] autorelease];

阅读有关内存管理的Apple文档..

http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

答案 4 :(得分:1)

  

因此我在@interface部分

中声明了它

是的,它只是保留空间和标签来访问类型为+名称

的ivar
  

然后@property(非原子,保留)UIView * calendarView。

正确,声明访问者(setter + getter),以及合成后的操作

  

在@implementation中我有@synthesise calendarView。

定义(实现)属性声明声明的访问器。

  

现在我想定义这个视图的框架并编写以下代码:

     

...   但我现在想知道我是否在这里做了一些严重的错误,因为calendarView已经被保留和合成。当然,UIView alloc是多余的,甚至必然会让应用程序崩溃,因为我遇到了内存问题,对吗?

一,你的内存管理已关闭:

CGRect calendarFrame = CGRectMake(170,     8, 200, 50);
UIView * view = [[UIView alloc] initWithFrame:calendarFrame];
self.calendarView = view; // use the setter, unless in init... or dealloc
[view release], view = 0;

2: 你通常不会在创建UIView时有太多用处。通常,您将创建它的子类。

三(问你的问题): 这没什么不对。变量将为nil,直到它被设置为止。该字段不是为声明的类型默认初始化 - 嗯,它是,但该类型实际上是一个指针,因此结果是它被初始化为nil。你可以创建一个视图或从其他地方传入它。在此之前,视图将为nil / NULL / 0.

  

所以我虽然应该编写代码而不是前两行,但它只会产生CalendarView根本不显示的效果:

     

[calendarView setFrame:CGRectMake(170,8,200,50)];   所以我的问题是,如果我真的需要在使用它之前分配视图?或者还有另一种解决方案吗?

更详细地回到第2点:在大多数情况下,你会想要创建一个子类。 UIView / NSView默认不进行绘图,但它可以用作视图容器。因此,您可能希望从一些现有的子类开始,以熟悉系统提供的视图。

一旦掌握了这一点,请尝试实现自己的子类并覆盖drawRect:

许多初学者喜欢使用Interface Builder(现已集成到Xc4中) - WYSIWYG视图编辑器。