Login Screen Implementation
We will look into the login screen implementation. This screen is implemented in the LoginViewController.swift
file and the LoginViewController.m
file.
The login screen is configured to open as the first screen in the navigation controller in the storyboard.
Screen components are associated with the implementation of the class via the storyboard as below:
The two text fields are associated with the
usernameField
andpasswordField
properties of theLoginViewController
class by outlets.The button actions are set to the
signupButtonPressed(_:)
andloginButtonPressed(_:)
methods.The activity indicator is associated with
activityIndicator
by an outlet to control animation while waiting (Details of the activity indicator is not covered in this tutorial).The tap gesture recognizer is connected to the
onTap(_:)
method so that the keyboard will be hidden when the screen is tapped. This method handles the process of ending edits.The manual segue,
OpenMainPage
is set so that the user program can open the data listing screen.
Creating a user
We will start with the user creation. When the "Sign Up" button is tapped, the signupButtonPressed(_:)
method is executed. The following sample code is an excerpt from this method (note that the excerpt is simplified).
The username and password are taken from the screen using the
UIKit
framework of iOS. They are set inusername
andpassword
, respectively.The username and password are passed to create a
KiiUser
instance on memory.The
performRegistration(_:)
method is called. The SDK sends a request to Kii Cloud to create the specified user.
Non-blocking API
The API that communicates with the server, like the performRegistration(_:)
method, is implemented as the non-blocking API. In iOS mobile apps, the main thread manages the user interface process. The whole mobile app will freeze if the main thread starts waiting for network communication to finish. The non-blocking API is designed to solve this problem by not waiting for the network communication to finish.
The blocking API, on another hand, will wait for the API execution to finish. The blocking API is to be used when you are creating a worker thread by yourself and executing the API from this thread. For most APIs, both blocking and non-blocking APIs are available. We present the sample code for both APIs in our programming guide.
The following sequence diagram illustrates how the non-blocking API works.
When the main thread calls the performRegistration(_:)
method, the SDK creates a worker thread internally and the method instantly returns control. The user can operate the screen while the network access process is ongoing, because the network call is made within the worker thread.
When the network call is finished and the next cycle of event processing starts, the main thread calls a closure for Swift or a block for Objective-C as the callback. Therefore, you do not need to worry about the thread synchronization in the callback.
Execution sequence
Be careful about the execution sequence.
In the above sample code, the place labeled as Step 3
is where you should write logic to be executed after the performRegistration(_:)
method is executed. The performRegistration(_:)
method is not yet complete when the place labeled as Step 2
is reached. If you write logic to be executed after the user registration in Step 2
by mistake, you will most likely encounter an error because the user registration process has just started.
When you are executing multiple APIs sequentially, you will need to write logic inside callback functions. This will make deeply nested code and make the code hard to read. To ensure code readability, you might use workarounds such as creating a worker thread by yourself and using the blocking API.
Execution result
You write logic to handle execution results inside the closure.
See the sample code in the programming guide to understand methods and classes to use in calling APIs. The below steps show how to write your code.
Once again, here is an excerpt of the user registration logic:
When handling the API execution result, you need to check if there is any exception thrown. Non-blocking API execution will trigger network communication, so there is always a chance of error, such as a network error, to be caused. This applies to all non-blocking APIs, not only to the performRegistration(_:)
method.
In Hello Kii, we handle the result as follows:
When the execution succeeded
If the variable
error
is nil, the execution was successful. The user is registered and logged in.The
OpenMainPage
segue brings the data listing screen up.The state of the logged-in user is stored in a static variable within the SDK. You can use this variable in the data listing screen.
When the execution failed
If the variable
error
is not nil, the variable stores an exception thrown in the SDK. We get the message with theshowMessage(_:error:)
method and show the message on the screen.The Kii Cloud SDK allows you to handle individual error cases by getting the error code from the
code
property of the variableerror
and the error message from thedescription
key of theuserInfo
property. TheshowMessage(_:error:)
method implemented in theUIViewController+Alert
class gets the error message from thedescription
key of theuserInfo
property and displays it on the screen.
Login
The implementation of the login process is almost the same as that of the user registration.
When the "Login" button is tapped, the loginButtonPressed(_:)
method is executed. The following sample code is an excerpt from this method.
Just like the user registration logic, we get the username and password from the screen.
Then, we pass these values to the authenticate(_:withPassword:_:)
method of the KiiUser
class and start the login process. If the username and password are valid, the mobile app will be in the logged-in state.
The authenticate(_:withPassword:_:)
method is a non-blocking API that causes network communication, so we write logic to process the result in the closure.
When the execution succeeded
If the variable
error
is nil, the login is successful. TheOpenMainPage
segue brings the data listing screen up.The state of the logged-in user is stored in a static variable within the SDK. You can use this variable in the data listing screen.
When the execution failed
If
error
is not nil, as with the case of failed user registration, an error message is displayed.
Current user
As already mentioned, once the user is logged in or successfully registered, the login state of this user will be kept in the SDK as the "current user". You can get the current user as follows:
This user is the one that you get as the argument user
of the callback in the login method.
Once you have the user, you can make various operations like accessing buckets of this user's scope.
If you restart the mobile app, you need to log in to the mobile app again.
What's next?
We will explore how the data listing screen is implemented. We will check how the data registration and retrieval are handled.
Go to Data Listing Screen Implementation.
If you want to learn more...
- See Blocking vs. Non-Blocking API for more discussion on the blocking and non-blocking API.
- See Signing up and Logging in for the details on how to implement the user registration and login.
- The term "login state" on this page refers to an access token. See Logging in and Using an Access Token to learn more.
- See Login with the Auto-Saved Credentials if you want to learn how to preserve and reuse the state when the mobile app is newly launched.