iOS应用开发教程:创建一个简单的Twitter应用

在这个教程中,将使用iOS 5和Xcode4.2,以及Storyboard来创建一个简单的Twitter应用。这个应用将展示推文列表,并且当点击某个推文时,会显示关于该推文和用户的详细信息。

创建项目

Xcode中,首先创建一个新的项目。选择“文件” > “新建” > “新建项目”。然后选择“主-详情应用程序”,点击“下一步”。输入产品名称为'Twitter Test',并确保选中“使用Storyboard”和“使用自动引用计数”复选框。点击“下一步”,选择保存项目的位置,然后点击“创建”。现在项目已经创建好了,它会自动设置一个Storyboard、一个主视图控制器和一个详情视图控制器。Storyboard是设计应用的地方,控制器是编写程序的地方。

Storyboard设置

打开Storyboard,看看它包含什么。点击左侧的MainStoryboard.storyboard,Storyboard就会出现。从这里可以看到:

  • 一个导航视图控制器——这种控制器在从列表视图导航到详情视图时会自动提供一个返回按钮。
  • 一个主视图控制器——将在这里展示推文列表。
  • 一个详情视图控制器——将在这里展示每个推文的详细信息。

控制器之间的线称为'segues'。稍后在处理用户选择推文的动作时会详细讨论这些。

设置表格视图

在左侧的树视图中选择表格视图,并在右侧选择“动态原型”。这告诉表格视图将从控制器动态设置单元格。

接下来,在左侧的树视图中选择“表格视图单元格”,然后在右侧将样式设置为“副标题”,并将“标识符”设置为'TweetCell'——这是在代码中用来找到单元格以便填充其详细信息的名称。

现在,已经在Storyboard部分设置了主视图。稍后会回到详情视图。

编码主视图控制器

进入MasterViewController.m,替换@interface到@end部分的代码:

@interface MasterViewController : UITableViewController { NSArray *tweets; } - (void)fetchTweets; @end

这告诉Objective-C有一个tweets实例变量和一个fetchTweets方法。

加载JSON

现在来实际获取推文。回到MasterViewController.m并插入以下方法:

- (void)fetchTweets { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSData* data = [NSData dataWithContentsOfURL: [NSURL URLWithString:@"https://api.twitter.com/1/statuses/public_timeline.json"]]; NSError* error; tweets = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error]; dispatch_async(dispatch_get_main_queue(), ^{ [self.tableView reloadData]; }); }); }

这个方法的作用是在单独的线程中获取JSON数据,然后在主线程中更新表格视图。这样做的原因是,如果在主线程中获取数据,那么应用程序会在数据加载完成之前锁定。

在viewDidLoad方法中调用这个方法:

- (void)viewDidLoad { [super viewDidLoad]; [self fetchTweets]; }

这告诉应用程序在视图加载时加载JSON数据。现在Twitter feed已经加载到名为tweets的实例变量中。这个变量现在包含一个数组,其中包含多个NSDictionary对象,NSDictionary是一个键/值集合。

填充表格视图

接下来,插入以下两个方法:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return tweets.count; } - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { static NSString *CellIdentifier = @"TweetCell"; UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; if (cell == nil) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; } NSDictionary *tweet = [tweets objectAtIndex:indexPath.row]; NSString *text = [tweet objectForKey:@"text"]; NSString *name = [[tweet objectForKey:@"user"] objectForKey:@"name"]; cell.textLabel.text = text; cell.detailTextLabel.text = [NSString stringWithFormat:@"by %@", name]; return cell; }

现在尝试运行应用程序——点击“运行”图标。它工作了:非常简单,对吧?

Segue设置

尝试选择一个推文。意图是加载详情视图,但这并没有发生。为什么?让回到Storyboard

注意到主视图控制器和详情视图控制器之间没有segue。当之前从静态单元格切换到原型单元格时,它被擦除了,所以现在它不知道该做什么。让帮助它。

设置Segue

在左侧,使用CTRL + 拖动从“表格视图单元格”到“详情视图控制器”,并选择“Push”。现在它知道该做什么了,所以尝试再次运行。

点击表格视图和详情视图之间的segue,并将其标识符更改为'showTweet'。这就是稍后在代码中识别它的方式。

响应Segue

在MasterViewController.m中,紧接在#import "MasterViewController.h"之后插入以下代码:

#import "DetailViewController.h"

这是为了让能够从主视图控制器访问详情视图控制器。插入以下方法:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender { if ([segue.identifier isEqualToString:@"showTweet"]) { NSInteger row = [[self tableView].indexPathForSelectedRow row]; NSDictionary *tweet = [tweets objectAtIndex:row]; DetailViewController *detailController = segue.destinationViewController; detailController.detailItem = tweet; } }

这基本上告诉应用程序在主视图和详情视图之间的segue时该做什么。它识别选定的行,找到推文,然后在详情视图控制器上设置detailItem属性。(detailItem属性是在最初选择“主-详情应用程序”时自动创建的。感谢Xcode!)

完成详情视图

打开Storyboard,双击'Master'和'Detail'标题,分别更改为'Tweets'和'Tweet':

删除标签“详情视图内容放在这里”。将创建自己的。插入一个用于名称的标签,一个用于推文的标签,以及一个用于个人资料图片的图像视图,如下所示:

可以按想要的方式自定义文本大小。

为详情视图创建输出

需要一种方法从代码中调用这些新控件。这是通过创建三个输出完成的,这是一种连接视图和控制器的线或连接。在DetailViewController.h中,用以下代码替换@interface行:

@interface DetailViewController : UIViewController { IBOutlet UIImageView *profileImage; IBOutlet UILabel *nameLabel; IBOutlet UILabel *tweetLabel; }

现在已经创建了输出。现在需要引用或连接这些视图。在左侧,使用CTRL + 拖动从详情视图控制器到“标签 - 名称放在这里”并选择nameLabel:

同样从详情视图控制器拖动到“标签 - 推文放在这里”并选择tweetLabel,以及从详情视图控制器拖动到“图像视图”并选择profileImage。

- (void)configureView { if (self.detailItem) { NSDictionary *tweet = self.detailItem; NSString *text = [[tweet objectForKey:@"user"] objectForKey:@"name"]; NSString *name = [tweet objectForKey:@"text"]; tweetLabel.lineBreakMode = UILineBreakModeWordWrap; tweetLabel.numberOfLines = 0; nameLabel.text = text; tweetLabel.text = name; dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ NSString *imageUrl = [[tweet objectForKey:@"user"] objectForKey:@"profile_image_url"]; NSData *data = [NSData dataWithContentsOfURL:[NSURL URLWithString:imageUrl]]; dispatch_async(dispatch_get_main_queue(), ^{ profileImage.image = [UIImage imageWithData:data]; }); }); } }
沪ICP备2024098111号-1
上海秋旦网络科技中心:上海市奉贤区金大公路8218号1幢 联系电话:17898875485