Сообщение отправлено в нераспределенный экземпляр - PullRequest
0 голосов
/ 18 июля 2011

Я использую TouchXML для разбора элемента в iOS. Я получаю ответ от веб-службы, используя NSInvocationOperation, затем анализирую и отображаю результаты. Все работает нормально, так как фоновый поток отображает результаты в основном потоке, используя [self performSelectorOnMainThread:@selector(displayLoginresult:) withObject:res waitUntilDone:NO];, но затем я получаю сообщение об ошибке:

2011-07-18 11:58:06.108 billsApp[873:7107] *** -[CFString release]: message sent to deallocated instance 0x5d809b0

Код для разбора элемента:

-(LoginResult *) tryLogin:(NSString *)userName withPassword:(NSString*)password{
    NSURL *url = [UrlUtility TryLogin:userName passwordHash:password];
    CXMLDocument *responseObj = [UrlUtility xmlDocWithUrl:url];
    if(responseObj == [NSNull null])
        return [NSNull null];

    CXMLElement *eleUser = [responseObj nodeForXPath:@"//User" error:nil];
    CXMLElement *eleResult = [responseObj nodeForXPath:@"//Result" error:nil]; 
    LoginResultType resultType;
    //NSLog(@"Result: ");
    //NSLog(eleResult );
//  NSLog([[eleResult stringValue] lowercaseString]);
    if ([[[eleResult stringValue] lowercaseString ] isEqualToString: @"successful"]){
        resultType = Successful;
    } else {
        resultType = InvalidUsernameOrPassword;
    }

    LoginResult *res = [[LoginResult alloc] init];
    res.result = resultType;

    for (CXMLElement *resultElement in [responseObj children] ) {
        NSLog([NSString stringWithFormat:@"%@ %@", [resultElement name], [resultElement stringValue]]);
    }

    //todo: fix enum parsing =[LoginResult loginResultTypeStringToEnum: [eleResult  stringValue]];  

    if(eleUser != nil) {
        CXMLElement *eleClientID = [eleUser nodeForXPath:@"ClientID" error:nil];
        CXMLElement *eleCompanyName = [eleUser nodeForXPath:@"CompanyName" error:nil];
        CXMLElement *eleCompanyContact = [eleUser nodeForXPath:@"CompanyContact" error:nil];
        CXMLElement *eleIsAgent = [eleUser nodeForXPath:@"IsAgent" error:nil];
        CXMLElement *eleParentID = [eleUser nodeForXPath:@"ParentID" error:nil];

        NSInteger *clientId = [[eleClientID stringValue] integerValue];
        NSString *companyName = [eleCompanyName stringValue];
        NSString *companyContact = [eleCompanyContact stringValue];
        bool isAgent = [Utils stringToBool:[eleIsAgent stringValue]];
        NSInteger *parentId = [[eleParentID stringValue] integerValue];
        User *user = [[User alloc] initWithData:clientId companyName:companyName companyContact:companyContact isAgent:isAgent parentId:parentId];
        res.user = user;
        // release elements

//      [eleClientID release];
//      [eleCompanyName release];
//      [eleCompanyContact release];
//      [eleIsAgent release];
//      [eleParentID release];

        //release raw values
//      [companyName release];
//      [companyContact release];
    }

//  [eleResult release];
//  [eleUser release];

    return res;
}

Часть меня хочет сказать, что это ошибка в TouchXML, но я нахожу это очень маловероятным. Можно ли как-то отследить ошибку?

РЕДАКТИРОВАТЬ: определения свойств в классе User:

@property (nonatomic, readwrite) NSInteger clientId;
@property (nonatomic, retain) NSString *companyName;
@property (nonatomic, retain) NSString *companyContact;
@property (nonatomic, readwrite) bool isAgent;
@property (nonatomic, readwrite) NSInteger parentId;

И экземпляр инициализируется с помощью:

-(User*)initWithData:(NSInteger *)clientId companyName:(NSString *)company companyContact:(NSString*)contact isAgent:(bool)agent parentId:(NSInteger*)parentId {
    //[self = super init];
    self.clientId= clientId;
    self.companyName= company;
    self.companyContact= contact;
    self.isAgent = agent;
    self.parentId = parentId;
    return self;
}

И класс LoginResult:

@interface LoginResult : NSObject {
    LoginResultType result;
    User *user;

    NSString * const loginResultTypeArray[4];
}

@property (nonatomic, readwrite) LoginResultType result;
@property (nonatomic, retain) User *user;

Ответы [ 2 ]

0 голосов
/ 19 июля 2011

Это был кошмар, чтобы выследить. У меня был метод, который возвращал NSString *, который затем анализировался другим методом для создания XML-документа, а затем был выпущен вторым методом. Мне действительно нужно было автоматически выпустить его в первом методе.

0 голосов
/ 18 июля 2011

Просто попробуй: правильно ли ты сохранил companyName и companyContatct в своем классе User?

EDIT:

Следующая вещь, которую я бы проверил, - loginResultTypeArray. Как ему присваивается строка? Я думаю, что этот совет также будет звучать для вас тривиально, но с таким небольшим количеством кода действительно трудно придумать полезное предложение ...

Не можете ли вы получить представление о , который CFString на самом деле выпускается? Если это не объект с автоматическим выпуском, возможно, трассировка стека может указывать на метод, который отправляет сообщение release ... это было бы очень полезно ...

В противном случае, я бы попытался NSLog некоторые из ваших NSString адресов, чтобы вы могли сравнить их с адресом, который вы нашли в журнале ошибок (и, опять же, попытаться выяснить, какая строка фактически использовалась повторно) после освобождения).

Наконец, другой подход, чтобы выяснить, какая строка используется после удаления, мог бы использовать метод swizzling для замены NSString dealloc на ваш метод, который перед вызовом swizzled dealloc делает некоторую запись объект. Это даст много информации в журнале, но, зная адрес строки, вы легко сможете найти то, что вам нужно. Найдите здесь информацию о метании.

...