CRUD con ParseSwift SDK en iOS: Guía Completa para Desarrolladores
17 min
crud parse objetos en ios introducción almacenar datos en parse se basa en la \<font color="#2166ae">parse object\</font> clase cada \<font color="#2166ae">parse object\</font> contiene pares clave valor de datos compatibles con json estos datos no tienen esquema, lo que significa que no necesitas especificar de antemano qué claves existen en cada \<font color="#2166ae">parse object\</font> simplemente puedes establecer los pares clave valor que desees, y nuestro backend los almacenará también puedes especificar los tipos de datos según las necesidades de tu aplicación y persistir tipos como \<font color="#2166ae">número\</font> , \<font color="#2166ae">booleano\</font> , \<font color="#2166ae">cadena\</font> , \<font color="#2166ae">datetime\</font> , \<font color="#2166ae">lista\</font> , \<font color="#2166ae">geopointers\</font> , y \<font color="#2166ae">objeto\</font> , codificándolos a json antes de guardarlos parse también admite almacenar y consultar datos relacionales utilizando los tipos \<font color="#2166ae">pointers\</font> y \<font color="#2166ae">relaciones\</font> en esta guía, aprenderás a realizar operaciones básicas de datos a través de una aplicación de ejemplo crud (aplicación de lista de tareas), que te mostrará cómo crear, leer, actualizar y eliminar datos de tu base de datos del servidor parse utilizando el \<font color="#2166ae">parseswift sdk\</font> este tutorial utiliza una aplicación básica creada en xcode 12 y ios 14 en cualquier momento, puedes acceder al proyecto completo a través de nuestros repositorios de github repositorio de ejemplo de ios https //github com/templates back4app/ios crud to do list objetivo para aprender a realizar operaciones básicas de base de datos en back4app utilizando una aplicación de lista de tareas como ejemplo requisitos previos para completar este inicio rápido, necesitas xcode una aplicación creada en back4app sigue el tutorial de nueva aplicación parse https //www back4app com/docs/get started/new parse app para aprender a crear una aplicación parse en back4app nota sigue el tutorial de instalación del sdk de parse (swift) https //www back4app com/docs/ios/parse swift sdk para crear un proyecto de xcode conectado a back4app entendiendo nuestra aplicación de lista de tareas para entender mejor el \<font color="#2166ae">sdk de parseswift\</font> realizarás operaciones crud en una aplicación de lista de tareas la base de datos de la aplicación tendrá una clase de tarea simple con un título y una descripción (ambos \<font color="#2166ae">cadenas\</font> ) puedes actualizar el título y/o la descripción de cada tarea referencia rápida de los comandos que vamos a usar una vez que un objeto cumpla con el \<font color="#2166ae">parseswift\</font> protocolo, implementa automáticamente un conjunto de métodos que te permitirán gestionar el objeto y actualizar cualquier cambio en tu base de datos de back4app dado el objeto \<font color="#2166ae">todolistitem\</font> 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 } estos métodos se enumeran a continuación 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 crear plantilla de aplicación de lista de tareas en cualquier momento, puedes acceder al proyecto completo a través de nuestros repositorios de github repositorio de ejemplo de ios https //github com/templates back4app/ios crud to do list ve a xcode y encuentra el \<font color="#2166ae">scenedelegate swift\</font> archivo para agregar una barra de navegación en la parte superior de la aplicación, configuramos un \<font color="#2166ae">uinavigationcontroller\</font> como el controlador de vista raíz de la siguiente manera 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 } la clase del controlador de vista raíz ( \<font color="#2166ae">todolistcontroller\</font> ) para el controlador de navegación es una subclase de \<font color="#2166ae">uitableviewcontroller\</font> , esto facilita el diseño de una lista de elementos 2 configurar el objeto crud los objetos que deseas guardar en tu base de datos de back4app deben conformarse al \<font color="#2166ae">parseobject\</font> protocolo en nuestra aplicación de lista de tareas, este objeto es \<font color="#2166ae">todolistitem\</font> por lo tanto, primero necesitas crear este objeto 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 } este objeto define una clase en tu base de datos de back4app cualquier nueva instancia de este objeto se almacena en tu base de datos bajo la \<font color="#2166ae">todolistitem\</font> clase 3 configurar todolistcontroller en \<font color="#2166ae">todolistcontroller\</font> deberíamos implementar toda la configuración necesaria para la \<font color="#2166ae">navigationbar\</font> , y las propiedades de \<font color="#2166ae">tableview\</font> 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 } para concluir este paso, implementamos la celda de vista de tabla personalizada \<font color="#2166ae">todolistitemcell\</font> 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 flujo crud implementamos toda la lógica crud en la \<font color="#2166ae">todolistcontroller\</font> clase ve a \<font color="#2166ae">todolistcontroller swift\</font> y agrega los siguientes métodos a la \<font color="#2166ae">todolistcontroller\</font> clase 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 } \ crear objeto ahora comenzamos a implementar el \<font color="#2166ae">createobject(title\ description )\</font> método crea una instancia de \<font color="#2166ae">todolistitem\</font> usando el \<font color="#2166ae">init(title\ description )\</font> inicializador para guardar este nuevo elemento en tu base de datos de back4app, el \<font color="#2166ae">parseswift\</font> protocolo proporciona un \<font color="#2166ae">save()\</font> método este método se puede llamar de forma sincrónica o asincrónica, elige uno de ellos según tu caso de uso una implementación asincrónica debería verse así 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 } ahora podemos completar la acción para el botón de agregar ubicado en el lado derecho de la barra de navegación ve a \<font color="#2166ae">todolistcontroller\</font> y agrega lo siguiente 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 } \ leer objeto nos movemos al \<font color="#2166ae">readobjects()\</font> método recuperar \<font color="#2166ae">todolistitem\</font> elementos de tu base de datos de back4app se realiza a través de un \<font color="#2166ae">query\<todolistitem\>\</font> objeto esta consulta se instancia de la siguiente manera 1 func readobjects() { 2 let query = todolistitem query() 3 4 } en este tutorial usamos una consulta que recuperará todos los elementos del tipo \<font color="#2166ae">todolistitem\</font> de tu base de datos de back4app en caso de que quieras recuperar un conjunto de elementos específicos, puedes proporcionar \<font color="#2166ae">queryconstraint\</font> elementos a \<font color="#2166ae">todolistitem query(queryconstraint )\</font> por ejemplo, para obtener todos los elementos donde \<font color="#2166ae">title == "some title"\</font> , la consulta toma la forma 1 let query = todolistitem query("title" == "some title") una vez que tengas la consulta lista, procedemos a recuperar los elementos llamando \<font color="#2166ae">query find()\</font> nuevamente, esto se puede hacer de manera sincrónica o asincrónica en nuestra aplicación de lista de tareas, lo implementamos de manera asincrónica 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 } con \<font color="#2166ae">readobjects()\</font> completado, ahora podemos recuperar todas las tareas almacenadas en tu base de datos de back4app y mostrarlas justo después de que la aplicación entre en primer plano regresa a \<font color="#2166ae">todolistcontroller\</font> y sobrescribe el \<font color="#2166ae">viewdidappear()\</font> método 1 class todolistcontroller uitableviewcontroller { 2 3 4 override func viewdidappear( animated bool) { 5 super viewdidappear(animated) 6 7 readobjects() 8 } 9 10 11 } \ actualizar objeto dado el \<font color="#2166ae">objectid\</font> de un \<font color="#2166ae">todolistitem\</font> , es sencillo realizar una actualización simplemente instanciamos un \<font color="#2166ae">todolistitem\</font> utilizando el \<font color="#2166ae">init(objectid )\</font> inicializador a continuación, actualizamos las propiedades que necesitamos y llamamos al \<font color="#2166ae">save()\</font> método (de \<font color="#2166ae">todolistitem\</font> ) para guardar los cambios 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 } \ eliminar objeto eliminar objetos en tu base de datos de back4app es muy similar a crear objetos comenzamos creando una instancia de \<font color="#2166ae">todolistitem\</font> con el objectid del elemento que queremos eliminar a continuación, simplemente llamamos (sincrónicamente o asincrónicamente) al \<font color="#2166ae">delete()\</font> método del objeto si la eliminación fue exitosa, actualizamos la interfaz de usuario, de lo contrario, informamos el error 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 } con \<font color="#2166ae">deleteobject(item )\</font> y \<font color="#2166ae">updateobject(objectid\ newtitle\ newdescription)\</font> completados, procedemos a agregar las acciones correspondientes para llamar a estas operaciones regresa a \<font color="#2166ae">todolistcontroller\</font> y agrega 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 } como mencionamos anteriormente, el botón accesorio en cada \<font color="#2166ae">todolistitemcell\</font> activa una hoja de edición a través del \<font color="#2166ae">tableview( accessorybuttontappedforrowwith )\</font> método delegado ¡está hecho! en este punto, has aprendido cómo realizar las operaciones crud básicas con parse en ios