【问题标题】:Objective C alloc/release errorObjective C 分配/释放错误
【发布时间】:2011-08-03 14:22:26
【问题描述】:

我有以下问题:

在标题中;

GDataXMLDocument *doc;
NSString *xmlBody;
@property (nonatomic,copy) NSString *xmlBody;
@property (nonatomic,retain) GDataXMLDocument *doc;

在米

#import "tchLoader.h"
#import "Variable.h"
#import "DisplayVariable.h"
@implementation tchLoader
@synthesize responseXMLData,lastLoadedResponseXMLData;
@synthesize conn;
@synthesize doc;
@synthesize xmlBody;


- (void)loadXML:(id<tchLoaderDelegate>)delegate {
    NSString *theBaseXML= @"some xml code here"
    if (self.xmlBody==nil){     
        self.xmlBody=theBaseXML;
    }
    _delegate = delegate;
    /*
    SCNetworkReachabilityFlags flags;
    SCNetworkReachabilityRef reachability =  SCNetworkReachabilityCreateWithName(NULL, [@"www.alues.com" UTF8String]);
    SCNetworkReachabilityGetFlags(reachability, &flags);

        // The reachability flags are a bitwise set of flags that contain the information about
        // connection availability
    BOOL reachable = ! (flags & kSCNetworkReachabilityFlagsConnectionRequired);
    */
    NSString *soapMessage =self.xmlBody;    
    NSURL *url = [NSURL URLWithString:@"https://area.tch-values.com/soapmwp/mws"];
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    NSString *msgLength = [NSString stringWithFormat:@"%d", [soapMessage length]];
    [request addValue: @"text/xml; charset=utf-8" forHTTPHeaderField:@"Content-Type"];
    [request addValue: @"http://www.tch-values.com/webservice" forHTTPHeaderField:@"SOAPAction"];
    [request addValue: msgLength forHTTPHeaderField:@"Content-Length"];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody: [soapMessage dataUsingEncoding:NSUTF8StringEncoding]];

    if ([NSURLConnection canHandleRequest:request] && true) {
        self.conn = [[NSURLConnection alloc ]initWithRequest:request delegate:self];
        if (self.conn) {
            self.responseXMLData = [NSMutableData data];
        }
    }
}

-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
    NSLog(@"ERROR with theConenction");
    [self.doc release];
    [self.conn release];
    [self.responseXMLData release];
}

- (void)connectionDidFinishLoading:(NSURLConnection *)connection {

    NSLog(@"DONE. Received Bytes: %d", [self.responseXMLData length]);  

        //[self.conn release];
    if ([_delegate respondsToSelector:@selector(xmlDidFinishLoading)]) {
        [_delegate xmlDidFinishLoading];
    }
}

-(void)insertAnswers: (NSMutableArray*) answeredVariables{



    for (Variable * variable in answeredVariables)
    {
        NSInteger pageID=[variable pageId];
        //NSMutableArray *answers=[NSMutableArray arrayWithCapacity:[[variable variableValues] count]];
        NSString *path = [NSString stringWithFormat:@"//inferenceresponse/state/variable[pageId=%d]/valuedefinition",pageID];
        NSArray *valueElement = [doc nodesForXPath:path error:nil];
        GDataXMLElement *valueDefinitionElement;

        if (valueElement.count > 0) {           
            valueDefinitionElement= (GDataXMLElement *) [valueElement objectAtIndex:0];
        }

        GDataXMLElement * sourceElement = [GDataXMLNode elementWithName:@"source"];
        [sourceElement addAttribute:[GDataXMLNode attributeWithName:@"type" stringValue:@"ask user"]];  
        GDataXMLElement * timeStampElement = [GDataXMLNode elementWithName:@"timestamp" stringValue:@"12345"];
        [sourceElement addChild:timeStampElement];      
        GDataXMLElement * assignmentElement = [GDataXMLNode elementWithName:@"assignmentnumber" stringValue:@"6"];

        for(NSString *answer in variable.variableValues){
            GDataXMLElement * variableValueElement = [GDataXMLNode elementWithName:@"variablevalue"];
            [variableValueElement addAttribute:[GDataXMLNode attributeWithName:@"value" stringValue:answer]];
            [valueDefinitionElement addChild:variableValueElement];
        }

        [valueDefinitionElement addChild:sourceElement];
        [valueDefinitionElement addChild:assignmentElement];    
    }

        NSData *xmlData = self.doc.XMLData;
        NSString *theXML = [[NSString alloc] initWithBytes:[xmlData bytes] length:[xmlData length] encoding:NSUTF8StringEncoding];  
        theXML =[theXML stringByReplacingOccurrencesOfString:@"inferenceresponse" withString:@"inferencerequest"];
        theXML =[theXML stringByReplacingOccurrencesOfString:@"<SOAP-ENV:Envelope xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\">" withString:@"<SOAP-ENV:Envelope  xmlns:xsd=\"http://www.w3.org/2001/XMLSchema\" xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" xmlns:SOAP-ENC=\"http://schemas.xmlsoap.org/soap/encoding/\" SOAP-ENV:encodingStyle=\"http://schemas.xmlsoap.org/soap/encoding/\" xmlns:SOAP-ENV=\"http://schemas.xmlsoap.org/soap/envelope/\"> "];
        theXML =[theXML stringByReplacingOccurrencesOfString:@"xmlns=\"\"" withString:@"xmlns=\"http://www.tch-values.com/xml/webservice\""];       
        theXML =[theXML stringByReplacingOccurrencesOfString:@"<state goalreached=\"false\">" withString:@"<state goalreached=\"false\"> <value>PlanKB</value> <goalvariable>myGoal</goalvariable> "];  
        self.xmlBody=theXML;
        [theXML release];
        //[self.doc release];
        NSLog(self.xmlBody);        
}

- (NSMutableArray*)variablesForPageID:(NSString*)pageID {
    NSMutableArray *variables = nil; 
    if (self.responseXMLData) {
        variables = [NSMutableArray arrayWithCapacity:10];
        NSData *xmlData = self.responseXMLData;
        NSError *error;
        self.doc=nil;
        doc = [[GDataXMLDocument alloc] initWithData:xmlData options:0 error:&error];
        if (self.doc == nil) { 
            return nil;
        }

        NSArray *status = [doc nodesForXPath:@"//inferenceresponse/state[@goalreached='true']" error:nil];
        if([status  count]==1){
            self.xmlBody=nil;
            Variable *variable=[[Variable alloc] init];

            NSString *path = [NSString stringWithFormat:@"//inferenceresponse/state/displayvariables/display[@isDisplayShown='false']"];
            NSArray *displayVariablesElements = [doc nodesForXPath:path error:nil];
            NSMutableArray *disps=[[NSMutableArray alloc] init];

            if(displayVariablesElements.count >0){          
                for(GDataXMLElement *disElement in displayVariablesElements){

                    DisplayVariable *disVar=[[DisplayVariable alloc] init];
                    NSArray *disPageid = [disElement nodesForXPath:@"@displayPageId" error:nil];
                    GDataXMLElement *Pageid = (GDataXMLElement *) [disPageid objectAtIndex:0];
                    disVar.displayPageId =Pageid.stringValue;

                    NSArray *disName = [disElement nodesForXPath:@"displayname" error:nil];
                    if(disName.count >0){
                        GDataXMLElement *disNam = (GDataXMLElement *) [disName objectAtIndex:0];
                        disVar.displayName =disNam.stringValue;
                    }

                    NSArray *disValue = [disElement nodesForXPath:@"displayvalue" error:nil];
                    if(disValue.count >0){
                        GDataXMLElement *disVal = (GDataXMLElement *) [disValue objectAtIndex:0];
                        disVar.displayValue =disVal.stringValue;
                    }

                    NSArray *disId = [disElement nodesForXPath:@"@id" error:nil]; 
                    GDataXMLElement *disIdEl = (GDataXMLElement *) [disId objectAtIndex:0];
                    disVar.pageId =[disIdEl.stringValue  intValue];

                    [disps addObject:disVar];
                    [disVar release];
                }
                variable.displayVariables=disps;
                [disps release];
            }   
            variable.lastVariableofConsultation=YES;
            [variables addObject:variable];
            [variable release];
        }       
            else{
                NSArray *inferenceMembers = [doc nodesForXPath:@"//inferenceresponse/state/variable[not(valuedefinition/variablevalue)]" error:nil];
                  for (GDataXMLElement *variableElement in inferenceMembers) {
                        Variable *variable=[[Variable alloc] init];
                        NSArray *items = [variableElement nodesForXPath:@"domaindefinition/domain/enumType/domainitem" error:nil];
                        NSMutableArray *domainItems = [NSMutableArray arrayWithCapacity:items.count];

                        for (int i=0; i<items.count;i++) {
                            GDataXMLElement *domainItem = (GDataXMLElement *) [items objectAtIndex:i];
                            [domainItems addObject:domainItem.stringValue];
                        }   
                        variable.domainItems=domainItems;               
                        NSArray *names = [variableElement nodesForXPath:@"name/@name" error:nil];

                        if (names.count > 0) {
                            GDataXMLElement *nameElement = (GDataXMLElement *) [names objectAtIndex:0];
                            variable.variableName = nameElement.stringValue;
                        }
                        NSArray *pageId = [variableElement nodesForXPath:@"pageId" error:nil];


        }
    }
    return variables;   
}


- (void)dealloc {

    [responseXMLData release] ;
    [lastLoadedResponseXMLData release] ;
    [conn release];
    [doc release];
    [xmlBody release];
    [super dealloc];
}


@end


#import "tchLoader.h"
#import "Variable.h"
#import "DisplayVariable.h"
@implementation tchLoader
@synthesize responseXMLData,lastLoadedResponseXMLData;
@synthesize conn;
@synthesize doc;
@synthesize xmlBody;

如果我 [theXML release] 它会崩溃,如果我不释放 theXML 那么它会完美运行,但我在模拟器 Instruments 工具中看到内存泄漏。 (我在这段代码中也看到了很多内存泄漏,但无法通过instrumnets 工具弄清楚发生了什么)

【问题讨论】:

  • 什么是 NSString *newXML = [[NSString alloc] initwith someobjects];以及它包含什么样的价值
  • 也许你在其他地方有一个额外的版本,额外的保留平衡它。
  • 发布崩溃。您显示的代码在概念上是正确的;正如 Control-V 所说,有关该初始化的详细信息会有所帮助。
  • 你正在分配它,访问者正在复制它,然后你正在释放它。原版不保留,newXML 发布后引用不好
  • 你应该避免写 NSLog(self.xmlBody),而应该写 NSLog(@"%@",self.xmlBody)。如果 xmlBody 的字符串在其中的任何位置包含“%@”,则日志将崩溃。

标签: iphone objective-c ios


【解决方案1】:

这看起来不对:

[doc release];

为什么要释放由属性管理的对象?

在您的@synthesize 语句中将它们更改为:

@synthesize doc = doc_;
@synthesize xmlBody = xmlBody_;

然后修复所有产生的错误以通过属性,仅在 dealloc 中释放属性。

编辑:

你说它在发布 XML 时会崩溃。这段代码是错误的:

NSString *theXML = [[NSString alloc] initWithBytes:[xmlData bytes] length:[xmlData length] encoding:NSUTF8StringEncoding];  
        theXML =[theXML stringByReplacingOccurrencesOfString:@"inferenceresponse" withString:@"inferencerequest"];
[theXML release];

您分配一个字符串,用“stringByReplacing...”调用替换该变量,并使用自动释放的字符串,然后尝试释放自动释放的结果字符串,这将崩溃。当你不需要在你所在的方法之后保留一个字符串时,总是使用自动释放。正确的代码是:

 NSString *theXML = [[[NSString alloc] initWithBytes:[xmlData bytes] length:[xmlData length] encoding:NSUTF8StringEncoding] autorelease];  
            theXML =[theXML stringByReplacingOccurrencesOfString:@"inferenceresponse" withString:@"inferencerequest"];

并取出 [theXML release] - 不会有泄漏。

我认为你真的应该尽快改用 ARC……它会让你避免很多这样的误解。

【讨论】:

  • tnx 你能解释一下这是什么意思吗? synthesize doc = doc_ 我将我的类更改为正常而不是单例但仍然是相同的错误..我想释放它,因为该类处理互联网连接并且不想为每个连接重新分配和创建类..我应该只取消对象?
  • 这是一个非常常见的约定。 synthesize 实例变量在语句的 rhs(右手边)上给出名称。它可以帮助您和其他代码读者提醒自己,他们正在直接访问 ivar,而不是使用属性 getter/setter 来访问它。 --- 我的偏好是doc = _doc(Xcode 4.2 将完成该约定)
  • 理论上苹果声明前导“_”仅供苹果使用,你不应该使用它们......实际上苹果不会以此为基础拒绝,正如你所说,XCode甚至可以完成事情那样……但我还是喜欢把它们放在最后。我也觉得那样他们不那么丑。
【解决方案2】:

如果你想释放一个 ivar/property(retain),这不是如何去做的:

[self.doc release];

改为:

self.doc = nil;

【讨论】:

  • 对不起,上面哪个是正确的?也有人说如果我通过财产获得物品,我不应该释放它们?
【解决方案3】:

单例对象的一个​​“问题”是它们似乎会泄漏。如果您创建一个对象并且从不销毁它,Instruments 会认为这是一个泄漏,即使您的意图是永远不会释放它。

【讨论】:

  • 问题不是泄漏,但是如果我释放它就会崩溃,这就是问题所在。如果我不释放它,那么我不释放我正在分配的内容是违反内存规则的
  • @XDeveloper 如果你发布它,那么它就不是单例了。
  • 但是我没有释放我在标题中声明并合成的 xmlBody,我释放了我刚刚在方法中创建的对象。所以 Singleton 意味着我不能在其方法中以任何方式释放“任何”对象?
  • 显然你应该释放那些“一次性”对象。
  • 单例不会显示为泄漏,泄漏工具不会将静态变量显示为泄漏。如果它确实出现在泄漏中,你不是写了一个单例,而是一个你管理不善的类。
【解决方案4】:
NSData *xmlData = doc.XMLData;
newXML = [[NSString alloc] initWithBytes:[xmlData bytes] length:[xmlData length] 
encoding:NSUTF8StringEncoding];

你的 newXML 是什么?它是 ivar 并合成并保留它吗?如果是,编译器将自动生成 getter 和 setter 方法。

NSData *xmlData = doc.XMLData;
self.newXML = [[NSString alloc] initWithBytes:[xmlData bytes] length:[xmlData length] 
encoding:NSUTF8StringEncoding];
self.timestamp = nil;

如果它不是属性,那么

NSString* newXML = [[NSString alloc] initWithBytes:[xmlData bytes] length:[xmlData length] 
encoding:NSUTF8StringEncoding];   
self.xmlBody=newXML;   
[newXML release]; 

【讨论】:

  • 然后它是一个 ivar,然后尝试使用我在上面“如果它不是属性”下已经给出的第二个代码,仪器不应该抱怨泄漏。
  • 您是否故意删除了编码?如果不是那与我的代码相同,它会崩溃吗?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-07
  • 1970-01-01
  • 1970-01-01
  • 2011-01-11
  • 1970-01-01
相关资源
最近更新 更多