ios - 缺乏互联网连接会阻止细胞的创建

标签 ios uitableview plist nsurlconnection

我正在创建一个应用程序,它从服务器获取 JSON 文本并将其转换为机器人锦标赛的比赛时间表。我有自定义单元格,其中填充了我从网站收到的数据,并且它们很好地显示了每个单独匹配的数据。问题是,当我将匹配项放入 .plist 文件(“data.plist”)中时,一旦最初建立了互联网连接,一旦应用程序按顺序被终止,用户不一定需要重新连接到互联网查看当天的比赛日程。我的代码可以完美运行,直到我无法连接到互联网。由于某种原因,一旦互联网连接失败,应用程序永远不会进入创建单元格的功能。请帮忙!!这是我的代码:

    - (void)viewDidLoad
    {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.

        aRequest = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://jrl.teamdriven.us/source/scripts/getElimMatchResultsJSON.php"] cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:15.0];
        aConnection = [[NSURLConnection alloc] initWithRequest:aRequest delegate:self];
        if(aConnection){
            receivedData = [NSMutableData data];
        }
        else{
            UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"No Connection!!" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];

            [alert show];
        }

        paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        jrlDirectory = [paths objectAtIndex:0];
        path = [jrlDirectory stringByAppendingPathComponent:@"data.plist"];

        if (![[NSFileManager defaultManager] fileExistsAtPath:@"data.plist"]) {
            [[NSFileManager defaultManager] copyItemAtPath:[[NSBundle mainBundle]pathForResource:@"data" ofType:@"plist"] toPath:path error:nil];
        }

        dataDict = [[NSMutableDictionary alloc] initWithContentsOfFile:path];    
    }

    - (void)didReceiveMemoryWarning
    {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }



    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{
        // Prevents data from repeating itself

        [receivedData setLength:0];
    }

    - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
        [receivedData appendData: data];
    }

    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
        UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Connection Failed" message:nil delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];

        [alert show];
        NSLog(@"Connection failed! Error - %@ %@", [error localizedDescription], [[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
    }

    -(void)connectionDidFinishLoading:(NSURLConnection *)connection{

        NSLog(@"Success! Received %d bits of data", [receivedData length]);

        // Must allocate and initialize all mutable arrays before changing them

        sweet16 = [[NSMutableArray alloc]init];
        quarterfinals = [[NSMutableArray alloc]init];
        semi = [[NSMutableArray alloc]init];
        finals = [[NSMutableArray alloc]init];
        dict = [[NSMutableDictionary alloc]init];

        // The error is created and can be referred to if the code screws up (example in the "if(dict)" loop)

        NSError *error;
        dict = [NSJSONSerialization JSONObjectWithData:receivedData options:NSJSONReadingMutableLeaves error:&error];
        matchNames = [[dict objectForKey:@"ElimMatchListResults"]allKeys];
        matchNames = [matchNames sortedArrayUsingSelector:@selector(compare:)];

        // Categorize the matches based on the first two letters of their match names

        for (NSString *name in matchNames) {
            if([[name substringToIndex:2]isEqual:@"16"]){
                 [sweet16 insertObject:[[dict objectForKey:@"ElimMatchListResults"] objectForKey:name] atIndex:sweet16.count];
            }
            else if([[name substringToIndex:2]isEqual:@"Q."]){
                 [quarterfinals insertObject:[[dict objectForKey:@"ElimMatchListResults"]objectForKey:name] atIndex:quarterfinals.count];
            }
            else if([[name substringToIndex:2]isEqual:@"S."]){
                [semi insertObject:[[dict objectForKey:@"ElimMatchListResults"]objectForKey:name] atIndex:semi.count];
            }
            else if([[name substringToIndex:2]isEqual:@"F."]){
                [finals insertObject:[[dict objectForKey:@"ElimMatchListResults"]objectForKey:name] atIndex:finals.count];
            }
        }

        headers = [NSArray arrayWithObjects:@"Sweet 16", @"Quarterfinals", @"Semifinals", @"Finals", nil];
        sections = [NSArray arrayWithObjects:sweet16, quarterfinals, semi, finals, nil];

        // If the dictionary "dict" gets filled with data...

        if (dict) {

            [[self tableView]setDelegate:self];
            [[self tableView]setDataSource:self];

            // Now uses data storage so that the user only needs to initially connect to the internet and then they can keep the schedule afterwords

            [dataDict setObject: [NSDictionary dictionaryWithObjectsAndKeys:
                                 [NSArray arrayWithArray:sections], @"sections",
                                 [NSArray arrayWithArray:headers], @"headers",
                                                     nil]
                          forKey:@"Matches"];
             [dataDict writeToFile:path atomically:YES];
        }
        else{
            NSLog(@"%@", error);
        }

    }

    // Set the number of sections based on how many arrays the sections array has within it

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
       return [[[dataDict objectForKey:@"Matches"] objectForKey:@"sections"] count];
    }

    // Set the number of rows in each individual section based on the amount of objects in each array
    //   within the sections array

    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
        return [[[[dataDict objectForKey:@"Matches"] objectForKey:@"sections"] objectAtIndex:section] count];
    }

    // Set headers of sections from the "headers" array

    - (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{
        return [[[dataDict objectForKey:@"Matches"] objectForKey:@"headers"] objectAtIndex:section];
    }

    // Create cells as the user scrolls

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


        NSLog(@"Entered Final Loop");

        static NSString *cellIdentifier = @"Cell";
        CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];

        if(!cell){
            cell = [[CustomCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cellIdentifier];
        }

        cell.matchNum.text = [[[[[dataDict objectForKey:@"Matches"] objectForKey:@"sections"] objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] objectForKey:@"MatchID"];
        cell.red1.text = [NSString stringWithFormat:@"%@",[[[[[dataDict objectForKey:@"Matches"] objectForKey:@"sections"] objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] objectForKey:@"Red 1"]];
        cell.red2.text = [NSString stringWithFormat:@"%@",[[[[[dataDict objectForKey:@"Matches"] objectForKey:@"sections"] objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] objectForKey:@"Red 2"]];
        cell.redScore.text = [NSString stringWithFormat:@"%@", [[[[[dataDict objectForKey:@"Matches"] objectForKey:@"sections"] objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] objectForKey:@"Red Score"]];
        cell.blue1.text = [NSString stringWithFormat:@"%@",[[[[[dataDict objectForKey:@"Matches"] objectForKey:@"sections"] objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] objectForKey:@"Blue 1"]];
        cell.blue2.text = [NSString stringWithFormat:@"%@",[[[[[dataDict objectForKey:@"Matches"] objectForKey:@"sections"] objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] objectForKey:@"Blue 2"]];
        cell.bluescore.text = [NSString stringWithFormat:@"%@", [[[[[dataDict objectForKey:@"Matches"] objectForKey:@"sections"] objectAtIndex:indexPath.section] objectAtIndex:indexPath.row] objectForKey:@"Blue Score"]];


        return cell;
    }

对于冗长的代码,我深表歉意,我只是想确保我了解了所有详细信息。请提出您需要的任何问题,以便澄清,我现在真的很困惑,不知道为什么如果没有互联网连接,它永远不会进入创建单元格的函数。

最佳答案

一些 react :

  1. 您的 fileExistsAtPath 看起来不正确。当然你应该有完全限定的路径,例如:

    if (![[NSFileManager defaultManager] fileExistsAtPath:path]) {
        [[NSFileManager defaultManager] copyItemAtPath:[[NSBundle mainBundle]pathForResource:@"data" ofType:@"plist"] toPath:path error:nil];
    }
    

    我还可能建议您检查 copyItemAtPath 是否成功(返回值或使用 error 参数)。

  2. 我假设您知道在 viewDidLoad 完成之前 data.plist 永远不会成功刷新(因为连接是异步启动的,并且您立即从initWithRequest)。此代码只是加载最后的 data.plist 值,同时检索新数据(尽管存在先前的错误)。这是你的期望吗?

  3. 除了我之前的观点之外,您的 connectionDidFinishLoading 似乎并未对表发出 reloadData 调用,因此您似乎总是会参见之前的数据。连接完成后,connectionDidFinishLoading 应为 UITableView 调用 reloadData

  4. 次要的、不相关的细节,但我可能会在 NSURLConnectionDataDelegate 方法 didReceiveResponse 中初始化 receivedData (并且仅当该响应也成功了)。它并不真正属于 viewDidLoad

  5. 我还鼓励您检查 JSONObjectWithData 是否失败。某些网络故障表现为成功的 NSURLConnection 请求,该请求返返回告错误的 HTML 页面 (!)。该 HTML 页面将无法处理 JSONObjectWithData。如果 JSONObjectWithData 返回 nilerror 对象不是 nil,您可能想要中止解析例程。

关于ios - 缺乏互联网连接会阻止细胞的创建,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17840528/

相关文章:

ios - 类似于 iPhone 相机应用程序的动画,其中捕获的图像落入图片查看器

ios - View Controller Presentation Warning - 同时呈现两个

ios - 更新到 Xcode 8 后出现错误 : "No such module" and "target overrides the ` EMBEDDED_CONTENT_CONTAINS_SWIFT`build setting"

ios - 我是否需要 iOS 设备来测试 PhoneGap Built 应用程序?

swift - UITableView Cell 显示问题

ios - 如何覆盖 UITableView 的功能?

ios - 读取和写入 plist(iPhone 编程)

ios - 如何使用 Swift 为 UITableViewCell 设置动画?

objective-c - 从 PLIST 中获取数据到表 3

iOS 10 - 更改相机、麦克风和照片库的权限导致应用程序崩溃