iOS
...
Data Objects
iOS 开发中利用 ParseSwift SDK 实现 CRUD 操作指南
16 分
在ios中进行crud parse对象操作 介绍 在parse上存储数据是围绕着 parse object parse object 类构建的。每个 parse object parse object 包含json兼容数据的键值对。这些数据是无模式的,这意味着您不需要提前指定每个 parse object parse object 上存在的键。您可以简单地设置您想要的任何键值对,我们的后端将存储它。 您还可以根据应用程序的需要指定数据类型,并持久化类型,例如 数字 数字 , 布尔值 布尔值 , 字符串 字符串 , 日期时间 日期时间 , 列表 列表 , 地理指针 地理指针 , 和 对象 对象 , 在保存之前将它们编码为json。parse还支持通过使用 指针 指针 和 关系 关系 来存储和查询关系数据。 在本指南中,您将学习如何通过crud示例应用程序(待办事项列表应用程序)执行基本数据操作,这将向您展示如何使用 parseswift sdk parseswift sdk 创建、读取、更新和删除来自parse服务器数据库的数据。 本教程使用在xcode 12中创建的基本应用程序和 ios 14 。 您可以随时通过我们的github仓库访问完整的项目。 ios示例仓库 目标 学习如何在 back4app 上执行基本数据库操作,以待办事项应用程序为例 先决条件 要完成此快速入门,您需要: xcode。 在 back4app 创建的应用程序。 请遵循 新 parse 应用程序教程 以了解如何在 back4app 上创建 parse 应用程序。 注意: 请遵循 安装 parse sdk(swift)教程 以创建一个连接到 back4app 的 xcode 项目。 理解我们的待办事项应用程序 为了更好地理解 parseswift sdk parseswift sdk ,您将对待办事项应用程序执行 crud 操作。应用程序数据库将具有一个简单的任务类,包含标题和描述(均为 字符串 字符串 )。您可以更新每个任务的标题和/或描述。 我们将使用的命令快速参考 一旦对象符合 parseswift parseswift 协议,它会自动实现一组方法,使您能够管理该对象并更新 back4app 数据库中的任何更改。给定对象 todolistitem todolistitem 1 struct todolistitem parseobject { 2 3 4 /// title for the todo item 5 var title string? 6 7 /// description for the todo item 8 var description string? 9 } 以下方法列在下面。 create //once created an instance of todolistitem object and set its custom properties, you can save it on your back4app database by calling any of the following methods 1 var newitem todoilisttem 2 // newitem's properties 3 4 // saves newitem on your back4app database synchronously and returns the new saved item it throws and error if something went wrong 5 let saveditem = try? newitem save() 6 7 // saves newitem on your back4app database asynchronously, and passes a result\<todolistitem, parseerror> object to the completion block to handle the save proccess 8 newitem save { result in 9 // handle the result to check the save was successfull or not 10 } 11 read //for reading objects stored on your back4app database, todolistitem now provides the query() static method which returns a query\<todolistitem> this query object can be constructed using on or more queryconstraint objects int he following way 1 let query = todolistitem query() // a query to fetch all todolistitem items on your back4app database 2 let query = todolistitem query("title" == "some title") // a query to fetch all todolistitem items with title "some title" on your back4app database 3 let query = todolistitem query(\["title" == "some title", "description" = "ok"]) // a query to fetch all todolistitem items with title = "some title" and description = "ok" 4 5 // fetchs the items synchronously or throws an error if found 6 let fetcheditems = try? query find() 7 8 // fetchs the items asynchronously and calls a completion block passing a result object containing the result of the operation 9 query find { result in 10 // handle the result 11 } update //given the objectid of an object stored on you back4app database, you can update it in the following way 1 let itemtoupdate = todolistitem(objectid "oobject id") 2 // update the properites of itemtoupdate 3 4 // save changes synchronousty 5 itemtoupdate save() 6 7 // or save changes asynchronously 8 itemtoupdate save { result in 9 // handle the result 10 } delete //the deletion process is performed by calling the method delete() on the object to be deleted 1 var itemtodelete todolistitem 2 3 // delete itemtodelete synchronously 4 try? itemtodelete delete() 5 6 // delte itemtodelete asynchronously 7 itemtodelete delete { result in 8 // handleresult 9 } 1 创建待办事项列表应用模板 随时可以通过我们的 github 仓库访问完整的项目。 ios 示例仓库 打开 xcode,找到 scenedelegate swift scenedelegate swift 文件。为了在应用程序顶部添加导航栏,我们以以下方式设置一个 uinavigationcontroller uinavigationcontroller 作为根视图控制器 1 class scenedelegate uiresponder, uiwindowscenedelegate { 2 3 var window uiwindow? 4 5 func scene( scene uiscene, willconnectto session uiscenesession, options connectionoptions uiscene connectionoptions) { 6 guard let scene = (scene as? uiwindowscene) else { return } 7 8 window = init(windowscene scene) 9 window? rootviewcontroller = uinavigationcontroller(rootviewcontroller todolistcontroller()) 10 window? makekeyandvisible() 11 12 // additional logic 13 } 14 15 16 } 导航控制器的根视图控制器类 ( todolistcontroller todolistcontroller ) 是 uitableviewcontroller uitableviewcontroller 的子类,这使得布局项目列表变得简单。 2 设置 crud 对象 您想要保存到 back4app 数据库的对象必须符合 parseobject parseobject 协议。在我们的待办事项应用中,这个对象是 todolistitem todolistitem 因此,您首先需要创建这个对象 1 import foundation 2 import parseswift 3 4 struct todolistitem parseobject { 5 // required properties from parseobject protocol 6 var objectid string? 7 var createdat date? 8 var updatedat date? 9 var acl parseacl? 10 11 /// title for the todo item 12 var title string? 13 14 /// description for the todo item 15 var description string? 16 } 这个对象在您的 back4app 数据库中定义了一个类。这个对象的任何新实例都将存储在您的数据库中,属于 todolistitem todolistitem 类 3 设置 todolistcontroller 在 todolistcontroller todolistcontroller 中,我们应该实现所有必要的配置,以便于 navigationbar navigationbar , 和 tableview tableview 属性 1 class todolistcontroller uitableviewcontroller { 2 var items \[todolistitem] = \[] 3 4 override func viewdidload() { 5 super viewdidload() 6 7 setuptableview() 8 setupnavigationbar() 9 } 10 11 private func setupnavigationbar() { 12 navigationitem title = "to do list" uppercased() 13 navigationitem rightbarbuttonitem = uibarbuttonitem(barbuttonsystemitem add, target self, action #selector(handlenewitem)) 14 } 15 16 private func setuptableview() { 17 tableview\ register(todolistitemcell self, forcellreuseidentifier todolistitemcell identifier) 18 } 19 20 override func tableview( tableview uitableview, numberofrowsinsection section int) > int { 21 items count 22 } 23 24 override func tableview( tableview uitableview, cellforrowat indexpath indexpath) > uitableviewcell { 25 let cell = tableview\ dequeuereusablecell(withidentifier todolistitemcell identifier, for indexpath) as! todolistitemcell 26 cell item = items\[indexpath row] 27 return cell 28 } 29 30 /// this method is called when the user wants to add a new item to the to do list 31 @objc private func handlenewitem() { 32 33 } 34 35 36 } 为了总结这一步,我们实现自定义表格视图单元格 todolistitemcell todolistitemcell 1 // content of todolistitemcell swift file 2 class todolistitemcell uitableviewcell { 3 class var identifier string { "\\(nsstringfromclass(self self)) identifier" } // cell's identifier 4 5 /// when set, it updates the title and detail texts of the cell 6 var item todolistitem? { 7 didset { 8 textlabel? text = item? title 9 detailtextlabel? text = item? description 10 } 11 } 12 13 override init(style uitableviewcell cellstyle, reuseidentifier string?) { 14 super init(style subtitle, reuseidentifier reuseidentifier) 15 16 accessorytype = detailbutton // this accessory button will be used to present edit options for the item 17 } 18 19 required init?(coder nscoder) { 20 super init(coder coder) 21 22 accessorytype = detailbutton // this accessory button will be used to present edit options for the item 23 } 24 } 4 crud 流程 我们在 todolistcontroller todolistcontroller 类中实现所有 crud 逻辑。前往 todolistcontroller swift todolistcontroller swift 并将以下方法添加到 todolistcontroller todolistcontroller 类 1 // mark crud flow 2 extension todolistcontroller { 3 /// creates a todolistitem and stores it on your back4app database 4 /// parameters 5 /// title the title for the to do task 6 /// description an optional description for the to to task 7 func createobject(title string, description string?) { 8 9 } 10 11 /// retrieves all the todolistitem objects from your back4app database 12 func readobjects() { 13 14 } 15 16 /// updates a todolistitem object on your back4app database 17 /// parameters 18 /// objectid the object id of the todolistitem to update 19 /// newtitle new title for the to to task 20 /// newdescription new description for the to do task 21 func updateobject(objectid string, newtitle string, newdescription string?) { 22 23 } 24 25 /// deletes a todolistitem on your back4app database 26 /// parameter item the item to be deleted on your back4app database 27 func deleteobject(item todolistitem) { 28 29 } 30 } \ 创建对象 现在我们开始实现 createobject(title\ description ) createobject(title\ description ) 方法。创建一个 todolistitem todolistitem 的实例,使用 init(title\ description ) init(title\ description ) 初始化器。为了将这个新项目保存到您的 back4app 数据库中, parseswift parseswift 协议提供了一个 save() save() 方法。此方法可以同步或异步调用,根据您的用例选择其中之一。异步实现应如下所示 1 func createobject(title string, description string?) { 2 let item = todolistitem(title title, description description) 3 4 item save { \[weak self] result in 5 guard let self = self else { return } 6 switch result { 7 case success(let saveditem) 8 self items append(saveditem) 9 dispatchqueue main async { 10 self tableview\ insertrows(at \[indexpath(row self items count 1, section 0)], with right) 11 } 12 case failure(let error) 13 dispatchqueue main async { 14 self showalert(title "error", message "failed to save item \\(error message)") 15 } 16 } 17 } 18 } 现在我们可以完成位于导航栏右侧的添加按钮的操作。前往 todolistcontroller todolistcontroller 并添加以下内容 1 class todolistcontroller uitableviewcontroller { 2 enum itemdescription int { case title = 0, description = 1 } 3 4 5 6 /// this method is called when the user wants to add a new item to the to do list 7 @objc private func handlenewitem() { 8 showeditcontroller(item nil) 9 } 10 11 /// presents an alert where the user enters a to do task for either create a new one (item parameter is nil) or edit an existing one 12 private func showeditcontroller(item todolistitem?) { 13 let controllertitle string = item == nil ? "new item" "update item" 14 15 let edititemalertcontroller = uialertcontroller(title controllertitle, message nil, preferredstyle alert) 16 17 edititemalertcontroller addtextfield { textfield in 18 textfield tag = itemdescription title rawvalue 19 textfield placeholder = "title" 20 textfield text = item? title 21 } 22 23 edititemalertcontroller addtextfield { textfield in 24 textfield tag = itemdescription description rawvalue 25 textfield placeholder = "description" 26 textfield text = item? description 27 } 28 29 let mainactiontitle string = item == nil ? "add" "update" 30 31 let mainaction uialertaction = uialertaction(title mainactiontitle, style default) { \[weak self] in 32 guard let title = edititemalertcontroller textfields? first(where { $0 tag == itemdescription title rawvalue })? text else { 33 return edititemalertcontroller dismiss(animated true, completion nil) 34 } 35 36 let description = edititemalertcontroller textfields? first(where { $0 tag == itemdescription description rawvalue })? text 37 38 edititemalertcontroller dismiss(animated true) { 39 if let objectid = item? objectid { // if the item passed as parameter is not nil, the alert will update it 40 self? updateobject(objectid objectid, newtitle title, newdescription description) 41 } else { 42 self? createobject(title title, description description) 43 } 44 } 45 } 46 47 let cancelaction = uialertaction(title "cancel", style cancel, handler nil) 48 49 edititemalertcontroller addaction(mainaction) 50 edititemalertcontroller addaction(cancelaction) 51 52 present(edititemalertcontroller, animated true, completion nil) 53 } 54 } \ 读取对象 我们转到 readobjects() readobjects() 方法。从您的 back4app 数据库中检索 todolistitem todolistitem 项目是通过一个 query\<todolistitem> query\<todolistitem> 对象来执行的。这个查询以以下方式实例化 1 func readobjects() { 2 let query = todolistitem query() 3 4 } 在本教程中,我们使用一个查询来检索您 back4app 数据库中所有类型的 todolistitem todolistitem 。如果您想检索一组特定的项目,可以提供 queryconstraint queryconstraint 元素到 todolistitem query(queryconstraint ) todolistitem query(queryconstraint ) 。例如,要获取所有 title == "some title" title == "some title" , 查询的形式为 1 let query = todolistitem query("title" == "some title") 一旦您准备好查询,我们就通过调用 query find() query find() 来检索项目。再次强调,这可以同步或异步完成。在我们的待办事项应用中,我们实现了异步 1 func readobjects() { 2 let query = todolistitem query() 3 4 query find { \[weak self] result in 5 guard let self = self else { return } 6 switch result { 7 case success(let items) 8 self items = items 9 dispatchqueue main async { 10 self tableview\ reloadsections(\[0], with top) 11 } 12 case failure(let error) 13 dispatchqueue main async { 14 self showalert(title "error", message "failed to save item \\(error message)") 15 } 16 } 17 } 18 } 完成了 readobjects() readobjects() 后,我们现在可以获取存储在您的 back4app 数据库中的所有任务,并在应用程序进入前台后立即显示它们。返回到 todolistcontroller todolistcontroller 并重写 viewdidappear() viewdidappear() 方法 1 class todolistcontroller uitableviewcontroller { 2 3 4 override func viewdidappear( animated bool) { 5 super viewdidappear(animated) 6 7 readobjects() 8 } 9 10 11 } \ 更新对象 给定一个 objectid objectid 的 todolistitem todolistitem 对象,执行更新是简单的。我们只需使用 todolistitem todolistitem 对象实例化 init(objectid ) init(objectid ) 初始化器。接下来,我们更新所需的属性并调用 save() save() 方法(来自 todolistitem todolistitem )以保存更改 1 func updateobject(objectid string, newtitle string, newdescription string?) { 2 var item = todolistitem(objectid objectid) 3 item title = newtitle 4 item description = newdescription 5 6 item save { \[weak self] result in 7 switch result { 8 case success 9 if let row = self? items firstindex(where { $0 objectid == item objectid }) { 10 self? items\[row] = item 11 dispatchqueue main async { 12 self? tableview\ reloadrows(at \[indexpath(row row, section 0)], with fade) 13 } 14 } 15 case failure(let error) 16 dispatchqueue main async { 17 self? showalert(title "error", message "failed to save item \\(error message)") 18 } 19 } 20 } 21 } \ 删除对象 在您的 back4app 数据库中删除对象与创建对象非常相似。我们首先创建一个 todolistitem todolistitem 的实例,使用我们想要删除的项目的 objectid。接下来,我们只需调用对象的 delete() delete() 方法。如果删除成功,我们更新 ui,否则我们报告错误。 1 func deleteobject(item todolistitem) { 2 item delete { \[weak self] result in 3 switch result { 4 case success 5 if let row = self? items firstindex(where { $0 objectid == item objectid }) { 6 self? items remove(at row) 7 dispatchqueue main async { 8 self? tableview\ deleterows(at \[indexpath(row row, section 0)], with left) 9 } 10 } 11 case failure(let error) 12 dispatchqueue main async { 13 self? showalert(title "error", message "failed to save item \\(error message)") 14 } 15 } 16 } 17 } 使用 deleteobject(item ) deleteobject(item ) 和 updateobject(objectid\ newtitle\ newdescription) updateobject(objectid\ newtitle\ newdescription) 完成后,我们继续添加相应的操作来调用这些操作。返回到 todolistcontroller todolistcontroller 并添加 1 // mark uitableviewdatasource delegate 2 extension todolistcontroller { 3 // when the user taps on the accessory button of a cell, we present the edit options for the to do list task 4 override func tableview( tableview uitableview, accessorybuttontappedforrowwith indexpath indexpath) { 5 guard !items isempty else { return } 6 7 showeditoptions(item items\[indexpath row]) 8 } 9 10 /// presents a sheet where the user can select an action for the to do list item 11 private func showeditoptions(item todolistitem) { 12 let alertcontroller = uialertcontroller(title title, message nil, preferredstyle actionsheet) 13 14 let editaction = uialertaction(title "edit", style default) { \[weak self] in 15 self? showeditcontroller(item item) 16 } 17 18 let deleteaction = uialertaction(title "delete", style destructive) { \[weak self] in 19 alertcontroller dismiss(animated true) { 20 self? deleteobject(item item) 21 } 22 } 23 24 let cancelaction = uialertaction(title "cancel", style cancel) { in 25 alertcontroller dismiss(animated true, completion nil) 26 } 27 28 alertcontroller addaction(editaction) 29 alertcontroller addaction(deleteaction) 30 alertcontroller addaction(cancelaction) 31 32 present(alertcontroller, animated true, completion nil) 33 } 34 } 正如我们之前指出的,每个 todolistitemcell todolistitemcell 的附加按钮通过 tableview( accessorybuttontappedforrowwith ) tableview( accessorybuttontappedforrowwith ) 委托方法触发编辑表单。 完成了! 到此为止,您已经学习了如何在 ios 上使用 parse 进行基本的 crud 操作。