【问题标题】:iOS (iPhone/iPad) SDK - Using a JSON parser with Twitter's user_timelineiOS (iPhone/iPad) SDK - 使用 JSON 解析器和 Twitter 的 user_timeline
【发布时间】:2011-10-16 20:28:20
【问题描述】:

好的,这是我的代码:

(应用程序名称)AppDelegate.h:

    #import <UIKit/UIKit.h>

    @class TwitterViewContoller;

    @interface <appname>AppDelegate : NSObject <UIApplicationDelegate> {
        UIWindow *window;
        UITabBarController *rootController;
        TwitterViewContoller *viewController;
        NSMutableData *responseData;
        NSMutableArray *tweets;
    }

    @property (nonatomic, retain) IBOutlet UIWindow *window;
    @property (nonatomic, retain) IBOutlet UITabBarController *rootController;
    @property (nonatomic, retain) IBOutlet TwitterViewContoller *viewController;
    @property (nonatomic, retain) NSMutableArray *tweets;

    @end

(应用程序名称)AppDelegate.m:

    #import "<appname>AppDelegate.h"
    #import "TwitterViewContoller.h"
    #import "SBJson.h"

    @implementation <appname>AppDelegate

    @synthesize window = _window;
    @synthesize rootController;
    @synthesize viewController;
    @synthesize tweets;

    #pragma mark -
    #pragma mark Application lifecycle

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Override point for customization after application launch. 
        responseData = [[NSMutableData data] retain];
        tweets = [NSMutableArray array];

        NSURLRequest *request = [NSURLRequest requestWithURL:
                         [NSURL URLWithString:@"http://api.twitter.com/1/statuses/user_timeline.json?screen_name=USER_NAME_ID"]];

        [[NSURLConnection alloc] initWithRequest:request delegate:self];
        //[window addSubview:rootController.view];  
        //[window makeKeyAndVisible];
        return YES;
    }

    #pragma mark NSURLConnection delegate methods
    - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
        [responseData setLength:0];
    }

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

    - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
    }

    - (void)connectionDidFinishLoading:(NSURLConnection *)connection {
        [connection release];
        NSString *responseString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
        [responseData release];

        //NSDictionary *results = [responseString JSONValue]; <---This...

        //NSArray *allTweets = [results objectForKey:@"results"]; <--- and this was original code but it caused an exception,

        NSArray *allTweets = [responseString JSONValue]; //<-- So I used this instead.
        NSLog(@"THE ARRAY = %@", allTweets); //<-- THE ARRAY IS SHOWING FINE IN THE OUTPUT LOG
        [viewController setTweets:allTweets];
        [self.window addSubview:rootController.view];
        [self.window makeKeyAndVisible];

    }

    - (void)dealloc {
        [_window release];
        [rootController release];
        [viewController release];
        [super dealloc];
    }

    @end

TwitterViewContoller.h:(是的,我知道我拼错了 - 哈哈)

    #import <UIKit/UIKit.h>
    #import "SBJson.h"

    @interface TwitterViewContoller : UIViewController {
        IBOutlet UILabel *label;
        NSArray *tweets;
        IBOutlet UITableView *tview;
    }

    @property(nonatomic, retain) IBOutlet UILabel *label;
    @property(nonatomic, retain) NSArray *tweets;

    @end

TwitterViewContoller.m:

    #import "TwitterViewContoller.h"
    #import "Tweet.h"

    @implementation TwitterViewContoller

    @synthesize label;
    @synthesize tweets;

    #pragma mark -
    #pragma mark Table view data source

    - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
        // Return the number of sections.
        return 1;
    }


    - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
        // Return the number of rows in the section.
        return 20;
    }

    - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
        return 80;
    }


    // Customize the appearance of table view cells.
    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

        static NSString *CellIdentifier = @"Cell";

        UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
        if (cell == nil) {
            cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier] autorelease];
        }

        // Configure the cell...
        NSLog(@"THE ARRAY = %@", tweets); //<--ARRAY IS NULL <-- <-- <--
        NSDictionary *aTweet = [tweets objectAtIndex:[indexPath row]];


        cell.textLabel.text = [aTweet objectForKey:@"text"];
        cell.textLabel.adjustsFontSizeToFitWidth = YES;
        cell.textLabel.font = [UIFont systemFontOfSize:12];
        cell.textLabel.minimumFontSize = 10;
        cell.textLabel.numberOfLines = 4;
        cell.textLabel.lineBreakMode = UILineBreakModeWordWrap;

        cell.detailTextLabel.text = [aTweet objectForKey:@"screen_name"];

        NSURL *url = [NSURL URLWithString:[aTweet objectForKey:@"profile_image_url"]];
        NSData *data = [NSData dataWithContentsOfURL:url];
        cell.imageView.image = [UIImage imageWithData:data];
        cell.selectionStyle = UITableViewCellSelectionStyleNone;
        return cell;
    }


    #pragma mark -
    #pragma mark Table view delegate

    - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
        // Navigation logic may go here. Create and push another view controller.
        /*
             <#DetailViewController#> *detailViewController = [[<#DetailViewController#> alloc] initWithNibName:@"<#Nib name#>" bundle:nil];
             // ...
             // Pass the selected object to the new view controller.
             [self.navigationController pushViewController:detailViewController animated:YES];
             [detailViewController release];
        */
    }

    - (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
        self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
        if (self) {
            // Custom initialization
        }
        return self;
    }

    - (void)didReceiveMemoryWarning {
        // Releases the view if it doesn't have a superview.
        [super didReceiveMemoryWarning];

        // Release any cached data, images, etc that aren't in use.
    }

    #pragma mark - View lifecycle

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view from its nib.
        tweets = [[NSArray alloc]init];
    }

    - (void)viewDidUnload {
        [super viewDidUnload];
        // Release any retained subviews of the main view.
        // e.g. self.myOutlet = nil;
    }

    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
        // Return YES for supported orientations
        return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
    }

    - (void) dealloc {
        [tweets release];
        [super dealloc];
    }

    @end

问题是我的 UITableView 正在显示,但我的推文都没有。我注意到 TwitterViewContoller 中的“tweets”数组(我知道我拼写错误)是空的(null 问题已修复)但我的 AppDelegate 中的“allTweets”不是空的。有什么想法吗?

【问题讨论】:

    标签: ios json cocoa-touch twitter


    【解决方案1】:

    测试以确保在您的应用委托中,viewController 属性不为零。如果您在 IB 中接线错误(我在您的应用程序委托中没有看到它的任何实例化),当您调用 setTweets 时它会静默失败。

    此外,如果您的视图控制器可见并且您重新设置了 tweets 属性,则表格视图不会自行更新。不要合成你的 tweets 属性,而是编写你自己的 getter 和 setter,就像这样(如果你愿意,你也可以为此目的使用 KVO)

    -(NSMutableArray*)tweets {
        return [[tweets retain] autorelease];
    }
    
    -(void)setTweets:(NSMutableArray*)newTweets {
        if(newTweets != tweets) {
            [newTweets retain];
            [tweets release];
            tweets = newTweets;
    
            [tView reloadData];
        }
    }
    

    顺便说一句,你应该让-tableView:numberOfRowsInSection: 返回[tweets count] 而不是一个固定的数字,如果你的行都是相同的高度,则没有必要实现-tableView:heightForRowAtIndexPath:——你可以设置@ 987654327@ IB 或表格视图代码中的属性。

    更新

    如果您的视图控制器属性没有被填充,那么在-application:didFinishLaunchingWithOptions 中手动加载和添加它可能是最简单的——我认为您当前延迟显示任何界面直到网络请求完成的方法在概念上是有问题的。如果网络不可用会怎样?这是一些代码:

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // ... omitting the first few lines
    
        // let's make sure that we have the tab bar controller, at least
        NSAssert(nil != self.rootViewController, @"tab bar controller not hooked up!");
    
        self.viewController = [[[TwitterViewContoller alloc] initWithNibName:@"TwitterViewContoller" andBundle:nil] autorelease];
        self.rootViewController.viewControllers = [NSArray arrayWithObject:self.viewController];
    
        // this is now the Right Way to set the root view for your app, in iOS 4.0 and later
        self.window.rootViewController = self.rootViewController;
        [self.window makeKeyAndVisible];
    }
    

    当您开始一个新项目时,有很多方式会让您感到困惑。一开始我喜欢自定义我的所有视图,使其具有丑陋的背景颜色,这样我总是知道它们是否在屏幕上——使用丑陋的颜色有助于确保我以后不会忘记更改它们。

    【讨论】:

    • viewController 确实为空。虽然我似乎无法弄清楚如何通过 Interface Builder 进行设置。使用 MainWindow.xib,我可以 Ctrl+单击 App Delegate 到窗口并选择 IBOutlet,但在 TwitterViewContoller_iPhone.xib 中似乎没有那么简单。有什么想法吗?
    • 此外,我在 -tableView:cellForRowAtIndexPath 下的 NSLog 测试似乎不再被调用(NSLog 本身并不重要 - 似乎 cellForRowAtIndexPath 不再被调用)。
    • self.window.rootViewController = self.rootViewController; 可以在早期版本的 iOS 中使用吗? (例如 3.1.3)。
    • self.viewController = [[[TwitterViewContoller alloc] initWithNibName:@"TwitterViewContoller" andBundle:nil] autorelease]; 显示一条警告,指出Instance method '-initWithNibName:andBundle:' not found (return type defaults to 'id')
    • 抱歉,应该是-initWithNibName:bundle:
    猜你喜欢
    • 2012-11-11
    • 2012-11-09
    • 1970-01-01
    • 2023-03-10
    • 1970-01-01
    • 1970-01-01
    • 2012-12-25
    • 1970-01-01
    • 2012-08-03
    相关资源
    最近更新 更多