Obj-C,在线分配的对象的潜在泄漏,警告?

时间:2011-11-10 20:22:16

标签: objective-c xcode cocoa-touch analyzer

我已将以下变量声明为实例变量并在我的m文件中使用它,但是我收到了警告。

TransparentToolbar *tools;

在线分配的对象的潜在泄漏...

我已经尝试为它创建一个属性,例如..

@property (nonatomic, retain) TransparentToolbar *tools;

并合成并释放它,但我的视图在dealloc结束时崩溃。

我做错了什么?

在pickerSortingDataCurrent ...

上编辑相同的警告
h
@interface myViewController : UIViewController <UIActionSheetDelegate, 
    UIPickerViewDelegate, UIPickerViewDataSource, UITableViewDelegate, 
    UITableViewDataSource, MFMailComposeViewControllerDelegate> {

    TransparentToolbar *tools;

    NSArray *pickerSortingDataCurrent;
}
@property (nonatomic, retain) TransparentToolbar *tools;
@property (nonatomic, retain) NSArray *pickerSortingDataCurrent;

m
@synthesize pickerSortingDataCurrent;
@synthesize tools;

- (void)viewDidLoad {
    [super viewDidLoad];

    tools = [[[TransparentToolbar alloc] 
           initWithFrame:CGRectMake(0, 0, 70, 44.01)] autorelease];
    tools.barStyle = UIBarStyleBlackOpaque;

    self.pickerSortingDataCurrent = [[NSArray alloc] initWithObjects:
      @"Next Date Ascending", 
      @"Next Date Descending", nil];     // removed some items here
}

- (void)dealloc {
    [tools release];
    [pickerSortingDataCurrent release];
    [super dealloc];
}

啊啊我有autorelease ....但是这并没有解决pickerSortingDataCurrent ......

编辑...

#import "TransparentToolbar.h"

@implementation TransparentToolbar

- (void)drawRect:(CGRect)rect {
    // do nothing in here
}

- (void) applyTranslucentBackground
{
    self.backgroundColor = [UIColor clearColor];
    self.opaque = NO;
    self.translucent = YES;
}

- (id) init
{
    self = [super init];
    [self applyTranslucentBackground];
    return self;
}

// Override initWithFrame.
- (id) initWithFrame:(CGRect) frame
{
    self = [super initWithFrame:frame];
    [self applyTranslucentBackground];
    return self;
}

@end

进一步编辑 enter image description here

3 个答案:

答案 0 :(得分:5)

如果您定义@property,那么通常在您访问班级中的ivar时,您可以使用getter / setter,无论是点符号还是标准方法调用。

点符号

id localyMyVar = self.myVar;
self.myVar = @"A string";

标准方法调用

id localMyVar = [self myVar];
[self setMyVar:@"A string"];

如果您始终明确使用这些getter和setter,那么除了dealloc或重写的setMyVar:方法之外,您几乎不需要在代码中的任何位置调用release。这样做可以在有限的地方进行内存管理。如果你开始释放并保留自己,那么当你刚开始时,事情会有点复杂。

<强>更新

@bbum为您提供答案,但我认为您也可以从编码中更加一致而受益。

例如,在违规行之前,您不使用setter直接分配给ivar。要一致并使用你花时间合成的setter / getter。我会改写

tools = [[[TransparentToolbar alloc] 
       initWithFrame:CGRectMake(0, 0, 70, 44.01)] autorelease];
tools.barStyle = UIBarStyleBlackOpaque;

TransparentToolbar *tmpTools = [[TransparentToolbar alloc] initWithFrame:CGRectMake(0, 0, 70, 44.01)];
tmpTools.barStyle = UIBarStyleBlackOpaque;
self.tools = tmpTools;
[tmpTools release]; tmpTools = nil;

您的init方法并未真正遵循指南,您应该检查self是否已实际设置,因此它应该类似于:

- (id)init
{
    self = [super init];
    if (self) {
        [self applyTranslucentBackground];
    }
    return self;
}

<强>更新

你在这里看到的内存泄漏:

self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.tools];

是因为您查看了UINavigationItem的文档,您会看到rightBarButtonItem被声明为retain

@property(nonatomic, retain) UIBarButtonItem *rightBarButtonItem

因此,调用self.navigationItem.rightBarButtonItem将在您传入的对象上保留+1,然后您将分配/启动,这是另一个+1保留。 UINavigationItem将在释放时释放它的保留但仍会保留原始保留。

修复:

UIBarButtonItem *rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.tools];
self.navigationItem.rightBarButtonItem = rightBarButtonItem;
[rightBarButtonItem release]; rightBarButtonItem = nil;

答案 1 :(得分:1)

self.pickerSortingDataCurrent = [[NSArray alloc] initWithObjects:
  @"Next Date Ascending", 
  @"Next Date Descending", nil];     // removed some items here

+1保留计数+ alloc,+1保留计数用于retain @property的分配。

将其重写为:

NSArray *labels = [[NSArray alloc] initWithObjects:
  @"Next Date Ascending", 
  @"Next Date Descending", nil];
self.pickerSortingDataCurrent = labels;
[labels release];

(或者您可以使用autorelease

答案 2 :(得分:0)

如果使用retain创建属性,则必须在dealloc方法中将其设置为nil。

@interface DMFakeyClass : NSObject

@property (nonatomic, retain) NSString *bogusString;

@end

@implementation DMFakeyClass

-(void)dealloc {
    self.bogusString = nil;
    [super dealloc];
}

@end

您需要做的就是拥有成功的内存管理策略。使用此属性时,请始终使用getter / setter(self.bogusString = [NSString stringWithString:@"bogus"];),并确保已自动释放或释放您分配的任何内容(self.bogusString = [[[NSString alloc] initWithString:@"bogus2"] autorelease];)。遵循这种模式,你不应该有任何问题。