-2

私はObjective-Cにかなり慣れていないのでUITableView、非同期呼び出しの後に更新するのに問題があります。からデータが取り込まれたテーブル ビューがありNSMutableArrayます。.net Web サービスからの JSON 応答から配列を設定します。wsdl2objcWeb サービスから JSON を取得するために使用しています。

これが私のコードです:

@interface NewsViewController : UITableViewController <ServiceSoapBindingResponseDelegate>

@property (nonatomic, strong) News *news;
@property (nonatomic, retain) NSMutableArray *newsList;

-(void) updateNewView:(NSMutableArray*) result;
-(void) loadNewsFromRemoteServer;

@end


-(void) viewDidLoad
{
    _newsList = [[NSMutableArray alloc] init];
    [self loadNewsFromRemoteServer];
    [super viewDidLoad];
}

-(void) loadNewsFromRemoteServer
{  
    NSString *customerID = @"xxx";
    NSString *uniqueID = @"xxx";    
    ServiceSoapBinding *bNews = [[ServiceSvc ServiceSoapBinding] retain];
    bNews.logXMLInOut = YES;
    ServiceSvc_GetNews *cRequest = [[ServiceSvc_GetNews new] autorelease];
    cRequest.id_ = customerID;
    cRequest.uniqueId = uniqueID;
    [bNews GetNewsAsyncUsingParameters:cRequest delegate:self];
}


-(void) operation:(ServiceSoapBindingOperation *)operation completedWithResponse:(ServiceSoapBindingResponse *)response
{
    NSArray *responseHeaders = response.headers;
    NSArray *responseBodyParts = response.bodyParts;
    NSMutableArray *newsListFromWebserver = [[NSMutableArray alloc] init];
    for(id header in responseHeaders) {
        // here do what you want with the headers, if there's anything of value in them
    }
    for(id bodyPart in responseBodyParts) {         
        if ([bodyPart isKindOfClass:[SOAPFault class]]) {
            // You can get the error like this:
            //NSLog(@"new list :: RESPONSE FROM SERVER :: %@",((SOAPFault *)bodyPart).simpleFaultString);
            continue;
        }
        //Get News List
        if([bodyPart isKindOfClass:[ServiceSvc_GetNewsResponse class]]) {
            ServiceSvc_GetNewsResponse *body = (ServiceSvc_GetNewsResponse*)bodyPart;
            NSString *nList = body.GetNewsResult;  //JSON FORMAT
            NSLog(@"new list :: RESPONSE FROM SERVER :: nList %@", nList);
            NSDictionary *resultsDictionary = [nList objectFromJSONString] ;
            for (NSDictionary * dataDict in resultsDictionary) {
                News *newNews = [[News alloc] init];
                _news = newNews;
                _news.newsTitle = [NSString stringWithFormat:[dataDict objectForKey:@"Title"]];
                _news.newsBody = [NSString stringWithFormat:[dataDict objectForKey:@"Body"]];
                _news.newsDate = [NSString stringWithFormat:[dataDict objectForKey:@"NewDate"]];
                [newsListFromWebserver addObject:_news];
               [_news release];
            }    
        }
    }   
    [self performSelectorOnMainThread:@selector(updateNewView:) withObject:newsListFromWebserver waitUntilDone:NO];
    [newsListFromWebserver release];
}

-(void) updateNewView:(NSMutableArray*) result
{
    _newsList = result;
    NSLog( @"new list - number of news :: %u", [_newsList count]);
    [self.tableView reloadData];
}

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{    
    static NSString *CellIdentifier = @"Cell";   
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {
        cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
    }    
     cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
    //Get the object from the array.
    News *cNews = [_newsList objectAtIndex:indexPath.row];
    cell.textLabel.text = cNews.newsDate;
    cell.detailTextLabel.text = cNews.newsTitle;
    cell.imageView.image = [UIImage imageNamed:@"bullet.png"];        
    return cell;
}

私のアプリケーションはこれをコンソールに記録します:

2012-09-08 22:36:45.463 xxx[45630:13a03] new list - number of news :: 1
2012-09-08 22:36:45.465 xxx[45630:13a03] *** -[__NSArrayM objectAtIndex:]: message sent to deallocated instance 0x79a3680

の呼び出しに失敗[_newsList objectAtIndex:indexPath.row]tableView:cellForRowAtIndexPath:ます。何か助けはありますか?前もって感謝します

4

2 に答える 2

1

updateNewView:メソッドがメインスレッドで呼び出されるまでに、メソッドでnewsListFromWebserver作成されたオブジェクトはoperation:completedWithResponse:そのメソッドの最後の行で解放され、したがって割り当てが解除されます。この問題を解決する最も簡単な方法は、メイン スレッドでの呼び出しの後に_newsListivarに値を割り当てることです。その場合、引数を削除できることに注意してください。operation:completedWithResponse:updateNewViewresult

updateNewViewまた、メソッドの最初の行にリークがあります。

これがどのように見えるべきかの小さなヒントです:

-(void) operation:(ServiceSoapBindingOperation *)operation completedWithResponse:           (ServiceSoapBindingResponse *)response
{
    // your old parsing code here

    self.newsList = newsListFromWebserver;
    [newsListFromWebserver release];
    [self performSelectorOnMainThread:@selector(updateNewView) withObject:nil waitUntilDone:NO];
}

-(void) updateNewView
{
    NSLog( @"new list - number of news :: %u", [_newsList count]);
    [self.tableView reloadData];
}
于 2012-09-08T23:19:50.980 に答える
0

あなたはARCを使用していないと言います。クラッシュしている理由は、自動解放された値をインスタンス変数に割り当て、それを保持していないためです。

-(void) updateNewView:(NSMutableArray*) result
{
    _newsList = result; // Should release the old and retain the new!
    NSLog( @"new list - number of news :: %u", [_newsList count]);
    [self.tableView reloadData];
}

個人的には、可能な限りプロパティを使用するようにプログラム全体を変更しますが、少なくとも古い値を解放して新しい値を保持する必要があります

-(void) updateNewView:(NSMutableArray*) result
{
    self.newsList = result;
    NSLog( @"new list - number of news :: %u", [_newsList count]);
    [self.tableView reloadData];
}

お役に立てれば!

于 2012-09-08T23:18:26.523 に答える