【问题标题】:Parsing YouTube JSON解析 YouTube JSON
【发布时间】:2014-08-02 01:33:09
【问题描述】:

我在解析来自 YouTube 的 JSON 时遇到问题。我正在尝试获取标题、videoId 和默认缩略图 URL。我之前已经解析过 JSON,但是我在从中获取我想要的东西时遇到了问题。

这是我的代码。它在NSDictionary* snippet = [item objectForKey:@"snippet"]; 上出现无法识别的选择器错误而崩溃,错误是-[__NSCFString objectForKey:]: unrecognized selector sent to instance 0x108781b0

#define kBgQueue dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)
#define storeURL [NSURL URLWithString: @"https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=25&playlistId=UUkfYL7q5G8CYtZgtSAwmwzw&key=AIzaSyBS4do208_KPGHAhszfVkHadSvtfSgr7Mo"]

#import "KFBYoutubeVideosTableViewController.h"
#import "SVProgressHUD.h"
#import "Reachability.h"
#import "TSMessage.h"
#import "TSMessageView.h"

@interface KFBYoutubeVideosTableViewController ()

@end

@implementation KFBYoutubeVideosTableViewController
@synthesize title, videoID, thumbURL, url, titleArray, videoIDArray, thumbArray;

- (id)initWithStyle:(UITableViewStyle)style
{
    self = [super initWithStyle:style];
    if (self) {

    }
    return self;
}

- (void)viewDidLoad
{
    [super viewDidLoad];

    [[SVProgressHUD appearance]setHudBackgroundColor:[UIColor blackColor]];
    [[SVProgressHUD appearance]setHudForegroundColor:[UIColor whiteColor]];
    [SVProgressHUD showWithStatus:@"Loading"];

    Reachability *networkReachability = [Reachability reachabilityForInternetConnection];
    NetworkStatus networkStatus = [networkReachability currentReachabilityStatus];

    if(networkStatus == NotReachable)
    {
        [TSMessage showNotificationWithTitle:@"Network Error" subtitle:@"No active network connection!" type:TSMessageNotificationTypeError];
        [SVProgressHUD dismiss];
    }

    self.title = @"KFB Videos";

    self.tableView = [[UITableView alloc]initWithFrame:CGRectZero style:UITableViewStyleGrouped];
    self.tableView.backgroundColor = [UIColor darkGrayColor];

    url = [NSURL URLWithString:@"https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=25&playlistId=UUkfYL7q5G8CYtZgtSAwmwzw&key=AIzaSyBS4do208_KPGHAhszfVkHadSvtfSgr7Mo"];

    dispatch_async(kBgQueue, ^{
        NSData *data = [NSData dataWithContentsOfURL:url];
        if (data == nil)
        {
            NSLog(@"data is nil");
        }
        else
        {
            [self performSelectorOnMainThread:@selector(fetchedData:) withObject:data waitUntilDone:YES];
        }
    });
}

- (void)viewDidDisappear:(BOOL)animated
{
    [SVProgressHUD dismiss];
}

- (void)fetchedData:(NSData *)responseData
{
    NSError *error;
    titleArray = [[NSMutableArray alloc]init];
    videoIDArray = [[NSMutableArray alloc]init];
    thumbArray = [[NSMutableArray alloc]init];

    NSArray *json = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
    NSLog(@"%@", json);

    for (NSDictionary *item in json)
    {
        NSDictionary* snippet = [item objectForKey:@"snippet"];
        title = [snippet objectForKey:@"title"];
        videoID = [[snippet objectForKey:@"resourceId"] objectForKey:@"videoID"];
        thumbURL = [[[snippet objectForKey:@"thumbnails"] objectForKey:@"default"] objectForKey:@"url"];

        [titleArray addObject:title];
        [videoIDArray addObject:videoID];
        [thumbArray addObject:thumbURL];
    }

    [self.tableView reloadData];
    [SVProgressHUD dismiss];
}

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    return [titleArray count];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"Cell"];
    if (cell == nil)
    {
        cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:@"Cell"];
        cell.textLabel.font = [UIFont systemFontOfSize:16.0];
    }
    if (cell)
    {
        cell.backgroundColor = [UIColor clearColor];
        cell.textLabel.text = [titleArray objectAtIndex:indexPath.row];
        cell.textLabel.textColor = [UIColor blackColor];
    }
    return cell;
}

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{ 
    NSLog(@"Title: %@, Video ID: %@, Thumbnail URL: %@", [titleArray objectAtIndex:indexPath.row],[videoIDArray objectAtIndex:indexPath.row], [thumbArray objectAtIndex:indexPath.row]);

    [tableView deselectRowAtIndexPath:indexPath animated:YES];
}

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

@end

这是 JSON:

{
    etag = "\"bvxF-DWHx1toJotsdJBeCm43SLs/tyIRY5zDT7R6YEirBFeFh0tVLCw\"";
    items =     (
                {
            etag = "\"bvxF-DWHx1toJotsdJBeCm43SLs/ON_wGC8nyy0H_bqRqQHlA7mXiM0\"";
            id = UUstIg9nSlWxTaKpWq7G0sppJf9oH5NaDE;
            kind = "youtube#playlistItem";
            snippet =             {
                channelId = UCkfYL7q5G8CYtZgtSAwmwzw;
                channelTitle = "Kentucky Farm Bureau";
                description = "Celebrate June as National Dairy Month with a visit to Jericho Acres Dairy Farm in Henry County.";
                playlistId = UUkfYL7q5G8CYtZgtSAwmwzw;
                position = 0;
                publishedAt = "2014-05-22T12:28:03.000Z";
                resourceId =                 {
                    kind = "youtube#video";
                    videoId = VSCr40jERks;
                };
                thumbnails =                 {
                    default =                     {
                        height = 90;
                        url = "https://i1.ytimg.com/vi/VSCr40jERks/default.jpg";
                        width = 120;
                    };
                    high =                     {
                        height = 360;
                        url = "https://i1.ytimg.com/vi/VSCr40jERks/hqdefault.jpg";
                        width = 480;
                    };
                    maxres =                     {
                        height = 720;
                        url = "https://i1.ytimg.com/vi/VSCr40jERks/maxresdefault.jpg";
                        width = 1280;
                    };
                    medium =                     {
                        height = 180;
                        url = "https://i1.ytimg.com/vi/VSCr40jERks/mqdefault.jpg";
                        width = 320;
                    };
                    standard =                     {
                        height = 480;
                        url = "https://i1.ytimg.com/vi/VSCr40jERks/sddefault.jpg";
                        width = 640;
                    };
                };
                title = "Kentucky Farm Bureau Reports June 2014";
            };
        },

【问题讨论】:

    标签: ios json youtube-api


    【解决方案1】:

    如果你仔细看,标题不在 json 响应的底部。这些节点中的每个节点都是一本字典。所以要从你的代码中得到你想要的东西,你必须这样做:

    NSDictionary *json = [NSJSONSerialization JSONObjectWithData:responseData options:kNilOptions error:&error];
    NSArray *items = [json objectForKey:@"items"];
    for (NSDictionary *item in json)
    {
        NSDictionary* snippet = [item objectForKey:@"snippet"];
        title = [snippet objectForKey:@"title"];
        videoID = [[snippet objectForKey:@"resourceId"] objectForKey:@"videoId"];
        thumbURL = [[[snippet objectForKey:@"thumbnails"] objectForKey:@"default"] objectForKey:@"url"];
    }
    

    如果您打算用这些数据做更多的事情,我建议您创建对象并在创建每个对象时解析 json。这样您就可以在将来跟踪其他属性。这样就干净多了。

    【讨论】:

    • 应用程序因 NSDictionary* sn-p = [item objectForKey:@"sn-p"]; 上出现无法识别的选择器错误而崩溃;
    • 我已经更新了我的回复。你得到的 json 对象是一个 NSDictionary 而不是一个数组,所以你首先必须从那里获取 items 数组,然后你可以遍历它。
    • 修复了大部分但videoID为NULL。
    • 我猜这是因为 videoId 不是字符串。
    • 不,因为我写错了密钥,我写了 VideoID 它应该是 videoId 。我在答案中修复了它
    猜你喜欢
    • 2011-11-30
    • 2013-02-12
    • 2015-01-09
    • 2011-05-15
    • 2013-09-02
    • 1970-01-01
    • 2015-11-03
    • 2015-01-10
    • 2013-03-27
    相关资源
    最近更新 更多