0

我有表格视图,名称和状态在哪里。当苹果推送通知 (APNS) 到来时,状态会发生变化。但我有这个问题。如果没有收到通知,我该怎么办?或者,如果用户点击此消息的关闭按钮。我尝试使用 ASIHTTPRequest 更新表:

- (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 *device。你能帮我解决这个问题吗?我试试这个,但它没有用:(在你写的地方)

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];

在那个地方。

编辑3:

如果我这样做怎么办:

- (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 方法并获取状态数组会更好。

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

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

4

1 回答 1

2

您在代码中的哪个位置调用[UITableView reloadData]

reloadData从服务器检索到新数据后,您应该调用您的 tableview。由于您的服务器调用是异步的,因此服务器调用将在主线程继续运行时在单独的线程上运行,因此我认为您有以下问题......

- (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


更新

针对您现在statusInt在设备内设置时遇到的问题NSManagedObject

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

这是由于它statusIntNSInteger主要数据类型而不是NSObject预期的[NSManagedObject setValue:forKey:]。从[NSManagedObject setValue:forKey:]的文档中,方法预期参数如下。

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

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

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

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

现在,从技术上讲,status从服务器返回的值可以按原样存储,无需任何转换为NSString​​ . 当您需要检索和使用您的主要数据类型时,int可以使用[NSString intValue]您已经使用过的方法。

尽管最佳实践是使用NSNumberFormatter可用于locale基于数字调整并确保不存在无效字符的 a 。

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
于 2013-07-02T12:15:21.577 回答