-1

我正在尝试使用调度队列中的全局 NSMutableDictionary 。但是,这些项目不断返回 NULL。

我要做的是使用 dispatch_queue 访问外部 json 文件,然后使用此信息填充 UITableView。

这就是我所拥有的

vc.h:

@interface viewcontroller {
 NSMutableDictionary *jsonArray;
}

vc.m:

    #define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0) //1
    #define jsonTest [NSURL URLWithString:@"http://www.sometest.com/test.php"]

    -(void)viewDidLoad {
      dispatch_async(kBgQueue, ^{
            NSData* data = [NSData dataWithContentsOfURL:
                            jsonTest];
           [self performSelectorOnMainThread:@selector(fetchedData:)
                                   withObject:data waitUntilDone:YES];
            // if I run the log here, I can access jsonArry and the log prints correctly
            NSLog(@"City: %@", [jsonArray objectForKey:@"city"];
        });
    }

    -(NSMutableDictionary *)fetchedData:(NSData *)responseData {

        NSError *error;
        jsonArray = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
        return jsonArray;
    }

/********************* Table formatting area **********************/

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (tableView == self.ipTable) { 
        if ([ipArray count] == 0){
            return 1;
        } else { // meta table
            return [ipArray count];
        }
    } else { // IP Meta Data
        return [jsonArray count];
    }
}

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


    if (tableView == self.myTable) {
        NSString *CellIdentifier = NULL;
        if ([ipArray count] == 0) {
            CellIdentifier = @"No Cells";
        } else {
            CellIdentifier = @"IP Cell";
        }

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        }

        if ([ipArray count] == 0)
        {
            [cell.textLabel setText:NSLocalizedString(@"None Found", nil)];
            return cell;

        } else {

        IPAddr *theip = [ipArray objectAtIndex: [indexPath row]];
        NSString *theipname = [theip ipName];
        if ([theipname isEqualToString:@""]) {
            [cell.textLabel setText: [theip ipNum]];
            [cell.detailTextLabel setText:NSLocalizedString(@"noName", nil)];
        } else {
            [cell.textLabel setText: [theip ipName]];
            [cell.detailTextLabel setText: [theip ipNum]];
        }
        return cell;
        }

    } else { // meta table

        static NSString *CellIdentifier = @"metaCell";

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

        if (cell == nil) {
            cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
        }

        // jsonArray content would go here to fill the cells.
        /******************** something here to fill the cells using jsonArray ********************/
        return cell;
    }

} // END UITAbleViewCell

如果我访问队列中的 jsonArray,它会返回正常并打印城市的日志。但是,如果我尝试在队列外使用它,它会返回 NULL。

我想弄清楚发生了什么,有什么想法吗?

我需要在同一个视图中以不同的方法使用 jsonArray,所以我需要它是全局的。

4

3 回答 3

0

我相当确定问题是在numberOfRowsInSection后台 线程完成并填充. 因此,当后台线程完成时,您必须重新加载表视图:cellForRowAtIndexPathjsonArray

- (void)viewDidLoad
{
    [super viewDidLoad];

    dispatch_async(kBgQueue, ^{
        NSData *data = [NSData dataWithContentsOfURL:jsonTest];
        NSError *error;
        NSArray *tmpArray = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
        dispatch_sync(dispatch_get_main_queue(), ^{
            // Assign new data to data source and reload the table view:
            jsonArray = tmpArray;
            [self.metaTableView reloadData];
        });
    });
}

所以表格视图最初是空的,稍后在数据到达时重新加载。

于 2013-08-22T17:47:53.773 回答
0

jsonArray只是一个实例变量,而不是一个属性。因此,将对象分配给它并不会保留它,并且一旦程序返回到运行循环,对象就可能被释放。我建议用and
替换 iVar ,并通过 EDIT 将对象分配给它@property (strong) NSMutableDictionary *jsonArray;@synthesize jsonArray;self.jsonArray = ...
(请参阅下面 Martin R 的评论):
因此,如果您使用 ARC,则将对象分配给它不会保留它,并且对象可能会被释放一旦程序返回到运行循环。
在这种情况下,我建议将 iVar 替换为@property (retain) NSMutableDictionary *jsonArray;and @synthesize jsonArray;,并将对象分配给它self.jsonArray = ...

于 2013-08-22T05:14:45.037 回答
0

尝试通过 nsnotification 调用另一种方法(使用您的 jsonarray)...我不确定是否有其他想法/方法可以做到这一点。但我正在展示我的想法。

将此代码放入您的 fetchedData 方法中,

NSNotificationCenter *nc = [NSNotificationCenter defaultCenter];
            [nc addObserver:self selector:@selector(someMethod:) name:@"JSonDownloaded" object: jsonArray];
             [[NSNotificationCenter defaultCenter] postNotificationName:@"JSonDownloaded" object: jsonArray];

-(void)someMethod:(NSNotification *)nspk
{
    NSLog(@"%@",nspk.object);
//Only after this you can able to access the jsonArray.
}

不要忘记注销观察者。

于 2013-08-22T04:40:57.880 回答