需要为指定了保留标志的属性调用保留

发布于 2024-11-15 04:51:40 字数 5154 浏览 0 评论 0原文

我是 Objective-C 的新手,和大多数新手一样,我对引用管理有疑问。

我编写了一个使用 NSURLConnection 下载数据的类。该代码类似于 Apple 在 http 中的示例: //developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html。唯一的区别是 receiveData 变量被声明为“@property (nonatomic,retain) NSMutableData *receivedData;”在 .m 文件中,我有“@synthesize receiveData = _receivedData;”。

我有 connectionStart 函数,它开始下载数据。在此函数中,我有以下代码:

if (theConnection) {
    // Create the NSMutableData to hold the received data.
    // receivedData is an instance variable declared elsewhere.
    self.receivedData = [NSMutableData data];
} else {
    // Inform the user that the connection failed.
}

程序崩溃并显示以下消息:

2011-06-12 12:47:22.298 WebGallery[1212:207] *** -[NSConcreteMutableData release]: message sent to deallocated instance 0x118a6fe0

如果我将收到的数据分配更改为此代码:

self.receivedData = [[NSMutableData data] retain];

那么程序可以正常工作,并且不会检测到内存泄漏。

如您所见,我需要在 NSMutableData 上调用保留,并且我正在使用属性,该属性被声明为“保留”。

为什么会出现这种情况?

编辑:.m 文件的完整内容:

#import "GalleryData.h"
#import "XmlParser.h"

@implementation GalleryData

@synthesize receivedData = _receivedData;
@synthesize imagesData = _imagesData;
@synthesize delegate = _delegate;
@synthesize currentObjectType = _currentObjectType;
@synthesize currentObjectIndex = _currentObjectIndex;

- (id) init
{
    [super init];
    _imagesData = [[NSMutableArray alloc] init];    
    return self;
}


- (void) dealloc
{
     [_imagesData release];
    _imagesData = nil;
    [super dealloc];
}

- (void) connectionStart:(NSURL *)theURL
{
    NSURLRequest *theRequest = [NSURLRequest requestWithURL:theURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];


    NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

    if (theConnection) {
        // Create the NSMutableData to hold the received data.
        // receivedData is an instance variable declared elsewhere.
        //ASK: Kodėl čia reikia daryti retain jei @property jau nustatyta retain?
        self.receivedData = [[NSMutableData data] retain];
    } else {
        // Inform the user that the connection failed.
    }

}

- (void) startLoading
{
    NSLog(@"Loading started");

    self.currentObjectIndex = 0;
    self.currentObjectType = ObjectTypeXML;
    [self connectionStart:[NSURL URLWithString:@"http://www.aleksandr.lt/gallery/data.xml"]];

}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    [self.receivedData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.receivedData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    [connection release];
    [self.receivedData release];

    NSLog(@"Connection failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    [connection release];

    if (self.currentObjectType == ObjectTypeXML) {
        NSXMLParser *nsXmlParser = [[NSXMLParser alloc] initWithData:self.receivedData];        
        XmlParser *parser = [[XmlParser alloc] initXmlParser:self.imagesData];

        [nsXmlParser setDelegate:parser];
        [nsXmlParser parse];        
        [nsXmlParser release];
        [parser release];

        [self.receivedData release];
        self.receivedData = nil;

        if ([self.imagesData count]) {
            self.currentObjectIndex = 0;
            self.currentObjectType = ObjectTypeThumbImage;
            ImageData *firstImage = [self.imagesData objectAtIndex:0];
            NSURL *theURL = [NSURL URLWithString:firstImage.thumbImageURL];
            [self connectionStart:theURL];
        } else {
            [self.delegate loadingFinished];
            return;
        }
    } else if (self.currentObjectType == ObjectTypeThumbImage) {
        ImageData *currentImage;
        currentImage = [self.imagesData objectAtIndex:self.currentObjectIndex];

        UIImage *thumbImage = [[UIImage alloc] initWithData:self.receivedData];

        if (thumbImage == nil) {
            NSLog(@"image was not created");
        }

        [currentImage setThumbImageScaled:thumbImage];

        [thumbImage release];
        [self.receivedData release];
        self.receivedData = nil;

        if (self.currentObjectIndex == ([self.imagesData count] - 1)) {
            [self.delegate loadingFinished];
            return;
        }

        self.currentObjectIndex++;

        currentImage = [self.imagesData objectAtIndex:self.currentObjectIndex];
        NSLog(@"'%@'", currentImage.thumbImageURL);
        NSURL *theURL = [NSURL URLWithString:currentImage.thumbImageURL];
        [self connectionStart:theURL];
    }
}

@end

I'm newbie in Objective-C, and as most of the newbies I have a questions about references management.

I've written a class which downloads data using NSURLConnection. The code is similar to Apple's example in http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/URLLoadingSystem/Tasks/UsingNSURLConnection.html. The only difference is that receivedData variable is declared as "@property (nonatomic,retain) NSMutableData *receivedData;" In .m file I have "@synthesize receivedData = _receivedData;".

I have connectionStart function which starts downloading data. In this function I have this code:

if (theConnection) {
    // Create the NSMutableData to hold the received data.
    // receivedData is an instance variable declared elsewhere.
    self.receivedData = [NSMutableData data];
} else {
    // Inform the user that the connection failed.
}

The program crashes with this message:

2011-06-12 12:47:22.298 WebGallery[1212:207] *** -[NSConcreteMutableData release]: message sent to deallocated instance 0x118a6fe0

If I change receivedData assignment to this code:

self.receivedData = [[NSMutableData data] retain];

Then the program works correctly and no memory leaks are detected.

As you see I need to call retain on NSMutableData and I'm using property, which is declared as "retain".

Why does this happen?

EDIT: Full contents of .m file:

#import "GalleryData.h"
#import "XmlParser.h"

@implementation GalleryData

@synthesize receivedData = _receivedData;
@synthesize imagesData = _imagesData;
@synthesize delegate = _delegate;
@synthesize currentObjectType = _currentObjectType;
@synthesize currentObjectIndex = _currentObjectIndex;

- (id) init
{
    [super init];
    _imagesData = [[NSMutableArray alloc] init];    
    return self;
}


- (void) dealloc
{
     [_imagesData release];
    _imagesData = nil;
    [super dealloc];
}

- (void) connectionStart:(NSURL *)theURL
{
    NSURLRequest *theRequest = [NSURLRequest requestWithURL:theURL cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:60.0];


    NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];

    if (theConnection) {
        // Create the NSMutableData to hold the received data.
        // receivedData is an instance variable declared elsewhere.
        //ASK: Kodėl čia reikia daryti retain jei @property jau nustatyta retain?
        self.receivedData = [[NSMutableData data] retain];
    } else {
        // Inform the user that the connection failed.
    }

}

- (void) startLoading
{
    NSLog(@"Loading started");

    self.currentObjectIndex = 0;
    self.currentObjectType = ObjectTypeXML;
    [self connectionStart:[NSURL URLWithString:@"http://www.aleksandr.lt/gallery/data.xml"]];

}

- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
    [self.receivedData setLength:0];
}

- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    [self.receivedData appendData:data];
}

- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    [connection release];
    [self.receivedData release];

    NSLog(@"Connection failed! Error - %@ %@",
          [error localizedDescription],
          [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    [connection release];

    if (self.currentObjectType == ObjectTypeXML) {
        NSXMLParser *nsXmlParser = [[NSXMLParser alloc] initWithData:self.receivedData];        
        XmlParser *parser = [[XmlParser alloc] initXmlParser:self.imagesData];

        [nsXmlParser setDelegate:parser];
        [nsXmlParser parse];        
        [nsXmlParser release];
        [parser release];

        [self.receivedData release];
        self.receivedData = nil;

        if ([self.imagesData count]) {
            self.currentObjectIndex = 0;
            self.currentObjectType = ObjectTypeThumbImage;
            ImageData *firstImage = [self.imagesData objectAtIndex:0];
            NSURL *theURL = [NSURL URLWithString:firstImage.thumbImageURL];
            [self connectionStart:theURL];
        } else {
            [self.delegate loadingFinished];
            return;
        }
    } else if (self.currentObjectType == ObjectTypeThumbImage) {
        ImageData *currentImage;
        currentImage = [self.imagesData objectAtIndex:self.currentObjectIndex];

        UIImage *thumbImage = [[UIImage alloc] initWithData:self.receivedData];

        if (thumbImage == nil) {
            NSLog(@"image was not created");
        }

        [currentImage setThumbImageScaled:thumbImage];

        [thumbImage release];
        [self.receivedData release];
        self.receivedData = nil;

        if (self.currentObjectIndex == ([self.imagesData count] - 1)) {
            [self.delegate loadingFinished];
            return;
        }

        self.currentObjectIndex++;

        currentImage = [self.imagesData objectAtIndex:self.currentObjectIndex];
        NSLog(@"'%@'", currentImage.thumbImageURL);
        NSURL *theURL = [NSURL URLWithString:currentImage.thumbImageURL];
        [self connectionStart:theURL];
    }
}

@end

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

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

发布评论

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

评论(2

失去的东西太少 2024-11-22 04:51:40

不要调用[self.receivedData release] - 这会使内部指针悬空。保留属性的全部要点在于它会自行释放。只需执行 self.receivedData = nil 即可。

Do not call [self.receivedData release] - this leaves the internal pointer dangling. The whole point of a retained property is that it releases itself. Just do self.receivedData = nil.

此岸叶落 2024-11-22 04:51:40

这是你的问题:

    [self.receivedData release];
    self.receivedData = nil;

你两次释放该属性(第一次显式释放,第二次通过分配 nil 隐式释放)。

Here is your problem:

    [self.receivedData release];
    self.receivedData = nil;

You're releasing the attribute twice (first time explicitly and second time implicitly by assigning nil).

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