Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/23.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
新手IPhone开发者使用仪器面板:我的漏洞在哪里?_Iphone_Objective C_Memory Management_Memory Leaks_Instruments - Fatal编程技术网

新手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];