0

我有tableview,其中是名称和状态。苹果推送通知(APNS)时状态发生变化。 但我有这个问题。如果通知未到,我该怎么办?或者如果用户点击此消息的关闭按钮。 我尝试使用ASIHTTPRequest更新表:从webserver(ASIHTTPRequest,PHP,mysql)更新iOS TableView单元格中的数据

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *CellIdentifier = @"Cell"; 
    HomePageTableCell *cell = (HomePageTableCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath]; 

    // Configure the cell... 
    NSManagedObject *device = [self.devices objectAtIndex:indexPath.row]; 
    cell.nameLabel.text = [device valueForKey:@"name"]; 

    if ([[device valueForKey:@"status"] isEqualToNumber:@1]) 
    { 
     cell.status.text = @"Not configured"; 
     cell.stav.image = [UIImage imageNamed:@"not_configured.png"]; 
    } 
    if ([[device valueForKey:@"status"] isEqualToNumber:@2]) 
    { 
     //some other states 
    } 

    return cell; 
} 

我尝试这种改变小区之前的状态是载入中...

- (void) getStatus:(NSString *)serialNumber 
{ 
    NSURL *url = [NSURL URLWithString:@"link to my server"]; 

    __block ASIFormDataRequest *request = [ASIFormDataRequest requestWithURL:url]; 
    __weak ASIHTTPRequest *request_b = request; 
    request.delegate = self; 

    [request setPostValue:@"updatedevice" forKey:@"cmd"]; 
    [request setPostValue:serialNumber forKey:@"serial_number"]; //get status of this serial number 

    [request setCompletionBlock:^ 
    { 
     if([self isViewLoaded]) 
     { 
      [MBProgressHUD hideHUDForView:self.view animated:YES]; 
      if([request_b responseStatusCode] != 200) 
      { 
       ShowErrorAlert(@"Comunication error", @"There was an error communicating with the server");      
      } 
      else 
      {          
       NSString *responseString = [request_b responseString]; 
       SBJsonParser *parser = [[SBJsonParser alloc] init]; 
       NSDictionary *result = [parser objectWithString:responseString error:nil]; 

       status = [result objectForKey:@"status"]; 
       NSInteger statusInt = [status intValue]; //change to int value 

       //here I want to change cell status in SQLite, but don't know how 
       //something with indexPath.row? valueForKey:@"status"???     
      } 
     } 
    }]; 
    [request setFailedBlock:^ 
    { 
     if ([self isViewLoaded]) 
     { 
      [MBProgressHUD hideHUDForView:self.view animated:YES]; 
      ShowErrorAlert(@"Error", [[request_b error] localizedDescription]); 

     } 
    }]; 

    [request startAsynchronous]; 
} 

或者是更好的方式来改变我的表视图,如果状态苹果通知没有来或用户没有点击通知消息?谢谢

编辑: 我不知道如何将数据存储到NSManagedObject *设备。你能帮助我吗? 我试试这个,但它没有工作:(你在哪里写的地方)

NSInteger statusInt = [status intValue]; //change to int value 
NSManagedObject *device = [self.devices objectAtIndex:indexPath.row]; 
[device setValue:statusInt forKey:@"status"]; 

EDIT2: 我得到它,但问题是重装表数据

NSString *responseString = [request_b responseString]; 
SBJsonParser *parser = [[SBJsonParser alloc] init]; 
NSDictionary *result = [parser objectWithString:responseString error:nil]; 

NSString *status = [result objectForKey:@"status"]; 
NSInteger statusInt = [status intValue]; //change to int value 
NSManagedObject *device = [self.devices objectAtIndex:indexPath.row]; 
[device setValue:statusInt forKey:@"status"]; //there is problem in save statusInt 

// [设备setValue:@ 5 forKey:@“status”]; //如果我这样做没关系状态是integer16型

第二个问题是在重装表数据。我把它放在这里

[self.tableView reloadData] 

但它在循环中一遍又一遍地重新加载,有什么错?我的事情有无限循环,如果我没有重新加载表格数据的变化将在下一个应用程序加载可见。我认为问题是,我称之为

- (void) getStatus:(NSString *)serialNumber atIndexPath:(NSIndexPath *)indexPath 
{} 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
} 

更好的应该是在viewDidLoad中或viewDidApper,但我不知道该怎么做回路所有设备和呼叫

[self getStatus:[device valueForKey:@"serialNumber"] atIndexPath:indexPath]; 

在那个地方。

EDIT3:

,如果我不喜欢这样写道:

- (void)viewDidLoad 
{ 
    [self updateData]; 
    [self.tableView reloadData]; 
} 
-(void)updateData 
{ 
    NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:@"Device"]; 
    request.returnsDistinctResults = YES; 
    //request.resultType = NSDictionaryResultType; 
    request.propertiesToFetch = @[@"serialNumber"]; 

    NSArray *fetchedObjects = [self.managedObjectContext 
           executeFetchRequest:request error:nil]; 

    NSArray *result = [fetchedObjects valueForKeyPath:@"serialNumber"]; 

    //there I get all serialNumbers of my devices and than I call method getStatus and get "new" status and than update it in Core Data. 
} 

是好办法来解决这个问题呢?如果我只调用一次getStatus方法并获取状态数组,我认为会更好。

也许我可以将所有serialNubers设置为一个变量('xxx','yyyy','zzz'),然后在服务器上执行SELECT * FROM设备WHERE serialNumber(serialNuber)。

您认为这可行吗?我没有经验如何将数据从数组转换为字符串,例如('array_part1','array_part2'....)

+0

请正确标记您的问题;例如,了解平台(OSX或iOS)比了解用于开发程序的IDE更重要。 – trojanfoe

+0

好的,对不起没有问题。我会做的。 – Miras

回答

2

在代码中的哪个位置,请拨打[UITableView reloadData]

一旦您从服务器检索到新数据,您应该在您的tableview上调用reloadData。当你的服务器调用是异步服务器调用,而主线程继续在一个单独的线程运行,因此,我相信你有以下问题......

- (void) ... 
{ 
    [self getStatus:@"SERIAL_NUMBER"]; 
    [self reloadData]; // This will be called before the async server call above has finished 
} 

因此你重装的原始数据,因此新数据可能在几秒钟后加载,不会显示。

若要解决此问题,请调整[getStatus:]方法以调用[UITableView reloadData]方法服务器响应。

[request setCompletionBlock:^ 
{ 
    if([self isViewLoaded]) 
    { 
     [MBProgressHUD hideHUDForView:self.view animated:YES]; 
     if([request_b responseStatusCode] != 200) 
     { 
      ShowErrorAlert(@"Comunication error", @"There was an error communicating with the server"); 

     } 
     else 
     {     

      NSString *responseString = [request_b responseString]; 
      SBJsonParser *parser = [[SBJsonParser alloc] init]; 
      NSDictionary *result = [parser objectWithString:responseString error:nil]; 

      status = [result objectForKey:@"status"]; 
      NSInteger statusInt = [status intValue]; //change to int value 

      // Store the server response in NSManagedObject *device, 
      // which will be used as the data source in the tableView:cellForRowAtIndexPath: method 

      // Once stored, check the tableview isn't NULL and therefore can be accessed 
      // As this call is async the tableview may have been removed and therefore 
      // a call to it will crash 
      if(tableView != NULL) 
      { 
        [tableView reloadData]; 
      }   
     } 
    } 
}]; 

ASIHTTPRequest也不再由开发商的支持,我建议你看看AFNetworking


更新

响应于你现在与NSManagedObject

NSManagedObject *device = [self.devices objectAtIndex:indexPath.row]; 
[device setValue:statusInt forKey:@"status"]; //there is problem in save statusInt 

这是作为statusInt引起在装置内设置statusInt遇到的问题是NSInteger,其是伯数据类型而不是NSObject,如[NSManagedObject setValue:forKey:]所预期的那样。从[NSManagedObject setValue:forKey:]的文档中,方法的预期参数如下。

- (void)setValue:(id)value forKey:(NSString *)key 

因此你需要传递,在这种情况下,NSNumberNSInteger的问题在于,它仅仅是基于当前系统的最大int数据类型的dynamic typedef。从NSInteger的实现中,您可以看到抽象。

#if __LP64__ 
typedef long NSInteger; 
#else 
typedef int NSInteger; 
#endif 

如果你当前的系统是64位,它会使用更大的long数据类型。

现在,技术上来说,服务器返回的status值可以按原样存储,而不需要作为NSString进行任何转换。当您需要检索并使用int的主数据类型时,可以使用已使用的[NSString intValue]方法。

尽管最好使用NSNumberFormatter,它可以用于基于locale的数字调整并确保不存在无效字符。

NSString *status = [result objectForKey:@"status"]; 
NSNumberFormatter * f = [[NSNumberFormatter alloc] init]; 
NSNumber * statusNumber = [f numberFromString:status]; 
NSManagedObject *device = [self.devices objectAtIndex:indexPath.row]; 
[device setValue:statusNumber forKey:@"status"]; 

要当你想使用的int你的代码中,只需调用[NSNumber intValue]检索主数据类型。

NSNumber *statusNumber = [device objectForKey:@"status"]; 
int statusInt = [statusNumber intValue]; 

至于你用无限循环有问题,这是由所谓的[... getStatus:atIndexPath:],其中包含了方法调用reloadData,从[UITableView tableView:cellForRowAtIndexPath:]内造成的。

这是因为reloadData实际上称为[UITableView tableView:cellForRowAtIndexPath:]。 因此你的代码继续去为以下...

Initial UITableView data load -> tableView:cellForRowAtIndexPath: -> getStatus:atIndexPath: -> Server Response -> reloadData -> tableView:cellForRowAtIndexPath: -> getStatus:atIndexPath: -> Server Response -> reloadData -> ... 

不幸的是,你不能只是空军一号细胞更新,您有权要求UITableView使用reloadData重新加载所有数据。因此,如果可能,您需要调整服务器以返回设备的唯一ID,以便您只能调整NSManagedObject内的更新设备。

对于getStatus方法的建议更改可以仅使用serialNumber,如果它作为密钥存储在NSManagedObject内。

- (void) getStatus:(NSString*)serialNumber 
+0

我编辑我的问题与另一个问题。感谢那个AFNetworking,我会研究它。谢谢 – Miras

+0

在你的代码中,你使用CoreData来设置设备?我看到你有一个名为'devices'的'NSArray',它包含'NSManagedObject'。 '[self.devices objectAtIndex:indexPath.row]'在[self getStatus:]'方法的服务器响应中不起作用的原因是'indexPath.row'来自'[UITableViewDelegate tableView:cellForRowAtIndexPath:] '因此'indexPath.row'在服务器响应代码中是'NULL'。请阅读[CoreData](http://developer.apple.com/library/mac/#documentation/cocoa/Conceptual/CoreData/cdProgrammingGuide.html)和[NSManagedObject](http://bit.ly/17oYVs8) –

+0

我更新我的问题,现在我知道如何保存,但有新问题。 – Miras