{"id":115,"date":"2015-12-11T17:08:33","date_gmt":"2015-12-11T17:08:33","guid":{"rendered":"http:\/\/kevingoedecke.com\/?p=115"},"modified":"2015-12-14T15:36:35","modified_gmt":"2015-12-14T15:36:35","slug":"tutorial-ios-user-management-app-using-swift-loopback","status":"publish","type":"post","link":"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/","title":{"rendered":"Tutorial: Example User Auth App using Swift &#038; LoopBack iOS SDK"},"content":{"rendered":"<p>In this tutorial we will create an iOS Swift app that uses the <a href=\"https:\/\/github.com\/strongloop\/loopback-sdk-ios\" target=\"_blank\">LoopBack iOS SDK<\/a> to authenticate and manage a user against the <a href=\"http:\/\/loopback.io\/\" target=\"_blank\">LoopBack<\/a> API. You&#8217;ll be able to register\/login\/logout and change your email address. This will give you a good starting point and an understanding on how to authenticate users in Swift with a LoopBack backend.<\/p>\n<h2>Key Features<\/h2>\n<ul>\n<li>User Registration<\/li>\n<li>User Authentication (Login\/Logout)<\/li>\n<li>Display User Details<\/li>\n<li>Edit User Details<\/li>\n<li>Supports iOS9 and Swift<\/li>\n<\/ul>\n<h2>Source Code<\/h2>\n<p>Available on GitHub: <a href=\"https:\/\/github.com\/kgoedecke\/loopback-swift-user-example\" target=\"_blank\">https:\/\/github.com\/kgoedecke\/loopback-swift-user-example<\/a><\/p>\n<h2>Screenshots<\/h2>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-132\" src=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/screenshot-2@2x-174x300.jpg\" alt=\"screenshot-2@2x\" width=\"255\" height=\"440\" srcset=\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/screenshot-2@2x-174x300.jpg 174w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/screenshot-2@2x-593x1024.jpg 593w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/screenshot-2@2x.jpg 750w\" sizes=\"auto, (max-width: 255px) 100vw, 255px\" \/><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-131\" src=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/screenshot-1@2x-174x300.jpg\" alt=\"screenshot-1@2x\" width=\"255\" height=\"440\" srcset=\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/screenshot-1@2x-174x300.jpg 174w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/screenshot-1@2x-593x1024.jpg 593w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/screenshot-1@2x.jpg 750w\" sizes=\"auto, (max-width: 255px) 100vw, 255px\" \/><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-140\" src=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/screenshot-3@2x-174x300.jpg\" alt=\"screenshot-3@2x\" width=\"255\" height=\"440\" srcset=\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/screenshot-3@2x-174x300.jpg 174w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/screenshot-3@2x-593x1024.jpg 593w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/screenshot-3@2x.jpg 750w\" sizes=\"auto, (max-width: 255px) 100vw, 255px\" \/> <img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-141\" src=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/screenshot-4@2x-174x300.jpg\" alt=\"screenshot-4@2x\" width=\"255\" height=\"440\" srcset=\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/screenshot-4@2x-174x300.jpg 174w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/screenshot-4@2x-593x1024.jpg 593w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/screenshot-4@2x.jpg 750w\" sizes=\"auto, (max-width: 255px) 100vw, 255px\" \/><\/p>\n<h2>Prerequisites<\/h2>\n<ul>\n<li>Deployed <a href=\"http:\/\/loopback.io\/\" target=\"_blank\">LoopBack<\/a> Backend<\/li>\n<li>Model named &#8220;Client&#8221; that is a subclass of User (separate project will follow)<\/li>\n<li>Make LoopBack SDK available in Swift (See: <a href=\"http:\/\/kevingoedecke.com\/2015\/12\/11\/using-loopback-ios-sdk-with-cocoapods-in-swift\/\" target=\"_blank\">Using LoopBack iOS SDK with Cocoapods in Swift<\/a>)<\/li>\n<\/ul>\n<h2>Getting Started<\/h2>\n<p>So you&#8217;ve got your Loopback Backend up and running and it is accessible through a public URL. In this tutorial we will use\u00a0<span class=\"lang:default decode:true crayon-inline \">http:\/\/api.backend.com:3000\/api<\/span>\u00a0 as a dummy URL for our Backend. You need to replace this with your actual Backend URL.<\/p>\n<p>Create a new XCode Project (Tabbed Application) and make the LoopBack iOS SDK available in Swift (See: <a href=\"http:\/\/kevingoedecke.com\/2015\/12\/11\/using-loopback-ios-sdk-with-cocoapods-in-swift\/\" target=\"_blank\">Using LoopBack iOS SDK with Cocoapods in Swift<\/a>).<\/p>\n<p><a href=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/start-swift-loopback-auth.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-162 size-large\" src=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/start-swift-loopback-auth-1024x623.png\" alt=\"start-swift-loopback-auth\" width=\"1024\" height=\"623\" srcset=\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/start-swift-loopback-auth-1024x623.png 1024w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/start-swift-loopback-auth-300x183.png 300w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/start-swift-loopback-auth-768x467.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<p>Delete the files <span class=\"lang:default decode:true crayon-inline\">FirstViewController.swift<\/span> and <span class=\"lang:default decode:true crayon-inline \">SecondViewController.swift<\/span> and also both View Controllers from the Storyboard. Your Storyboard should only contain one Controller now and that&#8217;s the Tab Bar Controller.<\/p>\n<p>Afterwards drag three new View Controllers onto the Storyboard and connect them to the Tab Bar Controller by holding CTRL + Clicking and dragging from the Tab Bar Controller to each of the three View Controllers. Select &#8220;view controllers&#8221; as Relationship Segue.<\/p>\n<p><a href=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/storyboard-swift-loopback-auth.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-164 size-large\" src=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/storyboard-swift-loopback-auth-1024x623.png\" alt=\"storyboard-swift-loopback-auth\" width=\"1024\" height=\"623\" srcset=\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/storyboard-swift-loopback-auth-1024x623.png 1024w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/storyboard-swift-loopback-auth-300x183.png 300w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/storyboard-swift-loopback-auth-768x467.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<h2>UI Elements<\/h2>\n<p>Now that we have all our View Controllers, we are going to add the UI elements like buttons and text input fields.<\/p>\n<p>Drag the following elements on the top View Controller:<\/p>\n<ul>\n<li>3x Text Fields (Email, Password, Repeat Password for the Registration)<\/li>\n<li>1x Button (Register Button)<\/li>\n<\/ul>\n<p>On the middle View Controller:<\/p>\n<ul>\n<li>2x Text Fields (Email, Password for the Login)<\/li>\n<li>1x Button (Login Button)<\/li>\n<\/ul>\n<p>On the bottom View Controller:<\/p>\n<ul>\n<li>7x Labels (User Account Overview, AccessToken Headline, AccessToken, User ID Headline, User ID, Email Headline, Email<\/li>\n<li>2x Buttons (Change Email Button, Logout Button)<\/li>\n<\/ul>\n<p><a href=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/start-loopback-swift-ui-elements.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-166 size-large\" src=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/start-loopback-swift-ui-elements-1024x601.png\" alt=\"start-loopback-swift-ui-elements\" width=\"1024\" height=\"601\" srcset=\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/start-loopback-swift-ui-elements-1024x601.png 1024w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/start-loopback-swift-ui-elements-300x176.png 300w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/start-loopback-swift-ui-elements-768x451.png 768w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/start-loopback-swift-ui-elements.png 2032w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<h2>View Controllers<\/h2>\n<p>Now that we have all our UI Elements in place, we going to create the View Controllers that are going to control them.<\/p>\n<p>Open &#8220;File&#8221; -&gt; &#8220;New&#8221; -&gt; &#8220;File&#8230;&#8221; and select &#8220;Cocoa Touch Class&#8221; from &#8220;iOS&#8221; -&gt; &#8220;Source&#8221;. When you press &#8220;Next&#8221; enter &#8220;RegisterViewController&#8221; as the Class name and as &#8220;Subclass of&#8221; select &#8220;UIViewController&#8221;.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-168\" src=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/register-view-controller-300x212.png\" alt=\"register-view-controller\" width=\"300\" height=\"212\" srcset=\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/register-view-controller-300x212.png 300w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/register-view-controller-768x542.png 768w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/register-view-controller-1024x722.png 1024w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/register-view-controller.png 1452w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>Create two more View Controllers by repeating those steps and name them &#8220;LoginViewController&#8221; and &#8220;AccountViewController&#8221;.<\/p>\n<p>Connect each View Controller in the Storyboard with our ViewController classes that we just created. In the Identity Inspector under &#8220;Custom Class&#8221; tell XCode to use the custom classes. Do this for each of the 3 View Controllers: RegisterViewController, LoginViewController and AccountViewController.<\/p>\n<p><a href=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/swift-loopback-set-classes.png\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-170 size-large\" src=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/swift-loopback-set-classes-1024x601.png\" alt=\"swift-loopback-set-classes\" width=\"1024\" height=\"601\" srcset=\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/swift-loopback-set-classes-1024x601.png 1024w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/swift-loopback-set-classes-300x176.png 300w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/swift-loopback-set-classes-768x451.png 768w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/swift-loopback-set-classes.png 2032w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<h2>IBOutlets and IBActions<\/h2>\n<p>In order to control the Labels and Buttons we need IBOutlets and IBActions in the appropriate View Controllers.<\/p>\n<p>Open the <span class=\"lang:default decode:true crayon-inline \">RegisterViewController.swift<\/span> and use the Assistant Editor to display both the Storyboard and the code of the View Controller.<\/p>\n<p>Select the Email Field and hold CTRL and drag the Email Field onto the Storyboard at the first line of the RegisterViewController class. A window will pop up and let you create an Outlet for the TextField.<\/p>\n<p><a href=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/swift-loopback-outlets.png\" rel=\"attachment wp-att-173\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone wp-image-173 size-large\" src=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/swift-loopback-outlets-1024x589.png\" alt=\"swift-loopback-outlets\" width=\"1024\" height=\"589\" srcset=\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/swift-loopback-outlets-1024x589.png 1024w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/swift-loopback-outlets-300x173.png 300w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/swift-loopback-outlets-768x442.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a><\/p>\n<p>Repeat those steps for the 2 password fields and name the Outlets &#8220;PasswordTextField&#8221; and &#8220;RepeatPasswordTextField&#8221;.<\/p>\n<p>Afterwards select the Register Button from the Storyboard and CTRL + Drag it to the RegisterViewController as well. This time select Action as the Connection type so XCode will create an IBAction instead of an IBOutlet.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-182\" src=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/loopback-register-button-300x193.png\" alt=\"loopback-register-button\" width=\"300\" height=\"193\" srcset=\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-register-button-300x193.png 300w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-register-button.png 504w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>Afterwards your\u00a0<span class=\"lang:default decode:true crayon-inline \">RegisterViewController.swift<\/span>\u00a0 should have the following Outlets and Actions:<\/p>\n<pre class=\"lang:default decode:true\">@IBAction func RegisterButton(sender: UIButton) {\r\n}\r\n@IBOutlet weak var RepeatPasswordTextField: UITextField!\r\n@IBOutlet weak var PasswordTextField: UITextField!\r\n@IBOutlet weak var EmailTextField: UITextField!<\/pre>\n<p>Now go ahead and create the appropriate IBOutlets and IBActions in the <span class=\"lang:default decode:true crayon-inline \">LoginViewController.swift<\/span>\u00a0:<\/p>\n<pre class=\"lang:default decode:true\">@IBAction func LoginButton(sender: UIButton) {\r\n}\r\n@IBOutlet weak var PasswordTextField: UITextField!\r\n@IBOutlet weak var EmailTextField: UITextField!<\/pre>\n<p>For the <em>AccountViewController<\/em> you only need to create Outlets for the Labels that will actually change its value and of course IBActions for the two buttons on the bottom.<\/p>\n<p><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-medium wp-image-181\" src=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/loopback-swift-label-outlets-300x296.png\" alt=\"loopback-swift-label-outlets\" width=\"300\" height=\"296\" srcset=\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-swift-label-outlets-300x296.png 300w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-swift-label-outlets.png 680w\" sizes=\"auto, (max-width: 300px) 100vw, 300px\" \/><\/p>\n<p>Afterwards you should have the following IBOutlets and IBActions in your <em>AccountViewController<\/em>:<\/p>\n<pre class=\"lang:default decode:true\">@IBAction func LogoutButton(sender: UIButton) {\r\n}\r\n@IBAction func ChangeEmailButton(sender: UIButton) {\r\n}\r\n@IBOutlet weak var EmailLabel: UILabel!\r\n@IBOutlet weak var UserIDLabel: UILabel!\r\n@IBOutlet weak var AccessTokenLabel: UILabel!<\/pre>\n<h2>LoopBack API Connection<\/h2>\n<p>Now that we have our UI Elements in plaace, let&#8217;s look into how to connect the app to our LoopBack Backend using the SDK.<\/p>\n<p>Open your <em>AppDelegate.swift<\/em> and add the following line as a local Variable in the AppDelegate, for example right after the declaration of <span class=\"lang:default decode:true crayon-inline\">var window: UIWindow?<\/span>:<\/p>\n<pre class=\"lang:default decode:true \">var adapter:LBRESTAdapter = LBRESTAdapter(URL: NSURL(string: \"http:\/\/api.backend.com:3000\/api\/\"))<\/pre>\n<p>The <em>LBRESTAdapter<\/em> gives you access to your LoopBack REST API and now that it&#8217;s in the AppDelegate you can access it pretty much from everywhere in your code.<\/p>\n<p>Before we can access our custom LoopBack &#8220;Client&#8221; model, we need to let Swift know that there actually is such a model and that it derives from the <em>LBUserModel<\/em>.<\/p>\n<p>For this we are going to create a new new Class named <em>ClientRepository<\/em>.<\/p>\n<p>Select &#8220;File&#8221; -&gt; &#8220;New&#8221; -&gt; &#8220;File&#8230;&#8221; and select Swift File and name it <span class=\"lang:default decode:true crayon-inline\">ClientRepository.swift<\/span>.<\/p>\n<p>Add the following code:<\/p>\n<pre class=\"lang:default decode:true\">class ClientRepository: LBUserRepository {\r\n    override init!(className name: String!) {\r\n        super.init(className: \"Clients\")\r\n    }\r\n    override init() {\r\n        super.init(className: \"Clients\")\r\n    }\r\n}\r\n\r\nclass Client: LBUser {\r\n    \r\n}<\/pre>\n<p>Next we will create a new Class called <span class=\"lang:default decode:true crayon-inline\">BackendUtilities.swift<\/span>, that will provide access to our Client model which is a subclass of the LoopBack User model.<\/p>\n<p>Select &#8220;File&#8221; -&gt; &#8220;New&#8221; -&gt; &#8220;File&#8230;&#8221; -&gt; &#8220;Swift File&#8221; and name it <span class=\"lang:default decode:true crayon-inline\">BackendUtilities.swift<\/span>.<\/p>\n<p>Insert the following code:<\/p>\n<pre class=\"lang:default decode:true\">class BackendUtilities  {\r\n    let appDelegate = (UIApplication.sharedApplication().delegate as! AppDelegate!)\r\n    let DEFAULTS_CURRENT_USER_ID_KEY: String = \"LBUserRepositoryCurrentUserId\"\r\n    var adapter: LBRESTAdapter\r\n    var clientRepo: ClientRepository\r\n    \r\n    static let sharedInstance = BackendUtilities()\r\n    \r\n    init() {\r\n        adapter = appDelegate.adapter as LBRESTAdapter!\r\n        clientRepo = adapter.repositoryWithClass(ClientRepository) as! ClientRepository\r\n    }\r\n}<\/pre>\n<p>The code follows the singleton pattern to enable you to make static calls and always access the same <em>LBRESTAdapter<\/em> as well as the same <em>ClientRepository<\/em>. Later you&#8217;ll be able to simply call <span class=\"lang:default decode:true crayon-inline\">BackendUtilities.sharedInstance.clientRepo<\/span> to access your <em>ClientRepository<\/em> and perform actions.<\/p>\n<p>The\u00a0<span class=\"lang:default decode:true crayon-inline\">DEFAULT_CURRENT_USER_ID_KEY<\/span> constant holds the key that the LoopBack SDK internally uses to store the User ID in the <em>NSUserDefaults<\/em>.<\/p>\n<h2>RegisterViewController<\/h2>\n<p>Now that we have everything in place, let&#8217;s can put the pieces together.<\/p>\n<p>Let&#8217;s start with the <em>RegisterViewController<\/em>.<\/p>\n<p>Open the RegisterViewController and add the following code into the RegisterButton IBAction:<\/p>\n<pre class=\"nums:true wrap:false lang:default decode:true\">if (PasswordTextField.text != RepeatPasswordTextField.text) {\r\n    let alertController = UIAlertController(title: \"Password\", message:\r\n        \"The passwords don't match\", preferredStyle: UIAlertControllerStyle.Alert)\r\n    alertController.addAction(UIAlertAction(title: \"Dismiss\", style: UIAlertActionStyle.Default,handler: nil))\r\n    self.presentViewController(alertController, animated: true, completion: nil)\r\n}\r\nelse    {\r\n    let user:Client = BackendUtilities.sharedInstance.clientRepo.createUserWithEmail(EmailTextField.text!, password: PasswordTextField.text!) as! Client\r\n\r\n    user.saveWithSuccess({ () -&gt; Void in\r\n        NSLog(\"Successfully registered new user.\")\r\n                \r\n        \/\/ Display registration confirmation\r\n        let alertController = UIAlertController(title: \"Registration\", message:\r\n            \"New user successfully registered\", preferredStyle: UIAlertControllerStyle.Alert)\r\n        alertController.addAction(UIAlertAction(title: \"Dismiss\", style: UIAlertActionStyle.Default,handler: nil))\r\n        self.presentViewController(alertController, animated: true, completion: nil)\r\n    }) { (error: NSError!) -&gt; Void in\r\n        NSLog(\"Error\")\r\n                    \r\n        \/\/ Display error alert for registration\r\n        let alertController = UIAlertController(title: \"Registration\", message:\r\n            \"Error creating new user\", preferredStyle: UIAlertControllerStyle.Alert)\r\n                    \r\n        alertController.addAction(UIAlertAction(title: \"Dismiss\", style: UIAlertActionStyle.Default,handler: nil))\r\n        self.presentViewController(alertController, animated: true, completion: nil)\r\n    }\r\n}\r\n<\/pre>\n<p><strong>Line 1-6:<\/strong> Simply checks if the passwords in the input fields match and in case they don&#8217;t, fires an <em>UIAlertController<\/em>.<\/p>\n<p><strong>Line 8:<\/strong> Get&#8217;s the <em>ClientRepository<\/em> from the <em>BackendUtilities<\/em> that we created earlier and calls the <em><a href=\"https:\/\/apidocs.strongloop.com\/loopback-sdk-ios\/api\/interface_l_b_model.html#a8078bba4859631207bd479523abafab8\">createUserWithEmail<\/a><\/em> method of it.<\/p>\n<p><strong>Line 10-18:<\/strong> Calls saveWithSuccess and handles what happens in case of the successful creation of the user. We simply going to display a UIAlertController here to inform the user that everything worked and he&#8217;s all set.<\/p>\n<p><strong>Line 19-27:<\/strong> Handles the behavior in case an error occurred and displays and error message in an <em>UIAlertController<\/em> accordingly.<\/p>\n<h2>Allowing HTTP Connections<\/h2>\n<p>The only thing missing for our app to have it&#8217;s first feature ready is that by default XCode doesn&#8217;t allow insecure HTTP connections.<\/p>\n<p>Open your Info.plist file, right click and select &#8220;Add Row&#8221;. Type in &#8220;App Transport Security Settings&#8221; as key and afterwards create a sub-entry with the key &#8220;Allow Arbitrary Loads&#8221; that has the value &#8220;YES&#8221;.<\/p>\n<p>Your plist file should look like this:<\/p>\n<p><a href=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/loopback-ios-allow-connections.png\" rel=\"attachment wp-att-188\"><img loading=\"lazy\" decoding=\"async\" class=\"alignnone size-large wp-image-188\" src=\"http:\/\/kevingoedecke.com\/wp-content\/uploads\/2015\/12\/loopback-ios-allow-connections-1024x595.png\" alt=\"loopback-ios-allow-connections\" width=\"1024\" height=\"595\" srcset=\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-ios-allow-connections-1024x595.png 1024w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-ios-allow-connections-300x174.png 300w, https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-ios-allow-connections-768x446.png 768w\" sizes=\"auto, (max-width: 1024px) 100vw, 1024px\" \/><\/a>Congratulations: If you run your app now, you should be able to register a new user with your existing LoopBack API.<\/p>\n<h2>LoginViewController<\/h2>\n<p>Open your LoginViewController and add the following code to your LoginButton IBAction:<\/p>\n<pre class=\"nums:true wrap:false lang:default decode:true\">@IBAction func LoginButton(sender: UIButton) {\r\n    BackendUtilities.sharedInstance.clientRepo.userByLoginWithEmail(EmailTextField.text, password: PasswordTextField.text, success: { (LBUser client) -&gt; Void in\r\n            NSLog(\"Successfully logged in.\");\r\n        \r\n            \/\/ Display login confirmation\r\n            let alertController = UIAlertController(title: \"Login\", message:\r\n                \"Successfully logged in\", preferredStyle: UIAlertControllerStyle.Alert)\r\n            alertController.addAction(UIAlertAction(title: \"Dismiss\", style: UIAlertActionStyle.Default,handler: nil))\r\n            self.presentViewController(alertController, animated: true, completion: nil)\r\n        }) { (error: NSError!) -&gt; Void in\r\n            NSLog(\"Error logging in.\")\r\n            \r\n            \/\/ Display error alert\r\n            let alertController = UIAlertController(title: \"Login\", message:\r\n                \"Login failed\", preferredStyle: UIAlertControllerStyle.Alert)\r\n            alertController.addAction(UIAlertAction(title: \"Dismiss\", style: UIAlertActionStyle.Default,handler: nil))\r\n            self.presentViewController(alertController, animated: true, completion: nil)\r\n    }\r\n}<\/pre>\n<p><strong>Line 2:<\/strong> Simply calls <em><span class=\"crayon-e\">userByLoginWithEmail<\/span><\/em><span class=\"crayon-e\"> on our clientRepo to login the user by the email and password provided.<\/span><\/p>\n<p><strong>Line 5-9:<\/strong> Displays the login confirmation in the case the login succeeds.<\/p>\n<p><strong>Line 13-17:<\/strong> Displays an <em>UIAlertController<\/em> error message in the case the login fails.<\/p>\n<h2>AccountViewController<\/h2>\n<p>First we are going to fill the labels in the AccountViewController with data.<\/p>\n<p>Add the following code to your AccountViewController.swift:<\/p>\n<pre class=\"lang:default decode:true \">var currentUser: Client\r\n    \r\nrequired init(coder aDecoder: NSCoder) {\r\n    currentUser = Client()\r\n    super.init(coder: aDecoder)!\r\n}<\/pre>\n<p><strong>Line 1:<\/strong> Creates a local variable named <em>currentUser<\/em> that holds the currently logged in User.<\/p>\n<p><strong>Line 3-6:<\/strong> Adds a designated initializer and actually initializes the currentUser object.<\/p>\n<p>Next add a function that assigns the currentUsers details to the IBOutlets we created earlier. We will call this function later when changes are being made.<\/p>\n<pre class=\"nums:true wrap:false lang:default decode:true\">func loadUserInformation()  {\r\n    AccessTokenLabel.text = BackendUtilities.sharedInstance.adapter.accessToken\r\n    UserIDLabel.text = currentUser._id as? String\r\n    EmailLabel.text = currentUser.email  \r\n}<\/pre>\n<p>Now override the <em>viewDidAppear<\/em> function so when the view appears we can load the users details from the SDK into the currentUser object.<\/p>\n<pre class=\"nums:true wrap:false lang:default decode:true\">override func viewDidAppear(animated: Bool) {\r\n    BackendUtilities.sharedInstance.clientRepo.findCurrentUserWithSuccess({ (client) -&gt; Void in\r\n        NSLog(\"Found user\")\r\n        if let _ = client    {\r\n            self.currentUser = client as! Client\r\n            self.loadUserInformation()\r\n        }\r\n    }) { (error: NSError!) -&gt; Void in\r\n        NSLog(\"Error fetching current user\")\r\n    }\r\n}<\/pre>\n<p><em>findCurrentUserWithSuccess<\/em> internally looks up if the User ID is set in the NSUserDefaults (key: <em>LBUserRepositoryCurrentUserId<\/em>) and if it&#8217;s set returns success. In this case we are going to set the <em>currentUser<\/em> to the the returned client and also call <em>loadUserInformation<\/em> to load the data into the UI Labels.<\/p>\n<p>All that&#8217;s left is adding functionality to the Logout button and to the Change Email button.<\/p>\n<pre class=\"nums:true wrap:false lang:default decode:true \">@IBAction func LogoutButton(sender: UIButton) {\r\n    BackendUtilities.sharedInstance.clientRepo.logoutWithSuccess({ () -&gt; Void in\r\n        \/\/ Reset local Client class object\r\n        NSLog(\"Successfully logged out\")\r\n            \r\n        \/\/ Display logout confirmation\r\n        let alertController = UIAlertController(title: \"Logout\", message:\r\n            \"Successfully logged out\", preferredStyle: UIAlertControllerStyle.Alert)\r\n        alertController.addAction(UIAlertAction(title: \"Dismiss\", style: UIAlertActionStyle.Default,handler: nil))\r\n            \r\n        self.presentViewController(alertController, animated: true, completion: nil)\r\n            \r\n        self.currentUser = Client()\r\n        self.loadUserInformation()\r\n    }) { (error: NSError!) -&gt; Void in\r\n        NSLog(\"Error logging out\")\r\n    }\r\n}<\/pre>\n<p><strong>Line 2:<\/strong> Calls the <em>logoutWithSuccess<\/em> function on the ClientRepository<\/p>\n<p><strong>Line 13:<\/strong> Sets the <em>currentUser<\/em> object to a new empty Client object<\/p>\n<p><strong>Line 14:<\/strong> Calls <em>loadUserInformation<\/em> to update the Labels through its IBOutlets<\/p>\n<pre class=\"nums:true wrap:false lang:default decode:true\">@IBAction func ChangeEmailButton(sender: UIButton) {\r\n    let alertController = UIAlertController(title: \"Email?\", message: \"Please enter your email\", preferredStyle: .Alert)\r\n    let cancelAction = UIAlertAction(title: \"Cancel\", style: .Cancel) { (_) in }\r\n        alertController.addTextFieldWithConfigurationHandler { (textField) in\r\n            textField.placeholder = title\r\n        }\r\n    let saveAction = UIAlertAction(title: \"Confirm\", style: .Default) { (_) in\r\n        if let field = alertController.textFields![0] as? UITextField {\r\n            \/\/ store your data\r\n            self.currentUser.email = field.text\r\n            self.currentUser.saveWithSuccess({ () -&gt; Void in\r\n                NSLog(\"sucessfully saved\")\r\n                }, failure: { (error: NSError!) -&gt; Void in\r\n                    NSLog(\"error saving\")\r\n                })\r\n            self.loadUserInformation()\r\n        }\r\n    }\r\n    alertController.addAction(cancelAction)\r\n    alertController.addAction(saveAction)\r\n    self.presentViewController(alertController, animated: true, completion: nil)\r\n}<\/pre>\n<p><strong>Line 10:<\/strong> Set the email of the currentUser object to the one that was entered in the UIAlertController<\/p>\n<p><strong>Line 11:<\/strong> Call saveWithSuccess on the currentUser object to execute the saving of the email address<\/p>\n<p>After adding those two Actions you should be able to logout as well as change the email address of the currently logged in user.<\/p>\n<h2>Conclusion<\/h2>\n<p>That&#8217;s it! \ud83d\ude09 You now have an app that provides basic user management features.<\/p>\n<p>This tutorial should give you a good starting point to develop your own app based on a LoopBack Backend. You should be able to easily extend it and take it further from here.<\/p>\n<p>You can find the complete source code of this tutorial on <a href=\"https:\/\/github.com\/kgoedecke\/loopback-swift-user-example\" target=\"_blank\">GitHub<\/a>.<\/p>\n","protected":false},"excerpt":{"rendered":"<p>In this tutorial we will create an iOS Swift app that uses the LoopBack iOS SDK to authenticate and manage a user against the LoopBack API. You&#8217;ll be able to register\/login\/logout and change your email address. This will give you a good starting point and an understanding on how to authenticate users in Swift with [&hellip;]<\/p>\n","protected":false},"author":1,"featured_media":120,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_exactmetrics_skip_tracking":false,"_exactmetrics_sitenote_active":false,"_exactmetrics_sitenote_note":"","_exactmetrics_sitenote_category":0,"_jetpack_memberships_contains_paid_content":false,"footnotes":""},"categories":[15],"tags":[16,21,17,19,22],"class_list":["post-115","post","type-post","status-publish","format-standard","has-post-thumbnail","hentry","category-programming","tag-loopback","tag-loopback-sdk","tag-strongloop","tag-swift","tag-user-auth"],"yoast_head":"<!-- This site is optimized with the Yoast SEO plugin v24.8.1 - https:\/\/yoast.com\/wordpress\/plugins\/seo\/ -->\n<title>Tutorial: Example User Auth App using Swift &amp; LoopBack iOS SDK - Kevin Goedecke<\/title>\n<meta name=\"robots\" content=\"index, follow, max-snippet:-1, max-image-preview:large, max-video-preview:-1\" \/>\n<link rel=\"canonical\" href=\"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/\" \/>\n<meta property=\"og:locale\" content=\"en_US\" \/>\n<meta property=\"og:type\" content=\"article\" \/>\n<meta property=\"og:title\" content=\"Tutorial: Example User Auth App using Swift &amp; LoopBack iOS SDK - Kevin Goedecke\" \/>\n<meta property=\"og:description\" content=\"In this tutorial we will create an iOS Swift app that uses the LoopBack iOS SDK to authenticate and manage a user against the LoopBack API. You&#8217;ll be able to register\/login\/logout and change your email address. This will give you a good starting point and an understanding on how to authenticate users in Swift with [&hellip;]\" \/>\n<meta property=\"og:url\" content=\"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/\" \/>\n<meta property=\"og:site_name\" content=\"Kevin Goedecke\" \/>\n<meta property=\"article:published_time\" content=\"2015-12-11T17:08:33+00:00\" \/>\n<meta property=\"article:modified_time\" content=\"2015-12-14T15:36:35+00:00\" \/>\n<meta property=\"og:image\" content=\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-ios-auth-app@2x.jpg\" \/>\n\t<meta property=\"og:image:width\" content=\"1800\" \/>\n\t<meta property=\"og:image:height\" content=\"900\" \/>\n\t<meta property=\"og:image:type\" content=\"image\/jpeg\" \/>\n<meta name=\"author\" content=\"Kevin Goedecke\" \/>\n<meta name=\"twitter:card\" content=\"summary_large_image\" \/>\n<meta name=\"twitter:label1\" content=\"Written by\" \/>\n\t<meta name=\"twitter:data1\" content=\"Kevin Goedecke\" \/>\n\t<meta name=\"twitter:label2\" content=\"Est. reading time\" \/>\n\t<meta name=\"twitter:data2\" content=\"10 minutes\" \/>\n<script type=\"application\/ld+json\" class=\"yoast-schema-graph\">{\"@context\":\"https:\/\/schema.org\",\"@graph\":[{\"@type\":\"WebPage\",\"@id\":\"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/\",\"url\":\"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/\",\"name\":\"Tutorial: Example User Auth App using Swift & LoopBack iOS SDK - Kevin Goedecke\",\"isPartOf\":{\"@id\":\"https:\/\/kevingoedecke.com\/#website\"},\"primaryImageOfPage\":{\"@id\":\"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/#primaryimage\"},\"image\":{\"@id\":\"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/#primaryimage\"},\"thumbnailUrl\":\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-ios-auth-app@2x.jpg\",\"datePublished\":\"2015-12-11T17:08:33+00:00\",\"dateModified\":\"2015-12-14T15:36:35+00:00\",\"author\":{\"@id\":\"https:\/\/kevingoedecke.com\/#\/schema\/person\/4b156cd6453e1af4bab9076b0a663871\"},\"breadcrumb\":{\"@id\":\"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/#breadcrumb\"},\"inLanguage\":\"en-US\",\"potentialAction\":[{\"@type\":\"ReadAction\",\"target\":[\"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/\"]}]},{\"@type\":\"ImageObject\",\"inLanguage\":\"en-US\",\"@id\":\"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/#primaryimage\",\"url\":\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-ios-auth-app@2x.jpg\",\"contentUrl\":\"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-ios-auth-app@2x.jpg\",\"width\":1800,\"height\":900},{\"@type\":\"BreadcrumbList\",\"@id\":\"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/#breadcrumb\",\"itemListElement\":[{\"@type\":\"ListItem\",\"position\":1,\"name\":\"Home\",\"item\":\"https:\/\/kevingoedecke.com\/\"},{\"@type\":\"ListItem\",\"position\":2,\"name\":\"Tutorial: Example User Auth App using Swift &#038; LoopBack iOS SDK\"}]},{\"@type\":\"WebSite\",\"@id\":\"https:\/\/kevingoedecke.com\/#website\",\"url\":\"https:\/\/kevingoedecke.com\/\",\"name\":\"Kevin Goedecke\",\"description\":\"Founder. Entrepreneur.\",\"potentialAction\":[{\"@type\":\"SearchAction\",\"target\":{\"@type\":\"EntryPoint\",\"urlTemplate\":\"https:\/\/kevingoedecke.com\/?s={search_term_string}\"},\"query-input\":{\"@type\":\"PropertyValueSpecification\",\"valueRequired\":true,\"valueName\":\"search_term_string\"}}],\"inLanguage\":\"en-US\"},{\"@type\":\"Person\",\"@id\":\"https:\/\/kevingoedecke.com\/#\/schema\/person\/4b156cd6453e1af4bab9076b0a663871\",\"name\":\"Kevin Goedecke\",\"url\":\"https:\/\/kevingoedecke.com\/blog\/author\/kgoedecke\/\"}]}<\/script>\n<!-- \/ Yoast SEO plugin. -->","yoast_head_json":{"title":"Tutorial: Example User Auth App using Swift & LoopBack iOS SDK - Kevin Goedecke","robots":{"index":"index","follow":"follow","max-snippet":"max-snippet:-1","max-image-preview":"max-image-preview:large","max-video-preview":"max-video-preview:-1"},"canonical":"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/","og_locale":"en_US","og_type":"article","og_title":"Tutorial: Example User Auth App using Swift & LoopBack iOS SDK - Kevin Goedecke","og_description":"In this tutorial we will create an iOS Swift app that uses the LoopBack iOS SDK to authenticate and manage a user against the LoopBack API. You&#8217;ll be able to register\/login\/logout and change your email address. This will give you a good starting point and an understanding on how to authenticate users in Swift with [&hellip;]","og_url":"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/","og_site_name":"Kevin Goedecke","article_published_time":"2015-12-11T17:08:33+00:00","article_modified_time":"2015-12-14T15:36:35+00:00","og_image":[{"width":1800,"height":900,"url":"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-ios-auth-app@2x.jpg","type":"image\/jpeg"}],"author":"Kevin Goedecke","twitter_card":"summary_large_image","twitter_misc":{"Written by":"Kevin Goedecke","Est. reading time":"10 minutes"},"schema":{"@context":"https:\/\/schema.org","@graph":[{"@type":"WebPage","@id":"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/","url":"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/","name":"Tutorial: Example User Auth App using Swift & LoopBack iOS SDK - Kevin Goedecke","isPartOf":{"@id":"https:\/\/kevingoedecke.com\/#website"},"primaryImageOfPage":{"@id":"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/#primaryimage"},"image":{"@id":"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/#primaryimage"},"thumbnailUrl":"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-ios-auth-app@2x.jpg","datePublished":"2015-12-11T17:08:33+00:00","dateModified":"2015-12-14T15:36:35+00:00","author":{"@id":"https:\/\/kevingoedecke.com\/#\/schema\/person\/4b156cd6453e1af4bab9076b0a663871"},"breadcrumb":{"@id":"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/#breadcrumb"},"inLanguage":"en-US","potentialAction":[{"@type":"ReadAction","target":["https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/"]}]},{"@type":"ImageObject","inLanguage":"en-US","@id":"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/#primaryimage","url":"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-ios-auth-app@2x.jpg","contentUrl":"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-ios-auth-app@2x.jpg","width":1800,"height":900},{"@type":"BreadcrumbList","@id":"https:\/\/kevingoedecke.com\/blog\/2015\/12\/11\/tutorial-ios-user-management-app-using-swift-loopback\/#breadcrumb","itemListElement":[{"@type":"ListItem","position":1,"name":"Home","item":"https:\/\/kevingoedecke.com\/"},{"@type":"ListItem","position":2,"name":"Tutorial: Example User Auth App using Swift &#038; LoopBack iOS SDK"}]},{"@type":"WebSite","@id":"https:\/\/kevingoedecke.com\/#website","url":"https:\/\/kevingoedecke.com\/","name":"Kevin Goedecke","description":"Founder. Entrepreneur.","potentialAction":[{"@type":"SearchAction","target":{"@type":"EntryPoint","urlTemplate":"https:\/\/kevingoedecke.com\/?s={search_term_string}"},"query-input":{"@type":"PropertyValueSpecification","valueRequired":true,"valueName":"search_term_string"}}],"inLanguage":"en-US"},{"@type":"Person","@id":"https:\/\/kevingoedecke.com\/#\/schema\/person\/4b156cd6453e1af4bab9076b0a663871","name":"Kevin Goedecke","url":"https:\/\/kevingoedecke.com\/blog\/author\/kgoedecke\/"}]}},"jetpack_featured_media_url":"https:\/\/kevingoedecke.com\/blog\/wp-content\/uploads\/2015\/12\/loopback-ios-auth-app@2x.jpg","jetpack_sharing_enabled":true,"_links":{"self":[{"href":"https:\/\/kevingoedecke.com\/blog\/wp-json\/wp\/v2\/posts\/115","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/kevingoedecke.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/kevingoedecke.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/kevingoedecke.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/kevingoedecke.com\/blog\/wp-json\/wp\/v2\/comments?post=115"}],"version-history":[{"count":64,"href":"https:\/\/kevingoedecke.com\/blog\/wp-json\/wp\/v2\/posts\/115\/revisions"}],"predecessor-version":[{"id":207,"href":"https:\/\/kevingoedecke.com\/blog\/wp-json\/wp\/v2\/posts\/115\/revisions\/207"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/kevingoedecke.com\/blog\/wp-json\/wp\/v2\/media\/120"}],"wp:attachment":[{"href":"https:\/\/kevingoedecke.com\/blog\/wp-json\/wp\/v2\/media?parent=115"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/kevingoedecke.com\/blog\/wp-json\/wp\/v2\/categories?post=115"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/kevingoedecke.com\/blog\/wp-json\/wp\/v2\/tags?post=115"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}