2

我正在创建一个应用程序,它从服务器获取 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;
    }

我为冗长的代码道歉,我只是想确保我得到了所有的细节。请提出任何你需要澄清的问题,我现在真的很困惑,为什么它永远不会进入如果没有互联网连接,则创建单元格的功能。

4

2 回答 2

2

几个反应:

  1. 你的fileExistsAtPath看起来不太对。当然,您应该具有完全合格的路径,例如:

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

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

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

  3. 除了我之前的观点之外,您connectionDidFinishLoading似乎没有发出reloadData对表格的调用,因此您似乎总是会看到以前的数据。连接完成后,应connectionDidFinishLoading调用reloadData.UITableView

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

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

于 2013-07-24T17:36:11.657 回答
0

找到了我的解决方案。这

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

仅位于“connectionDidFinishLoading:”函数中,因此如果没有互联网连接,则永远不会设置数据源。

我真的很感谢大家在这个问题上的帮助,并且我已经根据这些建议编辑了很多代码以使其更好地工作。谢谢!

于 2013-07-24T18:51:16.577 回答