-2

我对 Objective-C 很陌生,并且UITableView在异步调用后更新我的问题。我有一个从NSMutableArray;填充的表格视图 我从 .net Web 服务的 JSON 响应中填充数组。我正在使用wsdl2objc从 Web 服务获取 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 回答