哇又到了iOS编程教程的时间喽。在前面几此教程里,我们已经建立了一个非常简单的表格应用程序来显示食谱列表。如果你回头看看那个应用程序,你会发现所有的食谱都是直接在源代码中赋值的。以前我尽量保持事情的简单,主要集中展示了如何创建一个UITableView并使用它。然而,这不是一个很好的做法。在真正的应用程序中,对于用到的外在静态项目(即菜单信息),我们是把它们放在一个文件或数据库中或其他地方。在iOS编程,有一种这种类型文件叫做属性列表(Property List)。在Mac OS和iOS,这种文件通常用于存储简单的结构化数据(如应用程序设置)。在本教程中,我们将在我们的简单的表格应用程序里作出一些改变,调整它使它能够使用属性列表来存菜单数据。
简单地说,这里有这么一些东西,我们将讨论:
>如何把静态数据转换为属性列表
>如何从属性列表读取数据
为什么要分离数据
把静态数据转换到外部是个很好的做法。但是,为什么呢?把表中的数据转换到外部源的优点是什么?让我们问你,在我们的简单的表格应用程序中添加50个配方。也许,你会回到你的代码,并初始化所有新的食谱:
1
2 3 4 5 6 7 8 |
// Initialize table data
tableData = [ NSArray arrayWithObjects : @ "Egg Benedict", @ "Mushroom Risotto", @ "Full Breakfast", @ "Hamburger", @ "Ham and Egg Sandwich", @ "Creme Brelee", @ "White Chocolate Donut", @ "Starbucks Coffee", @ "Vegetable Curry", @ "Instant Noodle with Egg", @ "Noodle with BBQ Pork", @ "Japanese Noodle with Pork", @ "Green Tea", @ "Thai Shrimp Cake", @ "Angry Birds Cake", @ "Ham and Cheese Panini", nil ]; // Initialize thumbnails thumbnails = [ NSArray arrayWithObjects : @ "egg_benedict.jpg", @ "mushroom_risotto.jpg", @ "full_breakfast.jpg", @ "hamburger.jpg", @ "ham_and_egg_sandwich.jpg", @ "creme_brelee.jpg", @ "white_chocolate_donut.jpg", @ "starbucks_coffee.jpg", @ "vegetable_curry.jpg", @ "instant_noodle_with_egg.jpg", @ "noodle_with_bbq_pork.jpg", @ "japanese_noodle_with_pork.jpg", @ "green_tea.jpg", @ "thai_shrimp_cake.jpg", @ "angry_birds_cake.jpg", @ "ham_and_cheese_panini.jpg", nil ]; // Initialize Preparation Time prepTime = [ NSArray arrayWithObjects : @ "30 min", @ "30 min", @ "20 min", @ "30 min", @ "10 min", @ "1 hour", @ "45 min", @ "5 min", @ "30 min", @ "8 min", @ "20 min", @ "20 min", @ "5 min", @ "1.5 hour", @ "4 hours", @ "10 min", nil ]; |
这样做是没有错。但看代码,这是不容易编辑的,你必须严格遵循客观的C语法。更改代码可能会意外地引入其他错误。这不是我们想要的。显然,这将是更好地分离数据和编程逻辑(即代码)。像下面那样存储,看起来不是会更好么?
在现实中,你可能不是一个自己提供的数据(在这里是食谱信息)。这些信息可能是别人给的,他可能没有iOS的编程经验。当我们把数据放到外部文件时,它将变得更容易阅读/编辑,更容易理解。
随着你的进一步学习,你将学习到如何把数据放到在服务器端(或所谓的云)或从服务器端读取数据。您的应用程序中所有数据按需从服务器推送。它提供了一个很大的好处。现在,如果你的程序有的数据有任何细小的变化都必须从新提交到Apple,并被苹果审批。但是。如果你把数据和程序分离,并把数据放在云中,那么你可以随时随地更改数据而不用经苹果的同意。
今天我们不会谈论云。让我们回到基本,看看你如何把所有的食谱数据放在一个属性列表中。
什么是属性列表
属性列表提供了一个方便的方式来存储简单的结构化数据。它是以XML格式存储的。如果您在MAC或iphone上修改过一些配置文件,你可能会遇到.plist扩展名的文件。它们就是属性列表的例子。
您不能使用属性列表保存所有类型的数据。在属性列表中的项目的数据类型,包括“数组(array)”,“字典(Dictionary)”,“字符串(String)”,等等。对应详细的支持类型,你可以参考官方关于属性列表文件的介绍。
属性列表常被IOS用于保存应用程序设置属性,但这并不意味着你不使用它到其他用途。但它是被设计用于存储少量的数据。
那么什么是存储数据最好的方式呢
现在还不确定。下面让我们使用属性列表来演示如何表中的数据存储在一个外部文件中。这只是一个例子。当你获得更多的经验,你会学习其他的方式来存储数据。
将表数据转换到属性列表中
理论知识讲得差不多了,让我们开始着手,将数据转换成一个属性列表。首先,在Xcode项目打开简单表程序,就是以前的程序了。在“SimpleTable”文件夹上单击鼠标右键,并选择“New File ...”。选择“Other”下的“IOS”模板,选择“属性列表(Proper List)”,然后单击“下一步”继续。
出现提示时,使用“recipes(配方)”作为文件名。一旦您确认,Xcode会为你创建属性列表文件。默认情况下,属性列表是空的。
有两种方法来编辑属性列表。您可以用鼠标右键单击编辑区,然后选择“添加行”,添加一个新的值。
下面我们把三个数据数组添加到属性列表中,我们将添加3行“数组”类型。将它们命名为:recipename,Thumbnail和PrepTime。作为标识符的关键字,以后你就可以使用它在你的代码中来选择相应的数组。
要往数组中添加数据,你先展开它,然后单击“+”图标,添加一个新的项目。如果你不知道该怎么办,按照下面的说明中的步骤,
重复上述过程,直到你添加所有的值到数组。你的菜单清单应该是这样的:
正如前面提到的,通常保存在属性列表数据是XML格式。要查看源代码的属性列表,单击右键,选择“打开源代码”。
“recipes.plist”文件的源代码,会出现这样的:
在Object C中导入属性列表
接下来,我们将改变我们的代码,在从我们刚刚建立的属性列表中加载菜单。这是很容易的去得到属性列表的内容。iOS的SDK已经自带了一些内置的功能来处理读/写文件。
更改下面的代码:
1
2 3 4 5 6 7 8 |
// Initialize table data
tableData = [ NSArray arrayWithObjects : @ "Egg Benedict", @ "Mushroom Risotto", @ "Full Breakfast", @ "Hamburger", @ "Ham and Egg Sandwich", @ "Creme Brelee", @ "White Chocolate Donut", @ "Starbucks Coffee", @ "Vegetable Curry", @ "Instant Noodle with Egg", @ "Noodle with BBQ Pork", @ "Japanese Noodle with Pork", @ "Green Tea", @ "Thai Shrimp Cake", @ "Angry Birds Cake", @ "Ham and Cheese Panini", nil ]; // Initialize thumbnails thumbnails = [ NSArray arrayWithObjects : @ "egg_benedict.jpg", @ "mushroom_risotto.jpg", @ "full_breakfast.jpg", @ "hamburger.jpg", @ "ham_and_egg_sandwich.jpg", @ "creme_brelee.jpg", @ "white_chocolate_donut.jpg", @ "starbucks_coffee.jpg", @ "vegetable_curry.jpg", @ "instant_noodle_with_egg.jpg", @ "noodle_with_bbq_pork.jpg", @ "japanese_noodle_with_pork.jpg", @ "green_tea.jpg", @ "thai_shrimp_cake.jpg", @ "angry_birds_cake.jpg", @ "ham_and_cheese_panini.jpg", nil ]; // Initialize Preparation Time prepTime = [ NSArray arrayWithObjects : @ "30 min", @ "30 min", @ "20 min", @ "30 min", @ "10 min", @ "1 hour", @ "45 min", @ "5 min", @ "30 min", @ "8 min", @ "20 min", @ "20 min", @ "5 min", @ "1.5 hour", @ "4 hours", @ "10 min", nil ]; |
变成:
1
2 3 4 5 6 7 8 |
// Find out the path of recipes.plist
NSString *path = [ [ NSBundle mainBundle ] pathForResource : @ "recipes" ofType : @ "plist" ]; // Load the file content and read the data into arrays NSDictionary *dict = [ [ NSDictionary alloc ] initWithContentsOfFile :path ]; tableData = [dict objectForKey : @ "RecipeName" ]; thumbnails = [dict objectForKey : @ "Thumbnail" ]; prepTime = [dict objectForKey : @ "PrepTime" ]; |
代码里的改变
第2行 -读取“recipes.plist”文件之前,你必须先得到资源路径。
第5行--您已经定义了三个关键字(RecipeName,Thumbnail,PrepTime)的。在该示例中,每个关键字对应一个特定的数组。使用路径得到属性列表的数据,并存到字典中。
第6-8 -这些代码行中通过我们前面定义的关键字检索相应的数组。
一旦你完成更改后,再次尝试运行的应用程序。这个应用程序是像以前一样。但是,在内部从属性清单的食谱加载。