前一阵子在做一个软件,其中用到了XML-RPC,同时也需要数据的统一管理,

 

比如:从某个api端点获取数据,然后把数据保存到本地,然后所有的操作都会使用到这些数据。

 

当时的想法是创建一个单态模式的数据管理类,然后所有的操作都是通过这个类来完成。

 

想法是好的,但是由于自己是刚刚接触,所以某些概念,方法没有了解,造成了问题。

 

问题是这样的:

 

1、执行流程,第一步,访问api,获取数据,这个数据用来组合一个URL,然后这个URL提交到另一个

     ViewController里面,使用UIWebView进行访问。

2、进行api访问时,使用 [xxxClient sharedClient] 来获取api客户端,实际上就是一个单态的类,包含了很多api调用

3、上述操作是在 一个Table中的select中完成的,现象是,只要调用 sharedClient,程序在进入系统loop时,就会出现

     EXC_BAD_INST... 那个错误。

 

经过将近2个月的debug后,实在是找不出来原因,但是基本上能够确认是内存问题。所以就找到 Apple的开发文档,专门

找到 MemoryManagment 那一章,仔细地看了一下,其中大体的思想是:

 

1、你创建的对象,属于你,创建(alloc , new , copy 三种方式)

2、属于你的对象,你必须进行释放所有权操作

3、不属于你的对象,你不能够进行释放操作

4、对于某些情况下,你拥有的对象,可以进行延迟释放

 

关于创建对象,有另外一种方式,就是叫做快捷方式:[class classname....] 这种,

比如 [NSString stringWithString:(NSString *)str] 这样

 

采用快捷方式创建的对象,不能够进行任何释放操作,

 

因为 快捷方式一般可以理解成 [[[NSString alloc] initWithString:s] autorelease]

快捷方式采用了第4条思想,即在方法内部,创建的对象,需要作为返回值时,必须使用 autorelease进行返回

 

return [str autorlease]; 方式

 

实例解释:

 

思想1:

-(void) test1{
 NSString *str = [[NSString alloc] initWithString:@"Test1"];
        // ......
        [str release];    // 这个方法创建的,就有这个方法自身释放
}

 

思想3:

 

-(NSString *)getStr{
 NSString *str = [[NSString alloc] initWithString:@"Test1"];
        // ......
        return [str autorelease];     // 思想4  本方法创建的,同时又作为返回值的,必须使用 autorelease
}
 
-(void) test3{
 NSString *s = [self getStr];         // 此处s 一定 不要 释放 因为 s 指向的对象,是由 getStr创建的
        // .......
        // .......
}

找到这些后,开始进行代码改造,代码中还真是有很多问题,由于自己是Java出身,在方式上还是有一些不同的。

 

经过修改后的代码简介多了,但是还是不能够执行,发现内存问题还是存在。

 

在昨天的时候,这个工程进行 init 字符串的查找,找到了一个问题,就是串联调用,比如这种

 

NSURLRequest *req =

    [[NSURLRequest alloc] initWithURL:[[NSURL alloc] initWithString:@"http://www.google.cn/m"]];

 

上述的代码看上去没什么问题,可能会有很多Java开发人员也是类似这么写,但是仔细想想,NSURL怎么释放

 

根么没法释放,那么这种可以使用快捷方式进行改进, [NSURL URLWithString:@"http://www.google.cn/m"]

 

这样就不用担心释放问题了。

 

关于我的程序最后的解决方式:直接重写了 xxxClient这个类,用另一个替换,一步一步地实现方法,把内存管理规则用上

 

真的可以用了,但是为什么原来的不能够用,还是没有找到原因,最终还是认为内存问题吧