iOS开发:REST API调用与Core Data使用指南
1. REST API调用
在iOS开发中,我们经常需要与REST API进行交互,获取或发送数据。下面将介绍如何使用
RestClient
类进行GET和POST请求。
1.1 使用RestClient进行GET请求
RestClient
类结合了两个其他的功能,用于处理REST API的请求。要使用这个类,你需要将
RestClient
、
JSONParser
和
JSON
类包含到你的应用中。以下是具体步骤:
1.
创建新的iOS单视图应用
:在Xcode中创建一个新的iOS单视图应用项目。
2.
添加类文件
:将
RestClient
、
JSONParser
(清单9 - 1)和
JSON
(清单9 - 2)类添加到项目中。
3.
替换
ViewController.swift
内容
:将
ViewController.swift
的内容替换为清单9 - 10的代码。
以下是
RestClient
类的完整代码(清单9 - 9):
import Foundation
public class RestClient {
public class func Get(url : String, callback : (JSON?, NSError?)->()) {
let url = NSURL(string: url)
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {
(data, response, error) in
if let err = error {
callback(nil, err)
}
// attempt to parse
var parseError : NSError?
var parsedData = JSONParser.parse(data, error: &parseError)
if let err = parseError {
callback(nil, err)
}
callback ( parsedData, nil)
}
task.resume()
}
}
以下是使用
RestClient
类的示例代码(清单9 - 10):
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
RestClient.Get("https://openlibrary.org/works/OL11315329W") { (json, error) -> Void in
if let err = error {
println("Error: \(error?.localizedDescription)")
return
}
if let j = json {
var title = j["title"]?.stringValue
var revision = j["revision"]?.intValue
println("Title: \(title!)")
println("Revision: \(revision!)")
}
}
}
}
运行这个应用,你将在控制台看到类似以下的输出:
Title: Mastering the Art of French Cooking
Revision: 6
1.2 使用RestClient进行POST请求
当你需要向REST API发送POST请求时,可以使用
NSURLSession
和
NSJSONSerialization
的组合。以下是具体步骤:
1.
准备数据
:将需要发送的数据放入一个
[String, AnyObject]
字典中。例如:
var data: [String: AnyObject] = ["name" : "Pea Soup",
"Ingredients" : "Split Peas, Water, Chicken Broth, Milk, Salt, Onions"]
-
调用
RestClient的Post方法 :
RestClient.Post("http://echo.jsontest.com/status/OK", data: data) { (json, error) -> Void in
if let err = error {
println("Error: \(error?.localizedDescription)")
return
}
if let j = json {
var status = j["status"]?.stringValue
println("Status: \(status!)")
}
}
以下是包含
Post
方法的
RestClient
类的完整代码(清单9 - 11):
import Foundation
public class RestClient {
public class func Get(url : String, callback : (JSON?, NSError?)->()) {
let url = NSURL(string: url)
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) {
(data, response, error) in
if let err = error {
callback(nil, err)
}
// attempt to parse
var parseError : NSError?
var parsedData = JSONParser.parse(data, error: &parseError)
if let err = parseError {
callback(nil, err)
}
callback ( parsedData, nil)
}
task.resume()
}
public class func Post(url : String, data : [String: AnyObject], callback : (JSON?, NSError?)->()) {
let url = NSURL(string: url)
var request = NSMutableURLRequest(URL: url!)
request.HTTPMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-type")
request.addValue("application/json", forHTTPHeaderField: "Accept")
var paramError : NSError?
var paramData = NSJSONSerialization.dataWithJSONObject(data,
options: NSJSONWritingOptions.allZeros, error: ¶mError)
request.HTTPBody = paramData
println("POST DATA")
println(NSJSONSerialization.JSONObjectWithData(paramData, options: nil, error: nil)!)
let task = NSURLSession.sharedSession().dataTaskWithRequest(request) {
(data, response, error) in
if let err = error {
callback(nil, err)
}
// attempt to parse
var parseError : NSError?
var parsedData = JSONParser.parse(data, error: &parseError)
if let err = parseError {
callback(nil, err)
}
callback ( parsedData, nil)
}
task.resume()
}
}
以下是
ViewController.swift
中使用
Post
方法的代码(清单9 - 12):
import UIKit
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
var data: [String: AnyObject] = [ "name" : "Pea Soup",
"Ingredients" : "Split Peas, Water, Chicken Broth, Milk, Salt, Onions" ]
RestClient.Post("http://echo.jsontest.com/status/OK", data: data) { (json, error) -> Void in
if let err = error {
println("Error: \(error?.localizedDescription)")
return
}
if let j = json {
var status = j["status"]?.stringValue
println("Status: \(status!)")
}
}
}
}
运行这个应用时,会向JSONTest.com发送请求,请确保你已连接到互联网。在发送数据之前,数据的JSON版本会打印到控制台,你可以看到其格式。JSONTest.com会返回一个包含单个键值对的JSON字符串,完成处理程序会打印出状态值。你应该会在控制台看到类似以下的输出:
POST DATA
{
Ingredients = "Split Peas, Water, Chicken Broth, Milk, Salt, Onions";
name = "Pea Soup";
}
Status: OK
2. Core Data使用
Core Data是许多数据驱动的iOS和OS X应用的核心。它可用于存储、在网络和设备间同步信息,以及快速访问大型数据集。以下将介绍如何使用Core Data进行数据管理。
2.1 创建数据模型
当你想要设计使用Core Data持久化的实体时,需要创建一个数据模型。以下是具体步骤:
1.
添加Core Data框架
:在Xcode中创建一个新的iOS主 - 详细应用,保存项目后,在项目中添加Core Data框架。选择应用目标“Core Data”和“Build Phases”选项卡,在“Link Binary With Libraries”下点击加号按钮,从列表中选择“CoreData.framework”并点击添加。
2.
创建数据模型文件
:在项目中添加一个新文件,在新文件对话框的“Core Data”部分选择“Data Model”,将新文件保存为
RecipeBook
。
3.
定义实体和属性
:打开数据模型文件,在Xcode的数据模型编辑器中,点击“Add Entity”添加一个新实体,将其重命名为
Recipe
。为
Recipe
实体添加属性,如
name
(类型为
String
)、
serves
(类型为
Integer 32
)和
recipeDescription
(类型为
String
)。在“Relationships”部分添加一个名为
ingredients
的关系。
4.
创建另一个实体
:创建一个名为
Ingredient
的新实体,为其添加
measurement
(类型为
Int16
)和
ingredient
(类型为
String
)属性。在“Relationship”部分添加一个名为
parentRecipe
的关系,将其目标设置为
Recipe
类,并将逆关系设置为
ingredients
。回到
Recipe
实体,完成
ingredients
关系的设置,将目标设置为
Ingredient
类,逆关系设置为
parentRecipe
。
2.2 创建模型类
有了数据模型后,你可以使用Xcode为实体生成类。以下是具体步骤:
1.
打开数据模型
:在Xcode中打开数据模型文件。
2.
生成实体代码
:在菜单栏中选择“Editor” -> “Create NSManagedObject Subclass”。在弹出的对话框中,确保选择了
RecipeBook
数据模型,然后点击“Next”。
3.
选择实体
:选择
Recipe
和
Ingredient
实体,点击“Next”。
4.
选择语言和保存位置
:确保选择了Swift作为语言,最后选择类文件的保存位置。
以下是生成的
Recipe
实体类代码(清单10 - 1):
import Foundation
import CoreData
class Recipe: NSManagedObject {
@NSManaged var name: String
@NSManaged var recipeDescription: String
@NSManaged var serves: NSNumber
@NSManaged var ingredients: NSOrderedSet
}
以下是生成的
Ingredient
实体类代码(清单10 - 2):
import Foundation
import CoreData
class Ingredient: NSManagedObject {
@NSManaged var ingredient: String
@NSManaged var measurement: NSNumber
@NSManaged var parentRecipe: Recipe
}
2.3 创建数据存储
你需要创建或打开一个现有的数据存储。可以通过实例化
NSManagedObjectModel
和
NSPersistentStoreCoordinator
来实现。以下是具体步骤:
1.
创建辅助类文件
:在项目中创建一个新文件
CoreDataHelper.swift
,用于包含辅助类。
2.
定义类和初始化器
:在
CoreDataHelper.swift
中定义
CoreDataHelper
类和初始化器,设置模型名称和数据文件名称的属性。
import Foundation
import CoreData
public class CoreDataHelper {
var modelName : String
var datastoreFileName : String
init( modelName : String, datastoreFileName : String) {
self.modelName = modelName
self.datastoreFileName = datastoreFileName
}
}
-
创建
NSManagedObjectModel实例 :使用lazy关键字定义一个NSManagedObjectModel属性,并使用立即调用的闭包进行初始化。
lazy var managedObjectModel: NSManagedObjectModel = {
let modelURL = NSBundle.mainBundle().URLForResource("RecipeBook", withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
-
创建
NSPersistentStoreCoordinator实例 :同样使用lazy关键字定义一个NSPersistentStoreCoordinator属性。
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let documentsDirectory : NSURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).last as! NSURL
let url = documentsDirectory.URLByAppendingPathComponent(self.datastoreFileName)
var error: NSError? = nil
let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options, error: &error) == nil {
coordinator = nil
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = "There was an error creating or loading the data store"
}
return coordinator
}()
在创建数据存储时,需要处理可能出现的错误。如果数据存储无法打开,文件可能已损坏或迁移时出现问题。你可以使用开源工具“SQLite Database Browser for OS X”打开和编辑SQLite文件,同时可以通过启用iTunes文件共享让用户将文件发送给你进行修复。
通过以上步骤,你可以在iOS应用中实现REST API调用和Core Data数据管理,为应用的数据交互和存储提供强大的支持。
2.4 创建托管对象上下文
托管对象上下文(Managed Object Context)是 Core Data 中的一个重要概念,它充当对象的暂存区,用于管理对象的生命周期和跟踪对象的变化。以下是创建托管对象上下文的步骤:
-
在
CoreDataHelper类中添加方法 :在CoreDataHelper.swift文件中,为CoreDataHelper类添加一个方法来创建托管对象上下文。
import Foundation
import CoreData
public class CoreDataHelper {
var modelName : String
var datastoreFileName : String
init( modelName : String, datastoreFileName : String) {
self.modelName = modelName
self.datastoreFileName = datastoreFileName
}
lazy var managedObjectModel: NSManagedObjectModel = {
let modelURL = NSBundle.mainBundle().URLForResource("RecipeBook", withExtension: "momd")!
return NSManagedObjectModel(contentsOfURL: modelURL)!
}()
lazy var persistentStoreCoordinator: NSPersistentStoreCoordinator? = {
var coordinator: NSPersistentStoreCoordinator? = NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
let documentsDirectory : NSURL = NSFileManager.defaultManager().URLsForDirectory(.DocumentDirectory, inDomains: .UserDomainMask).last as! NSURL
let url = documentsDirectory.URLByAppendingPathComponent(self.datastoreFileName)
var error: NSError? = nil
let options = [NSMigratePersistentStoresAutomaticallyOption: true, NSInferMappingModelAutomaticallyOption: true]
if coordinator!.addPersistentStoreWithType(NSSQLiteStoreType, configuration: nil, URL: url, options: options, error: &error) == nil {
coordinator = nil
var dict = [String: AnyObject]()
dict[NSLocalizedDescriptionKey] = "Failed to initialize the application's saved data"
dict[NSLocalizedFailureReasonErrorKey] = "There was an error creating or loading the data store"
}
return coordinator
}()
func managedObjectContext() -> NSManagedObjectContext {
let context = NSManagedObjectContext(concurrencyType: .MainQueueConcurrencyType)
context.persistentStoreCoordinator = self.persistentStoreCoordinator
return context
}
}
-
使用托管对象上下文
:在需要使用托管对象上下文的地方,调用
CoreDataHelper类的managedObjectContext()方法。
let helper = CoreDataHelper(modelName: "RecipeBook", datastoreFileName: "RecipeBook.sqlite")
let context = helper.managedObjectContext()
2.5 添加新实体
当你需要向 Core Data 存储中添加新实体时,可以使用托管对象上下文。以下是添加新
Recipe
实体的步骤:
-
获取托管对象上下文
:使用前面创建的
CoreDataHelper类获取托管对象上下文。
let helper = CoreDataHelper(modelName: "RecipeBook", datastoreFileName: "RecipeBook.sqlite")
let context = helper.managedObjectContext()
-
创建新实体
:使用
NSEntityDescription.insertNewObjectForEntityForName方法创建新的Recipe实体。
let newRecipe = NSEntityDescription.insertNewObjectForEntityForName("Recipe", inManagedObjectContext: context) as! Recipe
newRecipe.name = "New Recipe"
newRecipe.serves = 4
newRecipe.recipeDescription = "This is a new recipe."
-
保存上下文
:调用托管对象上下文的
save方法将更改保存到数据存储中。
do {
try context.save()
print("New recipe saved successfully.")
} catch {
let nserror = error as NSError
print("Unresolved error \(nserror), \(nserror.userInfo)")
}
2.6 创建
NSFetchRequest
NSFetchRequest
用于从 Core Data 存储中检索数据。以下是创建
NSFetchRequest
并执行查询的步骤:
-
创建
NSFetchRequest对象 :指定要检索的实体名称。
let fetchRequest = NSFetchRequest(entityName: "Recipe")
-
设置查询条件(可选)
:可以使用谓词(
NSPredicate)来过滤查询结果。
let predicate = NSPredicate(format: "serves > %d", 2)
fetchRequest.predicate = predicate
-
执行查询
:使用托管对象上下文的
executeFetchRequest方法执行查询。
let helper = CoreDataHelper(modelName: "RecipeBook", datastoreFileName: "RecipeBook.sqlite")
let context = helper.managedObjectContext()
do {
let results = try context.executeFetchRequest(fetchRequest)
for recipe in results as! [Recipe] {
print("Recipe name: \(recipe.name)")
}
} catch {
let nserror = error as NSError
print("Unresolved error \(nserror), \(nserror.userInfo)")
}
2.7 使用获取结果控制器填充
UITableView
获取结果控制器(
NSFetchedResultsController
)可以方便地将 Core Data 查询结果绑定到
UITableView
上。以下是使用获取结果控制器填充
UITableView
的步骤:
-
创建获取结果控制器
:在
ViewController类中创建NSFetchedResultsController实例。
import UIKit
import CoreData
class ViewController: UIViewController, UITableViewDataSource, NSFetchedResultsControllerDelegate {
@IBOutlet weak var tableView: UITableView!
var fetchedResultsController: NSFetchedResultsController!
override func viewDidLoad() {
super.viewDidLoad()
let helper = CoreDataHelper(modelName: "RecipeBook", datastoreFileName: "RecipeBook.sqlite")
let context = helper.managedObjectContext()
let fetchRequest = NSFetchRequest(entityName: "Recipe")
fetchRequest.sortDescriptors = [NSSortDescriptor(key: "name", ascending: true)]
fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: context, sectionNameKeyPath: nil, cacheName: nil)
fetchedResultsController.delegate = self
do {
try fetchedResultsController.performFetch()
} catch {
let nserror = error as NSError
print("Unresolved error \(nserror), \(nserror.userInfo)")
}
tableView.dataSource = self
}
func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return fetchedResultsController.sections?.count ?? 0
}
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let sectionInfo = fetchedResultsController.sections![section]
return sectionInfo.numberOfObjects
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath)
let recipe = fetchedResultsController.objectAtIndexPath(indexPath) as! Recipe
cell.textLabel?.text = recipe.name
return cell
}
}
-
实现
NSFetchedResultsControllerDelegate方法 :处理数据变化时的更新操作。
func controllerWillChangeContent(controller: NSFetchedResultsController) {
tableView.beginUpdates()
}
func controller(controller: NSFetchedResultsController, didChangeObject anObject: AnyObject, atIndexPath indexPath: NSIndexPath?, forChangeType type: NSFetchedResultsChangeType, newIndexPath: NSIndexPath?) {
switch type {
case .Insert:
tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
case .Delete:
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
case .Update:
let cell = tableView.cellForRowAtIndexPath(indexPath!)
let recipe = controller.objectAtIndexPath(indexPath!) as! Recipe
cell?.textLabel?.text = recipe.name
case .Move:
tableView.deleteRowsAtIndexPaths([indexPath!], withRowAnimation: .Fade)
tableView.insertRowsAtIndexPaths([newIndexPath!], withRowAnimation: .Fade)
}
}
func controllerDidChangeContent(controller: NSFetchedResultsController) {
tableView.endUpdates()
}
2.8 删除项目
当你需要从 Core Data 存储中删除项目时,可以使用托管对象上下文。以下是删除
Recipe
实体的步骤:
-
获取要删除的实体
:使用
NSFetchRequest或其他方式获取要删除的实体。
let helper = CoreDataHelper(modelName: "RecipeBook", datastoreFileName: "RecipeBook.sqlite")
let context = helper.managedObjectContext()
let fetchRequest = NSFetchRequest(entityName: "Recipe")
let predicate = NSPredicate(format: "name == %@", "New Recipe")
fetchRequest.predicate = predicate
do {
let results = try context.executeFetchRequest(fetchRequest)
if let recipeToDelete = results.first as? Recipe {
context.deleteObject(recipeToDelete)
}
} catch {
let nserror = error as NSError
print("Unresolved error \(nserror), \(nserror.userInfo)")
}
-
保存上下文
:调用托管对象上下文的
save方法将更改保存到数据存储中。
do {
try context.save()
print("Recipe deleted successfully.")
} catch {
let nserror = error as NSError
print("Unresolved error \(nserror), \(nserror.userInfo)")
}
2.9 搜索实体
在 Core Data 中搜索实体可以使用谓词(
NSPredicate
)来过滤查询结果。以下是搜索
Recipe
实体的示例:
-
创建
NSFetchRequest对象 :指定要检索的实体名称。
let fetchRequest = NSFetchRequest(entityName: "Recipe")
- 设置搜索谓词 :根据搜索关键字创建谓词。
let searchText = "New"
let predicate = NSPredicate(format: "name CONTAINS[c] %@", searchText)
fetchRequest.predicate = predicate
-
执行查询
:使用托管对象上下文的
executeFetchRequest方法执行查询。
let helper = CoreDataHelper(modelName: "RecipeBook", datastoreFileName: "RecipeBook.sqlite")
let context = helper.managedObjectContext()
do {
let results = try context.executeFetchRequest(fetchRequest)
for recipe in results as! [Recipe] {
print("Search result: \(recipe.name)")
}
} catch {
let nserror = error as NSError
print("Unresolved error \(nserror), \(nserror.userInfo)")
}
总结
通过以上内容,我们详细介绍了在 iOS 开发中如何进行 REST API 调用和使用 Core Data 进行数据管理。REST API 调用部分涵盖了 GET 和 POST 请求的实现,而 Core Data 使用部分则包括了创建数据模型、模型类、数据存储、托管对象上下文,以及添加、查询、删除和搜索实体等操作。这些技术可以帮助开发者构建功能强大、数据驱动的 iOS 应用。希望本文能对你的 iOS 开发工作有所帮助。
流程图
以下是 Core Data 操作的主要流程:
graph TD;
A[创建数据模型] --> B[创建模型类];
B --> C[创建数据存储];
C --> D[创建托管对象上下文];
D --> E[添加新实体];
D --> F[创建 NSFetchRequest];
F --> G[使用获取结果控制器填充 UITableView];
D --> H[删除项目];
D --> I[搜索实体];
表格
| 操作 | 步骤 |
|---|---|
| REST API GET 请求 |
1. 创建新的 iOS 单视图应用;2. 添加类文件;3. 替换
ViewController.swift
内容
|
| REST API POST 请求 |
1. 准备数据;2. 调用
RestClient
的
Post
方法
|
| 创建数据模型 | 1. 添加 Core Data 框架;2. 创建数据模型文件;3. 定义实体和属性;4. 创建另一个实体 |
| 创建模型类 | 1. 打开数据模型;2. 生成实体代码;3. 选择实体;4. 选择语言和保存位置 |
| 创建数据存储 |
1. 创建辅助类文件;2. 定义类和初始化器;3. 创建
NSManagedObjectModel
实例;4. 创建
NSPersistentStoreCoordinator
实例
|
| 创建托管对象上下文 |
在
CoreDataHelper
类中添加方法并调用
|
| 添加新实体 | 1. 获取托管对象上下文;2. 创建新实体;3. 保存上下文 |
创建
NSFetchRequest
|
1. 创建
NSFetchRequest
对象;2. 设置查询条件(可选);3. 执行查询
|
使用获取结果控制器填充
UITableView
|
1. 创建获取结果控制器;2. 实现
NSFetchedResultsControllerDelegate
方法
|
| 删除项目 | 1. 获取要删除的实体;2. 保存上下文 |
| 搜索实体 |
1. 创建
NSFetchRequest
对象;2. 设置搜索谓词;3. 执行查询
|
iOS中REST API与Core Data集成
超级会员免费看
1214

被折叠的 条评论
为什么被折叠?



