此文是iOS教程组成员Linda Burke(一个独立的iOS开发人员,是canApps创始人)发布的。你是一个熟练其他平台,但想开始学习iPhone开发(这里主要是说Objective-C)的软件工程师吗?坦率的讲,这是我不久之前的情况,我觉得自己有点迟钝,而且离我的开发工作越来越远。
大约2年过去了,我创建许多iPhone和iPad应用。我经常不得不刻苦学习,我想你或许可以从我的尝试和痛苦中受益良多。
此教程的读者是拥有很多编程经验的人。如果完全是一个编程新手,你可能需要去看我们的iOS for High School Students 系列教程。
此教程目标是给你信心,讲Objective-C基础,而不是讲一些“让我们解释一下每个语法片段”方法,我们想深入浅出并给你一些实战经验和来自工作中的例子。当你需要深入学习的时候,这样会便于你查阅参考手册。
此教程中,教会你创建一个简单的应用,根据存储列表随机生成报价。这样,你就会熟悉Objective-C很多方面,包括:
· Variables变量
· Arrays数组
· Property lists属性列表
· Strings字符串
· Predicates?判断?
· Random selection随机选择
· Simple interface objects and events简单的接口对象和事件
事先警告你-使用Objective-C 做iPhone开发是有趣且容易上瘾的。准备好少睡懒觉,积攒零散时间哦!:]
开始之前,请确认你有Apple开发者账户和证书细节设置,以及已安装最新的Xcode版本(你可以从Mac App Store上免费下载)
这些都完成后,我将带你入门Objective-C.
Getting Started
首先要做的是:创建一个Xcode工程
启动xcode并创建一个选择iOS\Application\Single View Application末班的新的工程。然后点击Next(下一步),输入工程名称“QuoteGen” .输入你的默认公司标识,设置设备组为iPhone,确保使用arc是选中的(让其他的复选框不选中)。现在点击下一步,并选好你的工程存储位置。
你会注意到你的工程创建了AppDelegate.h, AppDelegate.m,ViewController.h 和ViewController.m 文件, 还有一个 ViewController.xib.
AppDelegate包含了初始化应用的代码。在本教程中,你知道这些就行了。下面是你会直接修改的其他文件的简要说明:
· ViewController.xib(简言之就是XIB文件)是一个接口布局文件,你经常用此文件创建/设计在iphone设备在显示在屏幕上
· ViewController.m 是一个接口控制器类,接口布局文件被连接到此类,这是自动发生的,所以此阶段你不需要考虑它,只要知道它是在你的接口类中简单设置对象和事件的。这是你创建的包括Objective-C代码的文件。
· ViewController.h 是一个接口控制器类的头文件,你会在此声明实例变量,定义访问接口屏幕的对象和事件
Note:两种方式都很有效,在本教程中我们使用XIB,但如果你想尝试Storyboard,课后请查阅this tutorial .
Heading in the Right Direction
开始创建你需要存储你的报价的变量属性声明。你需要知道在什么地方增加这些变了。是的,在类的头文件中,ViewController.h! 增加一个数组位于@interface和@end之间:
@property (nonatomic, retain) NSArray *myQuotes;
Property指令会告诉编译器,变量myQuotes是类的一个属性。不需要太深入了解此话题-日后会遇到复杂的内存管理-属性nonatomic 和retain 是为了提高效率广泛使用的。这个monatomic属性指定属性在非多线程环境下。Retain意味着指给变量一个指针像已存在的ViewController对象一样会保存在内存中。
Note:下面仅供参考,retain关键字和strong同义的。在Objective-C中,你经常不得不自己处理内存管理,但现在有一个叫ARC的特性,它是自动的,如果想了解更多关于ARC内容,请查阅 this tutorial.
This app is also going to store some famous quotes from movies. For this, you need a second array:
此应用会存储很多奇怪的引用,所以,你需要第二个数组:
@property (nonatomic, retain) NSMutableArray *movieQuotes;
这里使用NSMutableArray简单的阐述不同类型的数组的差别。稍后有更多阐述。
Manual Labor 手动实现
现在你需要“合成(synthesize)”那些数组 —— 这样,如果你没有在@implementation中提供setter/getter方法,就可以让编译器知道它应该为property声明的属性,合成setter 和/或者 getter方法。
为了实现以上特性,编辑ViewController.m文件,在@implementation声明行的下面添加一下两行:
@synthesize myQuotes; @synthesize movieQuotes;
@synthesize 提供默认的操作对象(object)的getting和setting方法。简单来说,这些方法允许你想数组里面添加数据或者检索数据以便显示。
现在你可以在myQuotes数组中存储你想要的对象的指针。再viewDidLoad方法中做这些操作,这个方法是当View(screen)显示的时候执行的。这个方法只执行一次,因此对象(引用)队列不回改变,所以viewDidLoad是执行这些操作的好的“地方”。
再viewDidLoad,[super viewDidLoad];语句后 ,添加下面的代码。包括你想要添加的对象(指针)这个就是“手动实现-manual labor”的方法,并且对于比较少的数据量来说,这样实现还算ok。
// 1 - Add array of personal quotes self.myQuotes = [NSArray arrayWithObjects: @"Live and let live", @"Don't cry over spilt milk", @"Always look on the bright side of life", @"Nobody's perfect", @"Can't see the woods for the trees", @"Better to have loved and lost than not loved at all", @"The early bird catches the worm", @"As slow as a wet week", nil];
这是调用方法的第一个例子。相比其他语言的语法,这样的语法比较难:
· ·当调用方法的时候,你需要用方括号将你想要调用的方法名所属的对象名括起来。在这个例子中,我们将要调用一个NSArray的静态方法。
· 然后,写出方法名(方法的第一个部分),和一个冒号。这个例子就是arrayWithObjects。
• 然后写出第一个参数。“arrayWithObjects:”这个方法有一点特殊,因为这是一个变长参数方法,因此我们可以将想要添加的对象列表作为参数传递给数组,并以nil结尾。
• 如果方法有多个参数,你会继续以这样的方式,即使这个方法有一个参数(是一个对象列表)。
如果你还在为语法迷茫,不要担心—— 一会儿,我们还将会看到大量的调用方法的例子。
同时注意,在Objective-C,当你使用字符串的时候,要在字符串的前面添加“@”符号。如果你以前经常使用的是其他语言,很容在字符串前面添加“@”符号,这就会很容易引起app的崩溃。所以,当程序使用字符串的时候崩溃了,仔细检查你是否填添加了“@”符号。
SELF HELP self关键字
使用“self”关键字,默认调用property声明的属性的setting 和 getting方法。“self”关键字和其他语言的“this”关键字相似,引用指向的对象是当前调用方法的对象。
你可以不通过“self”关键字直接访问实例变量,但是通过“self”关键字, 我们可以自动调用property声明的属性的getters和setters方法。除非你知道直接访问实例变量的原因。不然使用self关键字对于初学者是一个好的习惯。
每次分配了一个“保留的(retained)”属性,确保你在ViewDidUnload方法中清楚了这个属相,如下代码:
movieQuotes=nil; myQuotes=nil;
这很重要, 当view“倾销”的时候(在低内存出现的这种情况, 这是view就不可用了),确保你的对象(指针)数组被正确释放了。基本上代表性地操作就是在ViewDidUnload方法中做的操作和ViewDidLoad方法中的操作相反。
好的,现在我们已经设置了这些对象(指针)数组,让我们试试它们!
首先,声明 要关联到XIB文件的“接口元素和动作 (interface elements and actions),将下面几行代码添加到ViewController.h文件中:
@property (nonatomic, retain) IBOutlet UITextView *quote_text; -(IBAction)quote_btn_touch:(id)sender;
IBOutlet关键字指的是quote_text这个对象可以关联到XIB文件中的“接口元素(interface element)”,这样“视图控制器(view controller)”就可以访问(或者修改)“接口元素(interface element)”。这种情况下,我们就可以设置UITextView显示的文本,除此之外,我们也可以修改颜色,字体,大小,等等。
IBAction关键字表明quote_btn_touch是一个响应方法, 是关联到屏幕UI控件事件的响应方法。这个例子中,我们将改方法关联到quote按钮的“触摸事件(touched event)”。
如果你想知道,id意味着“任何继承与NSObject类的实例化对象”。通常,当我们设置按钮或者其他控件的响应事件的回调方法, 当事件发生, 回调响应的方法,他们会将,按钮或者其他控件作为第一个参数传递给回调方法。所以我们不必知道参数是什么类型的,所以我们声明了一个id类型的参数。
一旦,你需要合成(synthesize)你新添加property声明的属性,在ViewController.m文件中添加以下语句:
@synthesize quote_text;
同时,不要忘记在ViewDidUnload方法property声明的属性:
quote_text=nil;
现在创建“事件响应方法(action method)”,当quote被点击时,该响应方法被调用。再文件下面部分(@end语句之上),添加下面的声明:
-(IBAction)quote_btn_touch:(id)sender { // 1 - Get number of rows in array int array_tot = [self.myQuotes count]; // 2 - Get random index int index = (arc4random() % array_tot); // 3 - Get the quote string for the index NSString *my_quote = [self.myQuotes objectAtIndex:index]; // 4 - Display the quote in the text view self.quote_text.text = [NSString stringWithFormat:@"Quote:\n\n%@", my_quote]; }
arc4random方法是用来产生随机数的。这种情况下,我们想要随机访问“对象(指针)队列里”的对象,随机数的最大值是数组中的有效的元素个数,最小值是0。再Objective-C(类似其他语言),数组的第一个元素是0,而不是1.
index仅仅是一个临时变量,用来存储产生的随机数字 ,我们通过随机数字访问数组中特定的对象(指针),例子中的数组是一个简单的字符串数组,通过调用objectAtIndex:方法来获得对象(指针),并将该指针存储再一个字符串类型的临时变量中。
然后你就可以使用临时的字符串变量my_quote来设置quote_text控件的文显示。
调用stringWithFormat方法格式化最终显示的字符串。它显示的是替代变量,和C/C++的printf类似。%f指的是float类型变量,%d 指的是 integer 类型变量,%@ 指的是 Objective-C 对象(object)类型。
现在,为了再屏幕中看到响应的字符串,你需要将类中的outlet的text field的对象和XIB文件中的text field控件相关联。
We Have Lift Off!我们已经有所提升
为了看到所有的响应事件的类型,打开ViewController.xib文件。接下来,查看一下xcode窗口的右侧边栏。如果没有看到右侧边栏,你可能需要在顶部的工具栏中,在设View部分点击最右边的按钮,这样就可以,显示右侧边栏。
再右侧边栏的下侧有4个标签,你可以通过点击图标切换。下部可以查看UI控件的“Object Library”。Pasted Graphic 4.tiff ¬
从“Object Library”中,拖拽一个Text View控件和Round Rect 按钮控件到view上。按照你一意愿在view上排列这些控件。在按钮上添加标题,例如“Quote”。你可以按照意愿改变控件的颜色和字体。你可以在右侧边栏的上半部分的几个标签中修改控件的大部分属性——这样你可以在“Attributes Inspector”标签定制控件的外观。
因为text field只是用来显示,还有相应的事件——可编辑。
现在你需要将那个button和text view关联到类中声明的outlet 和 action。
关联选中text view右击鼠标,点击“New Reference Outlet”那个圆圈,拖拽到“File’s Owner”,松开,再弹出框中选择quote_text。
二者择一,你可以简单的在“File’s Owner”中操作,或者在右侧边栏的顶部切换到“Connections Inspector”标签。在File’s Owner中你可以看见controller类中所有的可关联的变量。你现在可以简单关联中拖拽到要关联的UI控件上。
现在,你可以通过代码修改quote_text对象,来设置设置text view文本显示的内容。
同样,我们也可以绑定添加到XIB文件中按钮的触摸事件到quote_btn_touch响应方法。选中xib中要关联的按钮,再右侧边栏中在Touch Up Inside选项前拖拽到“Files’s Owner”,并再弹出框中选择quote_btn_touch。
另外, 你可以简单的选中XIB 视图中的 button,在右侧边栏Connections Inspector中,你可以看见button事件的列表。现在从“Touch Up Inside”事件拖拽到“File’s Owner”,然后你就会获得一个可能的响应事件方法的列表。悬着一个你想要的
点击Xcode的Run按钮(xcode窗口顶部的第一个按钮)。完成应用程序的编译和运行。
如果这有报错,不要恐慌。这个阶段,报错应该是自说明的,通常是你声明的变量类型有误。记住,xcode是区分大小写。
“How so?” you ask?
如果你的应用程序通过编译, 并运行,然后点击Quote按钮获取随机的对象数据。
啊,属性列表的乐趣是快要到了!我非常喜欢属性列表。
Property Lists Rule!
用iOS\Cocoa Touch\Objective-C模板创建一个新文件。命名为SMNote然后设置其为UIDocument的子类。
在左侧边栏(项目导航栏)的你的项目的根节点处点击右键,选择“New File …”来创建一个新文件。选择 iOS\Resource\Property List,然后点击“Next”。选择一个位置来保存你的新文件(在教程中我们通常选择在项目文件夹的里面)并命名为“quotes”。
你可以在XCode的网格视图中编辑属性表或者像文本文件一样编辑。如果你想要像文本文件一样处理,在导航栏的quotes文件点击右键然后选择Open As\Source Code。
因为我们要通过复制黏贴来快速的添加所有对白,以源码的形式打开(即以文本文件方式)可能会更加快捷。如果你想的话,你也可以尝试在网格视图的方式来尝试弄清楚怎样增加下面框框中同样的内容。
现在,复制黏贴以下的电影对白信息到quotes 中(在文本编辑模式下)
<?xml version="1.0" encoding="UTF-8"?> <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd"> <plist version="1.0"> <array> <dict> <key>category</key> <string>classic</string> <key>quote</key> <string>Frankly, my dear, I don't give a damn.</string> <key>source</key> <string>Gone With the Wind</string> </dict> <dict> <key>category</key> <string>classic</string> <key>quote</key> <string>Here's looking at you, kid.</string> <key>source</key> <string>Casablanca</string> </dict> <dict> <key>category</key> <string>classic</string> <key>quote</key> <string>There's no place like home.</string> <key>source</key> <string>The Wizard of Oz</string> </dict> <dict> <key>category</key> <string>classic</string> <key>quote</key> <string>Play it again, Sam.</string> <key>source</key> <string>Casablanca</string> </dict> <dict> <key>category</key> <string>classic</string> <key>quote</key> <string>Elementary, my dear Watson.</string> <key>source</key> <string>Sherlock Holmes</string> </dict> <dict> <key>category</key> <string>modern</string> <key>quote</key> <string>Go ahead, make my day.</string> <key>source</key> <string>Dirty Harry</string> </dict> <dict> <key>category</key> <string>modern</string> <key>quote</key> <string>May the Force be with you.</string> <key>source</key> <string>Star Wars</string> </dict> <dict> <key>category</key> <string>modern</string> <key>quote</key> <string>Hasta la vista, baby.</string> <key>source</key> <string>Terminator 2: Judgement Day</string> </dict> <dict> <key>category</key> <string>modern</string> <key>quote</key> <string>It takes a great deal of bravery to stand up to your enemies, but a great deal more to stand up to your friends.</string> <key>source</key> <string>Harry Potter and the Sorcerer's Stone</string> </dict> <dict> <key>category</key> <string>modern</string> <key>quote</key> <string>I solemnly swear that I am up to no good.</string> <key>source</key> <string>Harry Potter and the Prisoner of Azkaban</string> </dict> <dict> <key>category</key> <string>modern</string> <key>quote</key> <string>You like pain? Try wearing a corset.</string> <key>source</key> <string>Pirates of the Caribbean</string> </dict> </array> </plist>
这里只是使用一些对白来作为例子。你乐意的话可以增加一些你喜欢的。如果你懒,示例项目中有一个有很多对白的属性表。对白被分类成了经典和现代两个种类,稍后用来说明一个非常实用的功能。
你也可以切换到属性表视图(在quotes 文件右键然后选择Open As\Property List)来看看你刚才加的值以及他们的组织形式。现在你已经懂得如何在不同的编辑方式下处理,你可以随你喜欢的来回切换。
属性表看起来很酷,但是如果有错误的时候你可能会很不爽。新手常见错误就是忘记增加末尾标识或者意外的删除了< or >。如果你的属性表不能正常加载,那你就必须去找出为什么。
如果你卡在这里,你需要有条不紊的浏览你的文件。我常常这么做以求变的更简单:复制我的plist文件,然后一次删除一个代码块来大致的确定我的错误的位置。
创建完你可爱的属性表后,你现在已经做好把它加载进一个数组来使用的准备。切换回 ViewController.m ,在viewDidLoad 后面加上以下内容:
// 2 - Load movie quotes NSString *plistCatPath = [[NSBundle mainBundle] pathForResource:@"quotes" ofType:@"plist"]; self.movieQuotes= [[NSMutableArray arrayWithContentsOfFile:plistCatPath] copy];
就是这么简单—-现在你有了一个你输入进属性表的所有电影对白数据的数组。
看看你的新数组,你可能认为你现在最需要做的是改变从电影对白数组中随机获得的数据。所以,在quote_btn_touch中有简单的把movieQuotes的数据替换成myQuotes 的例子。
但是如果你尝试过你会发现这不会生效。这是因为因为myQuotes 是一个字符串数组。但是movieQuotes 并不是一个字符串数组。恰恰相反,这这是一个字典数组,字典是一个有着一个列表的值,你可以通过一个独一无二的键来访问他们。
为什么呢?因为那就是你设置成属性表的的样式。
注解:字典是用来保存键/值的,和其他语言的哈希表很像。你可以看看字典中的valueForKey 方法。
因此用下文的内容来替换quote_btn_touch,代码中使用movieQuotes 数组,来获取每个字典,而且根据正确的键值获取了对白。
-(IBAction)quote_btn_touch:(id)sender { // 1 - Get number of rows in array int array_tot = [self.movieQuotes count]; // 2 - Get random index int index = (arc4random() % array_tot); // 3 - Get the quote string for the index //NSString *my_quote = [self.myQuotes objectAtIndex:index]; NSString *my_quote = [[self.movieQuotes objectAtIndex:index] valueForKey:@"quote"]; // 4 - Display the quote in the text view self.quote_text.text = [NSString stringWithFormat:@"Quote:\n\n%@", my_quote]; }
让第三行代码保持在注释状态,因为这稍后会派上用场。编译运行然后享受你的新成果!
现在,你可以有点花俏的允许用户在myQuotes 或movieQuotes中选择经典电影或现代电影台词了。
选项选项选项
首先你需要回到你的ViewController.h,头文件并增加一个属性。
@property (nonatomic, retain) IBOutlet UISegmentedControl *quote_opt;
在这里你增加了一个允许你从一堆选项选出一项的分段控件-这对于我们的选取对白种类是多么完美。
当然,你需要synthesize 你的新属性。在ViewController.m的头部(其他@synthesize语句那一带)增加以下内容。
@synthesize
现在切换到ViewController.xib 并且拖一个分段控件(UISegmentedControl )到你的视图上。
根据以下内容改变控件的属性:
· Style: Bar (my personal preference)
· Tint: whatever you like
· Segments: 3
· Select Segment: 0 and change the title to: Classic
· Select Segment: 1 and change the title to: Modern
· Select Segment: 2 and change the title to: Mine
这达到了有3个不同的对白种类的效果,更确切的说,你可以在3个选项中选择一个了。
创建完了分段控件,你必须把它和类文件中的outlet 属性连接起来。
你可以使用同样的方法,就像之前把控件和File‘s owner中的quote_opt联接起来一样。
对于这个控件,你不需要定义动作事件。
在你做其他事情之前,记得清理ViewDidUnload这个新的属性。
quote_opt=nil;
为什么不编译运行来看看你的新控件在屏幕上?在现在还不能做任何事情,但是这看起来不错。
判断的乐趣
一个判断是一个非常有用的对象用来过滤一个数组.有点儿像SQL语句中select的从句.我发现他们对于分类属性列表很有用.使我不必再创建单独的属性列表.
不要恨我,但是你要返回和改变 quote_btn_touch: 在ViewController.m 中去用myQuotes 代替
movieQuotes. 你很快就会做一些与众不同的电影对白. 并且你需要设置一个条件去循环, 这样你将仅能选择选择控制器中的第三个选项.
或者,如果你愿意,只需要用下面的代码来更换quote_btn_touch:
-(IBAction)quote_btn_touch:(id)sender { // 1 - Get personal quotes when the final segment is selected if (self.quote_opt.selectedSegmentIndex == 2) { // 1.1 - Get number of rows in array int array_tot = [self.myQuotes count]; // 1.2 - Get random index int index = (arc4random() % array_tot); // 1.3 - Get the quote string for the index NSString *my_quote = [self.myQuotes objectAtIndex:index]; // 1.4 - Display the quote in the text view self.quote_text.text = [NSString stringWithFormat:@"Quote:\n\n%@", my_quote]; } }
现在用户选择第三个选项将看到myQuotes.正如你会发现剩下的代码跟以前一样,唯一的不同是我们显示一个quote(并且 quote来自这个人的quote列表)在只有当选择控制器的index为2的被选择的时候.你可能还记得,选择控制器的index从0开始计算的.index为就是第三个选项.
编译测试你的代码确保可以像期望的那样正常运行,仅当这个”Mine”选项被选的时候 这个quotes 才出现.
首先你找出类别,你需要基于所选择的部分控制,然后使用类别来创建一个过滤后的数组的quotes,匹配类别。
这些在 quote_btn_touch:if声明另一边的代码 –所以简单地添加这个结局的方法来完成这个“if”声明中开始的部分 #1:
// 2 - Get movie quotes else { // 2.1 - determine category NSString *selectedCategory = @"classic"; if (self.quote_opt.selectedSegmentIndex == 1) { selectedCategory = @"modern"; } // 2.2 - filter array by category using predicate NSPredicate *predicate = [NSPredicate predicateWithFormat:@"category == %@", selectedCategory]; NSArray *filteredArray = [self.movieQuotes filteredArrayUsingPredicate:predicate]; // 2.3 - get total number in filtered array int array_tot = [filteredArray count]; // 2.4 - as a safeguard only get quote when the array has rows in it if (array_tot > 0) { // 2.5 - get random index int index = (arc4random() % array_tot); // 2.6 - get the quote string for the index NSString *quote = [[filteredArray objectAtIndex:index] valueForKey:@"quote"]; self.quote_text.text = [NSString stringWithFormat:@"Movie Quote:\n\n%@", quote]; } else { self.quote_text.text = [NSString stringWithFormat:@"No quotes to display."]; } }
那么.编译运行吧.检查你所选择quote的正确类型.如果你总是取到同样的类型,我猜测你没有链接选择控制器到你的类中.
字符串交响曲
到目前为止,都很不错.现在让我们一起探索在Objective-C中不同string的设置跟语法.
假如引用一个属性列表中数据源,那么程序也将会显示出来.进行检查,如果是一个有值的string,
那么你可以检查string的长度.
所以将下列代码添加到quote_btn_touch:在# 2.6部分的第一行后(第一行不包括他们的评论):
// 2.7 - Check if there is a source NSString *source = [[filteredArray objectAtIndex:index] valueForKey:@"source"]; if (![source length] == 0) { quote = [NSString stringWithFormat:@"%@\n\n(%@)", quote, source]; } // 2.8 - Set display string
你从数组获得数据并且检查它包含一个确保长度不为零的值.
!假如你想检验两个整数是否相等不要用==
那么你结合quote和数据源用stringWithFormat构建一个新的显示字符串.
为了让事情更有趣,你为什么不显示一些与quotes稍微不同的经典电影将检查包含所选择的quote类别.
用以下的代码替换quote_btn_touch:#2.8部分的内容:
// 2.8 - Customize quote based on category if ([selectedCategory isEqualToString:@"classic"]) { quote = [NSString stringWithFormat:@"From Classic Movie\n\n%@", quote]; } else { quote = [NSString stringWithFormat:@"Movie Quote:\n\n%@", quote]; } // 2.9 - Display quote self.quote_text.text = quote;
这个检查字符串等于一个特定值,在”经典”的情况下,就自定义基于类别quote 的label
如果你想检查一个特定的电影标题(或事件的任何其他字符串属性)开始于一个特定的值,您也可以这么做。说你想要显示一些额外的文本,如果这引自《哈利·波特》电影——添加以下对以上部分# 2.9:
if ([source hasPrefix:@"Harry"]) { quote = [NSString stringWithFormat:@"HARRY ROCKS!!\n\n%@", quote]; }
你也能猜到, hasPrefix 是用来检查是否开始的字符串有一个特定的文本值。构建和运行您的应用程序,确保它是你想要的。注意不同的类别和哈利·波特电影对白,以确保一切工作正常。
It’s ARRAYning Quotes
只是为了好玩,你要将你所有的quotes连在一起,像没有很多。这将说明如何遍历您可能需要的一个数组,如果你想要遍历一个数组中的每个项目来处理每个项。
在quote_btn_touch中:用以下代码替代#1部分 :
// 1 - Display all personal quotes if (self.quote_opt.selectedSegmentIndex == 2) { // 1.1 - Get array count int array_tot = [self.myQuotes count]; // 1.2 - Initialize string for concatenated quotes NSString *all_my_quotes = @""; // 1.3 - Iterate through array for (int x=0; x < array_tot; x++) { NSString *my_quote = [self.myQuotes objectAtIndex:x]; all_my_quotes = [NSString stringWithFormat:@"%@\n%@\n", all_my_quotes,my_quote]; } self.quote_text.text = [NSString stringWithFormat:@"%@", all_my_quotes]; }
使用for循环来遍历该数组从0行到最后一行。x 是这些行的计数。
现在运行并检查这些结果.
最后一件事。我在前面提到过,有不同类型的数组: NSArray 和NSMutableArray.
到目前为止,在这个工程都是做的同样的工作.
用一个可变数组,假如你想修改或者更新它. 正如其名称所提示的,可变数组可以改变.而正常数组是静态的,你不能添加新元素或删除元素。
例如,如果您想要在为了展示quote已经显示出来的一行被选择后更新数组.那么你需要用一个NSMutableArray.
在这个项目中, movieQuotes就是你的NSMutableArray,你要使用一个predicate. 所以你首先需要去找到movieQuotes中的这行并更新它.在#2.9部分后面添加这段代码
in quote_btn_touch::
// 2.10 - Update row to indicate that it has been displayed int movie_array_tot = [self.movieQuotes count]; NSString *quote1 = [[filteredArray objectAtIndex:index] valueForKey:@"quote"]; for (int x=0; x < movie_array_tot; x++) { NSString *quote2 = [[movieQuotes objectAtIndex:x] valueForKey:@"quote"]; if ([quote1 isEqualToString:quote2]) { NSMutableDictionary *itemAtIndex = (NSMutableDictionary *)[movieQuotes objectAtIndex:x]; [itemAtIndex setValue:@"DONE" forKey:@"source"]; } }
你遍历该数组,并检查每一行看是不是你正在找的。你再一次使用isEqualToString;然而这一次你比较两个字符串变量。
在数组中更新这一行,你在这一行检索这个对象并更新这个对象. 这对于本教程开始变得有点高级,但这是有必要知道的。
在我们更新数据字符串并且这个字符串是用来选择quotes每一个类别的时候,下一次你用NSPredicate过滤这个数组的时候这一行将不被包含.这相当方便.
该去哪里?
下面是上面教程的一个示例项目的所有代码.
这个项目你已经做到一个小完结了.你已经学习了如何用不同的方法使用数组,从接口事件初始化,通过Interface Builder用一个xib文件访问对象和做各种各样的字符串比较和衔接.假如这个是你第一款Iphone应用,那么是一个不错的努力.
现在你知道一些基础了.你可能会想试下我们的How To Create a Simple iPhone App 系列指南,或者
sign up for iTyran 对于IOS初学者.你有什么问题,或者做了些什么,都可以使用我们的论坛. 同样,如果你喜欢这篇教程,希望看到更多的系列,请在论坛让我知道!与此同时,好运和保持快乐!:]