Objective-C中的CocoaPods教程

来源:互联网 发布:双十一京东数据 编辑:程序博客网 时间:2024/06/05 19:07

*本文翻译自http://www.raywenderlich.com/64546/introduction-to-cocoapods-2


In this tutorial, you’ll learn how to use a popular dependency management tool calledCocoaPods.

在这个教程中,你将学习如何使用一个流行的依赖库管理工具:CocoaPods

But wait! What is a dependency management tool and why do you need one?

但什么是依赖库管理工具,为什么你需要它?

As an iOS developer, you certainly use a lot of code made by others, in the shape of libraries. Just imagine how difficult it would be if you had to implement everything from scratch!

作为一个iOS开发者,你会使用到很多别人创建的类库形式的代码。想象一下如果你不得不从头开始实现一切会有多困难!

Without a dependency management tool, you might simply add each library’s code to your project. However, this has several disadvantages:

如果没有依赖库管理工具,你也许会直接将类库的代码添加到你的工程里。然而,这样做有些不利之处:

  • Library code is stored within your project, wasting space.                         

  •  类库代码被存储在工程里,浪费了空间。

  • There’s no central place where you can see all libraries that are available. 

  • 没有一个集中的,能够看到全部可用类库的地方

  • It can be difficult to find and update a library to a new version, especially if several libraries need to be updated together.

  • 查找并升级一个类库到新版本会比较困难,尤其是一些类库需要同时升级的时候

  • Downloading and including libraries within your project may tempt you to make changes to the downloaded code and just leave it there (making it harder to update them later).

  • 下载并包含类库到你的工程会导致你要修改已经下载的代码,使更新它们更困难

A dependency management tool can help you overcome these issues. It will fetch library source code, resolve dependencies between libraries, and even create and maintain the right environment to build your project with the minimum of hassles.

一个依赖库管理工具能帮助你克服这些问题。它会获取类库源代码,解决类库之间的依赖,并创建和保持正确的运行环境,最小化对工程的影响。

You’ll get hands on experience using CocoaPods for dependency management in this tutorial. Specifically, you will create an app that uses several open-source libraries to fetch and display information from a popular television and movie information site,trakt.tv.

在本教程中你将会上手使用CocoaPods做依赖管理。你将创建一个程序,使用一些开源类库用来从一个受欢迎的电视和电影信息网站trakt.tv获取和显示信息

CocoaPods will make this project much easier. Read on to see for yourself!

CocoaPods会使这个工程变的更简单。继续阅读亲自来看吧!

Getting Started 开始

According to its website, CocoaPods is “the best way to manage library dependencies in Objective-C projects.” And in this case, the advertising is true!

网站上说,“在Objective-C工程中,CocoaPods是最理想的管理类库依赖的方法。”从本例中可见这是真的!


True Dat!

Instead of downloading code from GitHub and copying it into your project (and thus making future updates difficult), you can let CocoaPods do it for you.

不用再从GitHub上下载代码并复制到你的工程里了(这样未来升级很困难),CocoaPods为你做了这些。

In this tutorial, you will be building an app that displays upcoming TV episodes usingtrakt.tv. If you haven’t heard of it, trakt helps you keep track of the shows that you watch. Trakt hasseveral other features, but this is the only one that you will be using in this tutorial.

在本教程中,你将建立一个程序,使用trakt.tv显示即将到来的电视节目。如果你没听说过它,trakt会帮你追踪节目。trakt有其他功能,但本教程中你只会使用到这一个。

You will retrieve show information from a JSON feed provided by trakt. To simplify downloading, parsing, and showing results, you will useAFNetworking and a few other open-source libraries along the way.

你会从trakt提供的JSON中取回节目信息。为了简化下载,解析和显示结果,你会用到AFNetworking 和一些其他的开源库。

To get started, you first need to install CocoaPods. CocoaPods runs on Ruby, yet that’s the only dependency it has. Fortunately, all recent versions of Mac OS X (since OS X 10.7 Lion) ship with Ruby already installed. So all you need to do is update RubyGems (just to make sure you have a recent version).

为了开始,你首先需要安装CocoaPods。CocoaPods运行Ruby,这是它唯一的依赖。幸运的是,所有最近版本的Mac OS X(从OS X 10.7 Lion开始),Ruby已经安装好了。所以你要做的就是升级RubyGems(确保你有最新版)

To do so, open Terminal and type the following command:

打开终端并输入一下命令:

sudo gem update --system

Enter your password when requested. The Terminal output should look something like this:

需要时输入你的密码。终端输出应该像这样:

Terminal Output

This update may take a little while, so be patient and give it a few minutes to complete. You can also expect some documentation in the Terminal window about the latest version; you can ignore this for now.

这个升级会花费些时间,所以要耐心等待几分钟完成。你可能也会期待一些最新版本的文档,现在可以忽略它。

Next, you need to install CocoaPods. Type this command in Terminal to do so:

下一步,你需要安装CocoaPods。在终端中输入以下命令来安装:

sudo gem install cocoapods

You may get this prompt during the install process:

在安装过程中也许提示以下信息:

rake's executable "rake" conflicts with /usr/bin/rakeOverwrite the executable? [yN]

If so, just enter y to continue. (This warning is raised because the rake gem is updated as part of the install process. You can safely ignore it.)

如果有提示,只要输入y继续。(这个警告时由于rake gem作为安装流程的一部分更新。你可以安全的忽略它。)

Lastly, enter this command in Terminal to complete the setup of CocoaPods:

最后,输入以下命令完成CocoaPods安装:

pod setup

This process will likely take a while as this command clones theCocoaPods Specs repository into~/.cocoapods/ on your computer.

Great, you’re now setup to use CocoaPods!

这个流程很可能会花费些时间,因为这个命令克隆CocoaPods Specs repository 到你的电脑的~/.cocoapods目录下。

太棒了,你现在安装好了CocoaPods


Oh yeah!

Introducing the “Show Tracker” App

“Show Tracker”工程的介绍

Download the starter project for this tutorial here. This provides a basic UI to get you started – no dependencies have been added yet.

Open Main.storyboard, and you will see just one view controller:

可以从这里下载工程。这里提供了一个基本界面使你开始-没有依赖库添加。打开Main.storyboard,你会看见只有一个view controller:


View Controller

This is the initial view controller, simply calledViewController.

这是一个初始view controller,简单命名为ViewController.

It has a UIScrollView connected via an IBOutlet to itsshowsScrollView property and aUIPageControl connected toshowsPageControl.

它包含通过IBOutlet连接到的UIScrollView *showsScrollView,和UIPageControl *showsPageControl属性。

It is also set as the delegate for showsScrollView and currently has a single method,pageChanged:, which is connected to the value changed event ofshowsPageControl.

viewcontroller同时设置了代理UIScrollViewDelegate,并且有一个唯一方法叫pageChanged,连接到了“value changed”响应时间中

Now, close Xcode.

现在关闭xcode

Yeah, you read that right! It’s time to create your pod file.

是的,该创建pod file了

Installing Your First Dependency

安装你的第一个依赖库

Open Terminal and navigate to the directory containing yourShowTracker project by using thecd command:

打开终端,用cd命令进入到包含你的ShowTracker工程目录下

cd ~/Path/To/Folder/Containing/ShowTracker

Next enter this command:

输入以下命令:

pod init

This will create a default Podfile for your project. ThePodfile is where you define the dependencies your project relies on.

这会在工程目录下创建一个默认的Podfile文件。这个文件是你定义工程中需要的依赖库的地方。

Type this command to open Podfile using Xcode for editing:

输入以下命令打开用xcode打开Podfile并编辑这个文件

open -a Xcode Podfile

Note: You shouldn’t use TextEdit to edit the pod file because TextEdit likes to replace standard quotes with more graphically appealing quotes. This can cause CocoaPods to get confused and display errors, so it’s best to just use Xcode or another programming text editor.

注意:你不能用TextEdit编辑这个文件,因为TextEdit喜欢用更生动吸引人的引用替换标准引用。这会导致CocoaPods出现困惑并报告错误,所以最好用xcode或其他编程用的文本编辑器。

The default Podfile should look like this:

默认的Podfile文件会像这样:

# Uncomment this line to define a global platform for your project# platform :ios, "6.0" target "ShowTracker"do end

Replace # platform :ios, "6.0" with the following:

用7.0替换6.0

platform:ios,"7.0"

This tells CocoaPods that your project is targeting iOS 7.

这回告诉CocoaPods你的工程是针对ios7的。

Many libraries – AFNetworking included – have a minimum iOS version requirement. If you omit this line, CocoaPods assumes a default target version (currently iOS 4.3).

许多类库-包括AFNetworking-有最低ios版本要求。如果你忽略此行,CocoaPods会假定一个默认的版本(目前是ios4.3)

If you’ve only ever programmed in Objective-C, this may look a bit strange to you – that’s because the pod file is actually written in Ruby. You don’t need to know Ruby to use CocoaPods, but you should be aware that even minor text errors will typically cause CocoaPods to throw an error.

如果你只用过Objective-C,这里面会看起来有点怪-这是因为pod文件是Ruby写的。使用CocoaPods不需要知道Ruby,但你需知道即使微小的文本错误也会导致CocoaPods抛出错误。

It’s finally time to add your first dependency using CocoaPods! Copy and paste the following into your pod file, right aftertarget "ShowTracker" do:

到了用CocoaPods添加你第一个依赖库的时候了。在podfile中的target 'ShowTracker' do一行后面复制粘贴下面一行:

pod 'AFNetworking', '2.2.1'

This tells CocoaPods that you want to include AFNetworking version 2.2.1 (the latest as of the writing of this tutorial) as a dependency for your project.

这会告诉CocoaPods你想要包含AFNetworking的2.2.1版本(写本教程时的最新版)作为你工程的依赖库。

This link has more information about the Podfile format and syntax. If you want to do more complicated stuff (like specifying “any version higher than” a specific version of a library), you should definitely check it out.

这个链接有更多podfile格式和语法相关的信息。如果你想要做更复杂的东西(比如指定”任何高于特定版本的版本“,你需要看它)。

Save and close the pod file.

保存并关闭podfile。

You now need to tell CocoaPods to “install” the dependencies for your project. Enter the following command in Terminal to do so (making sure that you’re still in the directory containing the ShowTracker project and Podfile):

你现在需要告诉CocoaPods”安装“工程的依赖。在终端中输入以下命令(确保你依然在包含工程和podfile的目录下)

pod install

You should see output similar to the following:

你会看见输出信息像下面这样:

Analyzing dependenciesDownloading dependenciesInstalling AFNetworking (2.2.1)Generating Pods projectIntegrating client project

It might also tell you something like this:

[!] From now on use `ShowTracker.xcworkspace`.

If you type ls now (or browse to the project folder using Finder), you’ll see that CocoaPods created a Pods folder – where it stores all dependencies – andShowTracker.xcworkspace.

如果你输入ls(或者用Finder查看工程),你会看见CocoaPods创建了一个Pods目录-它存储所有依赖库-和ShowTracker.xcworkspace文件。

VERY IMPORTANT!

非常重要!

From now on, as the command-line warning mentioned, youmust always open the workspace (ShowTracker.xcworkspace) and not the project!

从现在起,就如命令行警告的那样,你必须打开ShowTracker.xcworkspace文件而不能打开工程文件。

Close the Xcode project (if you had it open) and open ShowTracker.xcworkspace.

关闭xcode 工程文件(如果你已经打开了)并打开ShowTracker.xcworkspace。

Register for Trakt

注册trakt

Before you can use the Trakt APIs, you first need toregister for a free account. Don’t worry – it’s fast and easy to do!

在使用trakt的APIs之前,你首先需要注册一个免费账号。别担心-非常快速且简单。

After registering, go to the Settings -> API page to get your API key. Go ahead and leave this page open as you’ll need it soon.

注册之后,前往Settings->API页面拿到API key. 保留这个页面因为你一会要用到它,然后继续。

Testing AFNetworking

测试AFNetworking

To verify that AFNetworking was successfully added, create a new file with theiOS -> Cocoa Touch -> Objective-C class template.

创建一个新的文件:iOS->Cocoa Touch->Objective-C,验证AFNetworking是否成功添加。

Name the class TraktAPIClient, and make it a subclass ofNSObject.

命名为TraktAPIClient,继承NSObject.

Make sure you add the new file to the ShowTracker project and not the Pods project – if you look at your Project Navigator, you’ll see that you now have two separate projects in your workspace.

确保你添加新文件到ShowTracker工程而不是Pods工程中-如果你看工程导航,你会在workspace中看见两个分开的工程


Adding TraktAPIClient

Open TraktAPIClient.h and replace the existing code with the following:

打开TraktAPIClient.h并替换已经存在的代码为以下代码:

// 1#import <AFNetworking/AFNetworking.h> // 2extern NSString *const kTraktAPIKey;externNSString*const kTraktBaseURLString; // 3@interface TraktAPIClient: AFHTTPSessionManager // 4+(TraktAPIClient*)sharedClient; // 5-(void)getShowsForDate:(NSDate*)date username:(NSString*)username numberOfDays:(int)numberOfDays success:(void(^)(NSURLSessionDataTask*task,id responseObject))success failure:(void(^)(NSURLSessionDataTask*task,NSError*error))failure; @end

Here’s what you’re doing:

你在做的是:

  1. First import the main header for AFNetworking, which isAFNetworking.h. This includesAFHTTPSessionManager, which will be the super class ofTraktAPIClient, and other related networking classes.
     1.首先导入主要的头文件AFNetworking.h。它包含AFHTTPSessionManager,作为TraktAPIClient和其它网络相关的类的父类,

  2. Next, declare two string constants with the extern modifier. This means these strings will be globally available.2.接下来,声明两个字符串用extern修饰符。这意味着这些字符串将全局可用。

  3. Change TraktAPIClient to extend AFHTTPSessionManager instead of NSObject, as mentioned in step 1.3.修改TraktAPIClient来扩展AFHTTPSessionManager而不是NSObject,这在第一步提及了。

  4. Declare sharedClient, which will return asingleton instance forTraktAPIClient.4.声明sharedClient方法,返回一个TraktAPIClient的单例实例

  5. Lastly, declare a helper method that will make it easier to use the trakt API to get shows for a specific date, username, and number of days.5.最后,声明一个帮助方法用来简化使用trakt API去显示具体日期,用户名,天数。

You might be wondering, “why did I create TraktAPIClient whenAFHTTPSessionManager already handles HTTP requests?”

你可能想知道,“AFHTTPSessionManager已经能处理HTTP请求,为什么我还要创建TraktAPIClient”

TraktAPIClient will make it easier to access the trakt API and make a lot of requests to the same base URL, using the same API key. This also encapsulates all the networking calls and responsibility into a single class.

TraktAPIClient会简化访问trakt API和对同一个绝对路径的多个请求,使用同一个API key。囊括了所有的网络请求和职责到单个类中。

Open TraktAPIClient.m and replace its contents with the following:

打开TraktAPIClient.m并替换成以下内容:

#import "TraktAPIClient.h" // Set this to your Trakt API KeyNSString*const kTraktAPIKey=@"PASTE YOUR API KEY HERE";NSString*const kTraktBaseURLString=@"http://api.trakt.tv"@implementation TraktAPIClient +(TraktAPIClient*)sharedClient{static TraktAPIClient*_sharedClient=nil;static dispatch_once_t oncePredicate; dispatch_once(&oncePredicate,^{ _sharedClient=[[self alloc] initWithBaseURL:[NSURL URLWithString:kTraktBaseURLString]];});return _sharedClient;} -(instancetype)initWithBaseURL:(NSURL*)url{  self = [super initWithBaseURL:url];if(!self){returnnil;}  self.responseSerializer= [AFJSONResponseSerializer serializer]; self.requestSerializer=[AFJSONRequestSerializer serializer];return self;} -(void)getShowsForDate:(NSDate*)date username:(NSString*)username numberOfDays:(int)numberOfDays success:(void(^)(NSURLSessionDataTask*task,id responseObject))success failure:(void(^)(NSURLSessionDataTask*task,NSError*error))failure{NSDateFormatter* formatter= [[NSDateFormatter alloc] init]; formatter.dateFormat=@"yyyyMMdd";NSString* dateString=[formatter stringFromDate:date]NSString* path= [NSString stringWithFormat:@"user/calendar/shows.json/%@/%@/%@/%d", kTraktAPIKey, username, dateString, numberOfDays][self GET:path parameters:nil success:^(NSURLSessionDataTask*task,id responseObject){if(success){ success(task, responseObject);}} failure:^(NSURLSessionDataTask*task,NSError*error){if(failure){ failure(task, error);}}];} @end

This code fulfills all the promises you made in the header file:

这段代码实现了所有你在头文件中的定义:

First, you declare the string constants. Make sure you replacePASTE YOUR KEY HERE with your actual trakt API key.

首先,你声明了字符串常量。确保替换@"PASTE YOUR API KEY HERE"成你自己的trakt API key.

Next, you implement sharedClient, which uses Grand Central Dispatch (GCD) to create a singleton instance.

然后,你实现sharedClient,使用GCD创建单例。

You then override initWithBaseURL: and setresponseSerializer andrequestSerializer to the default JSON serializer for each.

然后覆盖initWithBaseURL:方法,并设置responseSerializer和requestSerializer为默认json序列。

Lastly, you create the helper method to get shows using the format expected by trakt.

最后,用trakt期待的格式创建帮助方法来获取节目。

Now open AppDelegate.m and add the following right after the existing import line:

打开AppDelegate.m在已经存在的导入行添加以下代码

#import <AFNetworking/AFNetworkActivityIndicatorManager.h>

Then add the following to application:didFinishLaunchingWithOptions: right before the return statement:

然后在return之前添加下面一行到- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions方法中

[AFNetworkActivityIndicatorManager sharedManager].enabled=YES;

This will automatically show the network activity indicator whenever AFNetworking is performing network requests.

这样在AFNetworking进行网络请求时,网络活动显示器将自动出现。

Next, open ViewController.m and add the following import right after the last one:

然后,打开ViewController.m并添加下面一行:

#import "TraktAPIClient.h"

Then, replace viewDidLoad with the following:

替换viewDidLoad方法为以下内容:

-(void)viewDidLoad{[super viewDidLoad];  TraktAPIClient*client=[TraktAPIClient sharedClient][client getShowsForDate:[NSDate date] username:@"rwtestuser" numberOfDays:3 success:^(NSURLSessionDataTask*task,id responseObject){ NSLog(@"Success -- %@", responseObject);} failure:^(NSURLSessionDataTask*task,NSError*error){ NSLog(@"Failure -- %@", error);}];}

This code calls the helper method you just setup to get the shows for today and the next 3 days.

这段代码调用你刚创建的帮助方法显示今天和未来三天的节目。

Note: this API queries for tv episodes on a trakt user’s watch list. If you want to use your own username, you will first need to add shows to your watch list from thetv shows category. If you don’t want to do this, userwtestuser as the username, which already has shows added to it.

注意:这个API询问trakt用户收看列表中的节目集。如果你想用用户名,你会首先需要从节目类中添加节目到你的收看列表。如果你不想这么做,使用rwtestuser这个用户名,它已存在添加的节目。

Build and run, and you should see output in the console similar to the following:

运行程序,你应该看见如下输出:


Get Shows NSLog

Add More Pods

添加更多Pods

Now that you’ve seen CocoaPods in action, there’s only one thing to do…

现在你看到CocoaPods工作了,只有一件事要做...


Add More Pods!

Well, actually… you should strive to include as few pods as possible in each of your projects. While CocoaPods makes it easier to update library dependencies, you’re still going to have to updateyour own code from time to time when you update libraries.

事实上,你应该在每个工程中尽力包含最少的pods。虽然CocoaPods简化了升级依赖库,当你升级库时,你依然要随时升级你自己的代码。

Keeping your dependencies under control is the best way to go in the long run.

为了走的长远,保持你的依赖库可控是最好的方式。

You need to add two more dependencies for this project. Rather than openingPodFile from the command line, you can now find it in the Pods target in the workspace.

你还需要两个依赖库。不用再用命令行打开podfile,你可以在workspace的Pods中找到它

Podfile In Workspace

Open Podfile and append the following right after theAFNetworking line:

打开Podfile,添加下面一行:

pod 'SAMCategories', '0.5.2'pod 'Nimbus/AttributedLabel', '1.2.0'

Save the file, and install the dependencies (via pod install in Terminal, as before).

保存并安装依赖库(通过终端安装,像之前一样)

Do you notice anything different about the Nimbus/AttributedLabel pod? What is that slash in the middle of its name?

你注意到Nimbus/AttributedLabel的不同之处了吗?名字中间的/是什么呢?

Larger pods often break up their classes into several submodules that rely on a “core” module. In this case, the slash means that AttributedLabel is a submodule of Nimbus.

大的pods通常将他们的类分成依赖一个“核心模块”的几个子模块。在这里,/意思是AttributedLabel是Nimbus的子模块。

In case you’re not familiar with these libraries, here’s what they are:

假如你不熟悉这些库,现在来说明他们是什么:

SSToolkit is a handy collection of solutions to common issues faced by iOS developers. In the ShowTracker app, you’ll use it to check if the device has a Retina display.

SSToolkit是一个方便的解决方案的集合用来解决ios开发者面对的共同问题。在ShowTracker中,你会用它检查设备是否是Retina屏。

Nimbus, short for NimbusKit, is another collection of useful categories and classes for iOS. You’ll use it mainly for its AttributedLabel component in this app.

Nimbus是NimbusKit的简称,是另一个ios有用类的集合。本例中你主要用到它的AttributedLabel。

Just to verify everything still works, go ahead and build the app. However, you should now see several warning messages!

“But wait a minute, I haven’t changed any of my project’s code!”, you might be thinking.

Whenever you add a dependency via CocoaPods, the pod’s source files are included within your project’s workspace. And whenever you compile your project, they’re compiled too.

So, if the pod you’re using has a lot of warnings (or worse, doesn’t compile at all), it may be an indicator that the library is no longer maintained.

In such a case, you can look for an alternative library on theCocoaPods website by using the search field. You can find detailed information about pods there too, including links to pods’ websites, documentation, and more.

In this case, however, the warnings are mainly due to recently deprecated methods in iOS 7 (mostly calls tosizeWithFont:), and you can safely ignore them.

Add the following to the top of Podfile to tell CocoaPods to silence all warnings from pod dependencies:

inhibit_all_warnings!

Run pod install again, build your project, and you shouldn’t see any warnings anymore.

Completing Show Tracker

Great, you now have all the dependencies you’ll need to complete Show Tracker, so let’s do it!

Open ViewController.m and add the following imports, just after the last one:

#import <AFNetworking/UIKit+AFNetworking.h>#import <Nimbus/NIAttributedLabel.h>#import <SAMCategories/UIScreen+SAMAdditions.h>

Next, add the following properties right after @interface ViewController ():

@property(nonatomic, strong)NSArray*jsonResponse;@property(nonatomic)BOOL pageControlUsed;@property(nonatomic) NSInteger previousPage;

These will be used to store downloaded shows information.

Create a method called loadShow:, at the bottom of the file:

-(void)loadShow:(NSInteger)index{// empty for now...}

This method will be responsible for presenting a page to the user that displays information about a selected TV show episode.

Now you need to modify viewDidLoad so that it does something useful with the response object instead of simply logging it. First add the following right after[super viewDidLoad];:

self.previousPage=-1;

Then replace the contents of the success block with the following:

// Save response objectself.jsonResponse= responseObject; // Get the number of showsNSInteger shows=0;for(NSDictionary*dayin self.jsonResponse) shows+=[day[@"episodes"] count]// Set up page controlself.showsPageControl.numberOfPages= shows;self.showsPageControl.currentPage=0// Set up scroll viewself.showsScrollView.contentSize= CGSizeMake(CGRectGetWidth(self.view.bounds)* shows, CGRectGetHeight(self.showsScrollView.frame))// Load first show[self loadShow:0];

Now the responseObject JSON is stored, the page control and scroll view are setup, andloadShow: is called to load the first show on success.

You can now present information about a show by replacingloadShow: with the following:

-(void)loadShow:(NSInteger)index{// 1 - Find the show for the given indexNSDictionary*show=nil; NSInteger shows=0for(NSDictionary*dayin self.jsonResponse){ NSInteger count=[day[@"episodes"] count]// 2 - Did you find the right show?if(index < shows+ count){ show= day[@"episodes"][index- shows]; break;} // 3 - Increment the shows counter shows+= count;} // 4 - Load the show informationNSDictionary*showDict= show[@"show"]// 5 - Display the show title UILabel*titleLabel=[[UILabel alloc] initWithFrame:CGRectMake(index* CGRectGetWidth(self.showsScrollView.bounds)+20,40, CGRectGetWidth(self.showsScrollView.bounds)-40,40)]; titleLabel.text= showDict[@"title"]; titleLabel.backgroundColor=[UIColor clearColor]; titleLabel.textColor=[UIColor whiteColor]; titleLabel.font=[UIFont boldSystemFontOfSize:18]; titleLabel.textAlignment= NSTextAlignmentCenter; // 6 - Add to scroll view [self.showsScrollView addSubview:titleLabel];}

Build and run, and you will see something like this:


Title Only Screenshot

Cool, tonight a new episode of The Walking Dead will air! But which episode?

Add the following to loadShow: just before section #6:

// 5.1 - Create formatted airing datestaticNSDateFormatter*formatter=nil;if(!formatter){ formatter=[[NSDateFormatter alloc] init]; formatter.dateStyle= NSDateFormatterLongStyle; formatter.timeStyle= NSDateFormatterShortStyle; formatter.timeZone=[NSTimeZone timeZoneWithAbbreviation:@"PST"];} NSDictionary*episodeDict= show[@"episode"]; NSTimeInterval showAired=[episodeDict[@"first_aired_localized"] doubleValue];NSString*showDate=[formatter stringFromDate:[NSDate dateWithTimeIntervalSince1970: showAired]]// 5.2 - Create label to display episode infoUILabel*episodeLabel=[[UILabel alloc] initWithFrame:CGRectMake(index* CGRectGetWidth(self.showsScrollView.bounds),360, CGRectGetWidth(self.showsScrollView.bounds),40)];NSString* episode = [NSString stringWithFormat:@"%02dx%02d -\"%@\"",[[episodeDict valueForKey:@"season"] intValue],[[episodeDict valueForKey:@"number"] intValue],[episodeDict objectForKey:@"title"]];episodeLabel.text=[NSString stringWithFormat:@"%@\n%@", episode, showDate];episodeLabel.numberOfLines=0;episodeLabel.textAlignment= NSTextAlignmentCenter;episodeLabel.textColor=[UIColor whiteColor];episodeLabel.backgroundColor=[UIColor clearColor]; CGSize size=[episodeLabel sizeThatFits:CGSizeMake(CGRectGetWidth(self.view.frame), CGRectGetHeight(self.view.frame)- CGRectGetMinY(episodeLabel.frame))];CGRect frame= episodeLabel.frame;frame.size.width= self.view.frame.size.width;frame.size.height= size.height;episodeLabel.frame= frame; [self.showsScrollView addSubview:episodeLabel];

This creates a label containing info about the episode, including season, episode number, title and a human-readable date and time it’s going to be aired.

Build and run, and you can now see that The Walking Dead is already in its 4th season!


Title Details Screenshot

Doesn’t it feel as if there’s a giant void at the center of the screen that’s calling out to be filled? What if you put an image there?

Still in loadShow:, add the following code just before section #6:

// 5.3 - Get imageNSString*posterUrl= showDict[@"images"][@"poster"];if([[UIScreen mainScreen] sam_isRetina]){ posterUrl=[posterUrl stringByReplacingOccurrencesOfString:@".jpg" withString:@"-300.jpg"];}else{ posterUrl=[posterUrl stringByReplacingOccurrencesOfString:@".jpg" withString:@"-138.jpg"];} // 5.4 - Display image using image viewUIImageView *posterImage = [[UIImageView alloc] init];posterImage.frame= CGRectMake(index* CGRectGetWidth(self.showsScrollView.bounds)+90,105,150,225);[self.showsScrollView addSubview:posterImage]// 5.5 - Asynchronously load the image[posterImage setImageWithURL:[NSURL URLWithString:posterUrl] placeholderImage:[UIImage imageNamed:@"placeholder.png"]];

This code first determines the image to download based on whether the device has a retina display (since there is no need to download a larger image on a non-retina device). Note thatisRetinaDisplay is a helper method included from SSToolkit.

After that, a UIImageView is created and added to the scroll view.

Finally, the image is downloaded and set on the image view, using the convenience method provided by AFNetworking. This method also sets a placeholder image that is displayed until the download is finished.

Build and run, and you will see a beautiful poster of the show.


Title, Details, and Poster Screenshot

Great! You now have information displayed about the first show but what about the rest?

You first need to show information about the other shows as the view is paged via theshowsPageControl.

Replace pageChanged: with the following:

-(IBAction)pageChanged:(id)sender{// Set flag self.pageControlUsed= YES// Get previous page number NSInteger page= self.showsPageControl.currentPage; self.previousPage= page; // Call loadShow for the new page[self loadShow:page]// Scroll scroll view to new page CGRect frame= self.showsScrollView.frame; frame.origin.x= frame.size.width* page; frame.origin.y=0;[UIView animateWithDuration:.5 animations:^{[self.showsScrollView scrollRectToVisible:frame animated:NO];} completion:^(BOOL finished){ self.pageControlUsed=NO;}];}

Here pageControlUsed is set to YES, indicating that the new page will be shown because the user selected it with the page control and not by scrolling the scroll view. (You’ll need this later when you handle scrolling using the scroll view.)

Then, the new page is loaded and its frame calculated. Finally, the new page is displayed on the screen.

Build and run. You can now navigate through pages using the page control. Simply tap on the circles in the page control and the screen will navigate to the next or previous page. Cool, isn’t it?

But, something’s missing… What about changing pages by scrolling? If you try to do that, you’ll notice that you get blank pages, unless you’d already scrolled to that page using the page control. Let’s fix that.

Paste the following UIScrollViewDelegate methods at the end of the file:

-(void)scrollViewDidScroll:(UIScrollView*)sender{// Was the scrolling initiated via page control?if(self.pageControlUsed)return// Figure out page to scroll to CGFloat pageWidth= sender.frame.size.width; NSInteger page=floor((sender.contentOffset.x- pageWidth /2)/ pageWidth)+1// Do not do anything if we're trying to go beyond the available page rangeif(page== self.previousPage || page <0 || page >= self.showsPageControl.numberOfPages)return; self.previousPage= page; // Set the page control page display self.showsPageControl.currentPage= page; // Load the page[self loadShow:page];} -(void)scrollViewDidEndDecelerating:(UIScrollView*)scrollView{ self.pageControlUsed= NO;}

Note the use of self.pageControlUsed. That’s because when the scroll view offset is changed inpageChanged (when you change the page using the page control),scrollViewDidScroll: is called, but if you handled the scrolling at that point, you’d be loading the same page twice. So you need to detect when scrolling is initiated via the page control and do nothing.

Build and run, and you can now navigate through the shows by scrolling too!

But what if the user wants to know more about the show? Trakt has a page for every show registered, and its URL is in the information the app has already received.

You can use NIAttributedLabel to present it.

At the top of ViewController.m, replace @interface ViewController () with the following:

@interface ViewController() <NIAttributedLabelDelegate>

This declares that ViewController conforms to theNIAttributedLabelDelegate protocol.

Now add the following NIAttributedLabelDelegate method at the bottom ofViewController.m:

-(void)attributedLabel:(NIAttributedLabel*)attributedLabel didSelectTextCheckingResult:(NSTextCheckingResult*)result atPoint:(CGPoint)point{[[UIApplication sharedApplication] openURL:result.URL];}

This delegate method is called when a link is selected. It simply requestsUIApplication to open the URL, which will result in Safari being launched to open it.

But how can one add a link to the label displayed in the app? Simple, just change the implementation ofloadShow: in section #5 so that the label displaying the show title is anNIAttributedLabel instead of a UILabel.

Replace the // 5 - Display the show title section with the following:

// 5 - Display the show titleNIAttributedLabel*titleLabel=[[NIAttributedLabel alloc] initWithFrame:CGRectMake(index* CGRectGetWidth(self.showsScrollView.bounds),40, CGRectGetWidth(self.showsScrollView.bounds),40)];titleLabel.text= showDict[@"title"];titleLabel.backgroundColor=[UIColor clearColor];titleLabel.linkColor=[UIColor redColor];titleLabel.font=[UIFont systemFontOfSize:18];titleLabel.textAlignment= NSTextAlignmentCenter;[titleLabel addLink:[NSURL URLWithString:showDict[@"url"]] range:NSMakeRange(0, titleLabel.text.length)];titleLabel.delegate= self;

The main difference is the existence of linkColor, andaddLink:. It’s also important to set the label’s delegate toself, which represents the current instance of theViewController.

Build and run, and you will see the show title in red. If you click it, Safari will open with the show page from trakt!

Where To Go From Here?

You can download the completed project from here.

Now that you know the basics of using CocoaPods, you can read through theCocoaPods Guides to learn the finer details of using CocoaPods, including how to create your own pod spec and submit it to theofficial repository.

To check if CocoaPods already supports a specific library, you can search theCocoaPods website.

Here are some of the libraries I think are most useful:

  • AFNetworking: Network connectivity and response handling.

  • CorePlot: Graphing and plotting framework.

  • MagicalRecord: Super Awesome Easy Fetching for Core Data 1!!!11!!!!1!

  • MBProgressHUD: An activity indicator that can be added to your views.

  • Nimbus: The iOS framework that grows only as fast as its documentation.

You should also check out the trakt API. It’s well-documented, and you can do a lot of things with it.

Regarding the sample application, there are many improvements you could make, such as:

  • What happens if there isn’t a TV show for the given date range?

  • What if there are a lot of shows? None of the pages that are loaded are thrown away, and this can quickly consume a lot of memory!

  • There’s more information to be displayed – like a synopsis, the channel airing the show, etc.

I hope you enjoyed the tutorial, and I look forward to reading your comments in the forums.

Know of another useful library? Tell us about it! Have you created a pod spec? Let us know about that too!



0 0
原创粉丝点击