新手IPhone开发者使用仪器面板:我的漏洞在哪里?
更新新手IPhone开发者使用仪器面板:我的漏洞在哪里?,iphone,objective-c,memory-management,memory-leaks,instruments,Iphone,Objective C,Memory Management,Memory Leaks,Instruments,更新 我已经更新了planets.m/h文件,以反映评论员的建议(谢谢bbum和DarkDust)。 我的工厂方法现在都调用autorelease,如下所示: - (Planet *) initWithName: (NSString *)name; + (Planet *) planetWithNameAndMoons:(NSString *)name moons:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION; + (Planet *) plane
我已经更新了planets.m/h文件,以反映评论员的建议(谢谢bbum和DarkDust)。 我的工厂方法现在都调用autorelease,如下所示:
- (Planet *) initWithName: (NSString *)name;
+ (Planet *) planetWithNameAndMoons:(NSString *)name moons:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
+ (Planet *) planetWithName:(NSString *)name;
+ (Planet *) planetWithResultSet:(FMResultSet *)resultSet;
现在我的init看起来像这样
- (id)init {
self = [super init];
self.Id = 0;
self.SupportsLife = NO;
self.Moons = [NSMutableArray array];
return self;
}
我在我的第二个控制器中从根上调用planetWithName。我就是这样使用它的
- (Planet *)newPlanet
{
int i = 0;
Planet *planet = nil;
NSMutableDictionary *criteria = [NSMutableDictionary new];
do {
i += 1;
[criteria setValue: [NSString stringWithFormat:@"Planet %d", i] forKey: @"Name"];
planet = [[PlanetRepo SharedRepo] Find: criteria];
} while (planet != nil); // if a planet is found with that name, keep looking...
planet = [Planet planetWithName: (NSString *)[criteria valueForKey:@"Name"]];
[planet retain];
[criteria release];
criteria = nil;
return planet;
}
这是我的PlanetRepo类(注意,它围绕着FMDB)
PlanetRepo.h
#import <Foundation/Foundation.h>
#import "Planet.h"
@interface PlanetRepo : NSObject {
FMDatabase * _repoSource;
}
+ (PlanetRepo *) SharedRepo;
- (Planet *)Find:(NSDictionary *)criteria;
- (NSMutableArray *)GetAll;
- (Planet *)GetById:(id ) Id;
- (BOOL) Save:(Planet *) planet;
- (BOOL) Delete: (Planet *) planet;
- (BOOL) Open:(NSString *)repoSource;
- (void) Close;
@end
@interface PlanetRepo (Private)
- (NSError *) CreateDatabaseIfNeeded:(NSString *)databasePath;
@end
我想这意味着我在[Planet init]中创建数组时遇到了问题
我在这里也列出了我的班级档案。我非常感谢在这方面的任何帮助
行星
#import <Foundation/Foundation.h>
#import "FMDatabase.h"
@class Planet;
@interface Planet : NSObject { }
@property (nonatomic, assign) int Id;
@property (nonatomic, copy) NSString *Name;
@property (nonatomic, retain) NSMutableArray *Moons;
@property (nonatomic, assign) BOOL SupportsLife;
- (Planet *)initWithName: (NSString *)name;
+ (Planet *) newWithNameAndMoons:(NSString *)name moons:(id)firstObj, ... NS_REQUIRES_NIL_TERMINATION;
+ (Planet *) newWithName:(NSString *)name;
+ (Planet *) readPlanetFrom:(FMResultSet *)resultSet;
@end
一些问题:
- 实例变量和属性应以小写字母开头(以消除类名的歧义)
- 在
方法中分配init
没有必要,但也没有坏处(顺便说一句,它需要tmp=nil;
测试)if(self){…}
- 您可以通过说
self.moons=[NSMutableArray];
+ (Planet *) newWithName:(NSString *)name {
return [[self alloc] initWithName: name];
}
这应该是这样的:
+ (id) planetWithName: (NSString *) aName {
return [[[self alloc] initWithName: name] autorelease];
}
此外,这:
+ (Planet *) readPlanetFrom:(FMResultSet *)resultSet
应该是这样的:
+ (id) planetWithResultSet: (FMResultSet *) aResultSet
如果看不到更多的代码,就很难说泄漏的确切来源。在启用保留/释放跟踪的分配工具下运行代码。选择一个泄漏的行星,查看所有保留/释放事件。将有一个额外的保留。尽我所能尝试,我无法在这里发现问题。我只有一个版本y胡乱猜测:您是否有一个单独的线程分配行星?例如,通过
performSelectorInBackground:
?如果是这样,您首先需要设置一个NSAutoreleasePool,并在方法末尾将其耗尽。如果这真的是问题,您将看到类似***\u NSAutoreleaseNoPool()的消息:Foo类的对象0x1234560在没有池的情况下自动释放-只是泄漏
不过,我有一点意见:你使用new
是很少见的。new
是一个。但是,它的用法是
所以不是
tmp = [NSMutableArray new];
self.Moons = tmp;
[tmp release];
更常见的是写:
self.Moons = [[[NSMutableArray alloc] init] autorelease];
或者更好:
self.Moons = [NSMutableArray array];
你能解释一下为什么你认为泄漏是
+[Planet newWithName]
吗?它确实执行了它应该执行的操作,返回了一个带有retain count 1的实例。或者我遗漏了什么吗?不过,你在+[Planet planetWithName:]这一点上是绝对正确的
使用autorelease是更好的风格。如果没有更多的代码,很难得出结论,但我可以想象调用者会做类似于self.myPlanet=[Planet newWithName:@“Bob”]
其中myPlanet
是一个声明为retain
的@属性
。该工具并没有告诉您init和newWithName存在问题。它告诉您泄漏的对象就是在那里创建的。您可以在创建对象时展开负责框架以查看整个堆栈,这可能会导致elp你知道为什么以后不能正确发布。感谢所有发表评论的人。我采纳了DarkDust和bbum的建议,并将我的工厂方法重命名为planet。我知道这是一个obj-c风格的问题,但我很高兴知道什么是正确使用。我还将卫星创建更改为self。卫星=[NSMutableArray];我不是直接调用performSelectorInBackground:框架是否会在某个时候自动执行此操作?我将ios 4作为我的目标。不,线程仅由您显式创建(在内部,像NSURLConnection这样的一些类会创建它们自己的线程,但您永远不会注意到)。
tmp = [NSMutableArray new];
self.Moons = tmp;
[tmp release];
self.Moons = [[[NSMutableArray alloc] init] autorelease];
self.Moons = [NSMutableArray array];