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

发布于 2024-12-14 23:50:49 字数 2015 浏览 2 评论 0原文

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

TransparentToolbar *tools;

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

例如,我尝试为其创建一个属性......

@property (nonatomic, retain) TransparentToolbar *tools;

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

我做错了什么?

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

啊啊我有自动释放....但这并不能解决 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

进一步编辑 在此处输入图像描述

I've declared the following variable as an instance variable and am using it in my m file, however I've getting a warning.

TransparentToolbar *tools;

Potential leak of an object allocated on line ...

I' have tried creating a property for it, for example..

@property (nonatomic, retain) TransparentToolbar *tools;

And synthesize'ing and releasing it, but my view crashes at the end of dealloc.

What am I doing wrong ?

EDIT same warning on 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];
}

Ahhhh I have autorelease.... but that doesn't solve the pickerSortingDataCurrent ...

EDIT...

#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

FURTHER EDIT
enter image description here

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

执笔绘流年 2024-12-21 23:50:49

如果您定义了@property,那么通常每当您访问类中的ivar时,您都会使用getter/setter,无论是点表示法还是标准方法调用。

点表示法

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

标准方法调用

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

如果您始终显式使用这些 getter 和 setter,那么除了 dealloc 或重写的 setMyVar: 方法。这样做可以让内存管理发生在有限的地方。如果你开始释放并保留自己,那么刚开始时事情可能会有点复杂。

更新

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

例如,在有问题的行之前,您可以直接分配给 ivar,而不使用 setter。保持一致并使用您花时间合成的 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;
}

UPDATE

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

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;

If you define @property then generally any time you access the ivar in your class you use the getter/setter whether that be dot notation or standard method call.

Dot notation

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

Standard method call

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

If you always explicitly use these getters and setters then you pretty much do not need to call release anywhere in your code apart from dealloc or an overridden setMyVar: method. Doing it this way allows memory management to occur in limited places. If you start releasing and retaining yourself then things can be a bit complicated when you first start out.

UPDATE

@bbum gives you the answer but I think you would benefit from being more consistant in your coding as well.

For example before the offending line you are assigning directly to an ivar without using the setter. Be consistant and use the setter/getter that you took the time to synthesize. I would rewrite

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

to

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

Your init methods are not really following the guidelines either you should be checking that self is actually set, so it should look something similar to:

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

UPDATE

The memory leak you are seeing here:

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

is because you look at the docs for UINavigationItem you will see that rightBarButtonItem is declared as retain

@property(nonatomic, retain) UIBarButtonItem *rightBarButtonItem

Therefore the call self.navigationItem.rightBarButtonItem will take a +1 retain on the object you pass in and then you are alloc/initing which is another +1 retain. The UINavigationItem will release it's retain when it is dealloc'd but there will still be your original retain hanging around.

The fix:

UIBarButtonItem *rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.tools];
self.navigationItem.rightBarButtonItem = rightBarButtonItem;
[rightBarButtonItem release]; rightBarButtonItem = nil;
厌倦 2024-12-21 23:50:49
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

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

+1 retain count for the +alloc, +1 retain count for the assignment to the retain @property.

Rewrite it as:

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

(Or you could use autorelease)

佼人 2024-12-21 23:50:49

如果您使用 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];)。遵循该模式,您应该不会遇到任何问题。

If you create a property with retain, you must set it to nil in your dealloc method.

i.e.

@interface DMFakeyClass : NSObject

@property (nonatomic, retain) NSString *bogusString;

@end

@implementation DMFakeyClass

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

@end

That's pretty much all you have to do to have a successful memory management strategy. When you use this property, always use the getter/setter (self.bogusString = [NSString stringWithString:@"bogus"];) and make sure you've autoreleased or released anything you alloc (self.bogusString = [[[NSString alloc] initWithString:@"bogus2"] autorelease];). Follow that pattern and you shouldn't have any issues.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文