【问题标题】:Class works not correct. How to make it better?类工作不正确。如何让它变得更好?
【发布时间】:2011-04-27 07:44:22
【问题描述】:

我已经写了课,想给你看...

我认为这门课写的不正确,这就是为什么我的申请中有韭菜。首先,delloc 从不打电话。我可以在这门课中进行哪些更改以使其变得更好,请帮助。

Articles.h

#import <Foundation/Foundation.h>

@interface Article : NSObject {
    BOOL favorite;
    NSMutableString * title;  
    NSMutableString * summary;  
    NSMutableString * mainLink;  
    NSMutableString * pubDate;  
    NSMutableString * author;  
    NSMutableString * imageLink;  
}

@property (nonatomic, assign) BOOL favorite;  
@property (nonatomic, retain) NSMutableString * title;  
@property (nonatomic, retain) NSMutableString * summary;  
@property (nonatomic, retain) NSMutableString * mainLink;   
@property (nonatomic, retain) NSMutableString * pubDate;  
@property (nonatomic, retain) NSMutableString * author;  
@property (nonatomic, retain) NSMutableString * imageLink;  

- (id)initWithValues:(NSString *) inTitle mainLink:(NSString *) inMainLink summary:(NSString *) inSummary
             pubDate:(NSString *) inPubDate author:(NSString *) inAuthor imageLink:(NSString *) inImageLink;


//Setter methods
- (void)setTheTitle:(NSString *) inTitle;
- (void)setTheMainLink:(NSString *) inMainLink;
- (void)setTheSummary:(NSString *) inSummary;
- (void)setThePubDate:(NSString *) inPubDate;
- (void)setTheAuthor:(NSString *) inAuthor;
- (void)setTheImageLink:(NSString *)inImageLink;

@end

Articles.m

#import "Articles.h"

@implementation Article

@synthesize favorite;  
@synthesize title;  
@synthesize summary;  
@synthesize mainLink;
@synthesize pubDate;  
@synthesize author;  
@synthesize imageLink;  

- (void)dealloc {
    NSLog(@"article dealloc \n");
    [self.title release];
    [self.mainLink release];
    [self.summary release];
    [self.pubDate release];
    [self.author release];
    [self.imageLink release];

    [super dealloc];
}



- (id)init {

    self = [super init];
    if(self) {
      // set your properties...
      self.title     = [[[NSMutableString alloc] init] autorelease];
      self.mainLink  = [[[NSMutableString alloc] init] autorelease];
      self.summary   = [[[NSMutableString alloc] init] autorelease];
      self.pubDate   = [[[NSMutableString alloc] init] autorelease];
      self.author    = [[[NSMutableString alloc] init] autorelease];
      self.imageLink = [[[NSMutableString alloc] init] autorelease];
      self.favorite = NO;
    }
    return self;
}

- (id)initWithValues:(NSString *) inTitle mainLink:(NSString *) inMainLink summary:(NSString *) inSummary
            pubDate:(NSString *) inPubDate author:(NSString *) inAuthor imageLink:(NSString *) inImageLink
{
    self = [super init];
    if(self) {
        // set your properties ...
        if (inTitle != nil) {
            self.title = inTitle;
        }

        if (inMainLink != nil) {
            self.mainLink = inMainLink ;
        }

        if (inSummary != nil) {
            self.summary = inSummary;
        }

        if (inPubDate != nil) {
            self.pubDate = inPubDate;
        }

        if (inAuthor != nil) {
            self.author = inAuthor ;
        }

        if (inImageLink != nil) {
            self.imageLink = inImageLink ;
        }

        self.favorite = NO;
    }

    return self;
}


@end

添加:

看我的主班有NSXMLParser。在我写的主类 .h 文件中:

Article * currentArticle;

现在在 .m 文件中,当解析器 didStartElement 我分配蚂蚁在解析器 didEndElement 中初始化文章时,我将它释放 [self.currentArticle release];但 delloc 不调用。

- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI 
                                        qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    // Copy current Xml Element name.
    currentElement = [elementName copy];
    if ([elementName isEqualToString:@"item"]) {
        // Clear out our story item caches...
        self.currentArticle = [[Article alloc] init];
    }
    [currentElement release];

}

添加测试版

- (void) parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI 
                                        qualifiedName:(NSString *)qName attributes:(NSDictionary *)attributeDict {
    // Copy current Xml Element name.
    currentElement = [elementName copy];
    if ([elementName isEqualToString:@"item"]) {
        // Clear out our story item caches...
        self.currentArticle = [[Article alloc] init];
        [self.currentArticle release];
    }
    [currentElement release];

}

看我在初始化之后添加了[self.currentArticle release]; 并在此处放置断点...当我的应用程序第一次进入这部分代码时它调用 init 但不调用 release 第二次调用 release ?但为什么 ?这是不对的

为什么我不使用自动释放!!!

 self.title     = [[[NSMutableString alloc] init] autorelease];
    self.mainLink  = [[[NSMutableString alloc] init] autorelease];
    self.summary   = [[[NSMutableString alloc] init] autorelease];
    self.pubDate   = [[[NSMutableString alloc] init] autorelease];
    self.author    = [[[NSMutableString alloc] init] autorelease];
    self.imageLink = [[[NSMutableString alloc] init] autorelease];

我没有在这部分代码中使用自动释放,因为我已经读过它给韭菜带来了,因为当我编写自动释放时,对象会在应用程序工作结束时释放!我在写???

谢谢!!!

【问题讨论】:

  • 如果没有调用 dealloc 方法,那么很可能问题不在类本身,而在于它的使用方式......
  • +1 一个很好的学习例子
  • 你从来没有在任何地方调用过 initWithValues 吗?
  • 其次,我也是 +1。
  • 是的,我正在调用 initWithValues

标签: iphone ios class


【解决方案1】:

你可以像这样删除每个 setter

- (void)setTheSummary:(NSString *) inSummary
{

    if (self.summary != nil) {
        [self.summary release];
    }

    self.summary = [[NSMutableString alloc] initWithString:inSummary];
}

您已经将每个 ivar 声明为属性并合成了 getter 和 setter。因此,您可以设置标题,例如:

self.title = newTitle;

这将重新定义新标题并将其分配给标题并释放先前(如果存在)的值。

编辑

如果你设置属性像

self.title = [[NSMutableString alloc] init];

可变字符串的实例将被过度保留,因此会有泄漏。

Retain 将保留计数增加 1,这通过属性的声明发生,并且会通过调用 init 增加一。

改成:

self.title = [[[NSMutableString alloc] init] autorelease];

编辑 2

更改这些构造的初始化:

if (inTitle == nil) {
    self.title = [[NSMutableString alloc] init];
}
else
{
    [self.title release];
    self.title = [[NSMutableString alloc] initWithString:inTitle];
}

收件人:

if (inTitle != nil) {
    self.title = inTitle;
}

现在添加

self = [self init];

并删除

[super init];

在您的 init 方法的开头initWithValues; 这将首先为您初始化属性,它减少了代码重复并使您的类更小。删除[super init] 只需要调用一次 NSObject 的初始化程序,您可以通过调用self = [self init]; 来执行此操作。

您已经使用这种模式创建了一个所谓的指定初始化程序。你可以阅读更多关于初始化器here

编辑 3

为了让你的初始化器完美,你应该这样写:

- (id)init 
{
    self = [super init];
    if(self) {
       // set your properties...
    }
    return self;
}

- (id)initWithValues:(NSString *) inTitle mainLink:(NSString *) inMainLink summary:(NSString *) inSummary
            pubDate:(NSString *) inPubDate author:(NSString *) inAuthor imageLink:(NSString *) inImageLink
{
    self = [self init];
    if(self) {
       // set properties with parameters ...
    }
    return self;
}

此模式将允许您对指定初始化程序和/或调用继承层次结构的初始化程序中可能发生的错误做出反应。这将确保在出现问题时返回 nil,并且您不会将属性设置为错误的实例。

【讨论】:

  • 我做了一个 cmets 并添加了你建议的代码……你能检查一下吗?
  • 很好,请阅读我的编辑。将自动释放添加到分配中。您可以完全删除 setTheSummary 之类的设置器,如果您想从班级外部或班级内部设置某些内容,只需说:myArticle.title = XXX;self.title = XXX;
  • 我添加了 // ADDED AUTORELEASE
  • 意思是我不需要setTheTitle这样的函数...?
  • 是的,因为@synthesize 将启用点语法,例如self.title = @"foo";,实际上与您也可以使用的[self setTitle:@"foo"]; 相同。试试看。 setter 是由编译器为您生成的。插入第二个编辑,请阅读。
【解决方案2】:

对于初学者,我会替换每个

   if (self.imageLink !=nil) {
        [self.imageLink release];
        self.imageLink = nil;
    }

dealloc

[imageLink release];

为了帮助您解决主要问题,即为什么您的实例永远不会被释放,我们需要查看您创建它的代码。

编辑

好的,这是一个猜测可能会发生什么。我希望你能用这个猜测来解决这个问题(没有看到实际代码这是我所能做的):

在你的代码中的某个地方你有这样的东西:

Article *article = [[Article alloc] init];

你说你要在文章上发布,所以你也会有

[article release];

代码中的其他地方。

现在为什么即使你调用了 release 也没有调用 dealloc?我的猜测是你在两者之间做这样的事情:

NSMutableArray *array = [NSMutableArray arrayWithCapacity: 0];
[array addObject: article];

这实际上保留了文章,这可能是它永远不会发布的原因。怎么修?像这样:

[array removeObject: article];

希望这会有所帮助。

【讨论】:

  • 我调用释放创建的对象,但它不起作用... delloc 没有调用
  • @Vito:好的,现在我们需要查看您创建文章的代码。
【解决方案3】:

虽然您的代码有很多问题,但这是导致内存泄漏的部分:

self.title = [[NSMutableString alloc] init];

为什么? title 属性定义为:

@property (nonatomic, retain) NSMutableString * title;

因此,setter 将保留计数增加到 2

dealloc 中,title 的保留计数仅减一,​​因此在解除分配 article 后对象仍然存在。

快速修复:

self.title = [[[NSMutableString alloc] init] autorelease];

编辑:这就是dealloc 永远不会被调用的原因:

self.currentArticle = [[Article alloc] init];

再次查看保留计数:alloc 将保留计数设置为 1。 然后-我假设currentArticle被定义为(nonatomic, retain)-它再次被保留,保留计数现在是2。在dealloc 方法中——我再次假设——你释放currentArticle,所以保留计数是1。除非保留计数为0,否则对象不会释放!

快速修复: 同上

self.currentArticle = [[[Article alloc] init] autorelease];

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-01-29
    • 2021-04-25
    • 2014-12-11
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多