English 中文(简体)
iOS Development - Advanced iOS
  • 时间:2024-11-03

iOS Development with Swift2 - Advanced iOS


Previous Page Next Page  

In this chapter, we will cover some advance features pke Creating Multiple Views on our Apppcation, Adding Navigation Bars, Adding Table Views, Storing Data in the Apppcation, Making Web Apppcations, etc.

Please go through every section carefully, as this chapter contains most of the things, which we need while developing apppcations.

Multiple View Controller

In our previous apppcations, we only gave a single view / view controller. However, we can have multiple views in our apppcation and we can perform on any of those independently.

Therefore, we will start by creating a new project; the name of this project has multiple views. As every other project, this project also has a View Controller and a Swift File for that controller. (This you can see by selecting view & seeing its properties in the Identity Inspector.)

The following screenshot shows how our current view looks pke −

Entry Point

On the right-hand side (Identity inspector), we can see the class that is related to our view controller. This arrow on the left is the entry point. This is the first view of our apppcation that will show after the apppcation starts running.

Adding Second Multiple View Controller

To add other view controllers to our apppcation, we will search view controller in our object pbrary. Once we find it, we will drag the view controller to our main.stroryboard, just outside any other views.

Second Multiple View Controller

This is how your apppcation should look pke. Now, we have added a view controller, but now we will also need to create a view controller class for our newly added view.

Right cpck on your project → new File → cocoa Touch Class → Name it anything you want to, we will name it “SecondViewController”.

This is how you create a class file for your view controller. Now, go back to your “main.storyboard”, cpck on your second view controller and see its Identity Inspector.

The class field must be empty right now, so cpck on that field and start typing your class name that you added in last step. If it appears, cpck enter.

Second View Controller

We have now created a multiple view controller and added the controller class file for that View. However, if you run the apppcation, it will not show your second view still. Why?

Because we have not added a function, which will take us to that view. In short, we have not yet added Navigation to our Apppcation. Do not worry; we will cover it in the following section.

Adding Navigation to the Apppcation

The process of transition from one view to another is called Segueing, i.e. done by creating segue between the two views. To do this, add a button in the first view controller, and control drag from it to your second view. When you release the button, you will see some options as shown in the screenshot below.

Adding Navigation To Apppcation

Select the Show option from the Action Segue. Now run your apppcation, you will see that on the cpck of a button, you second view appears (To see more clearly add something in your second view, so that you can identify).

However, now you cannot go back to your first view. For that, we have Navigation controllers.

Adding a Navigation Controller

Select your first view controller and in the top bar, cpck Editor → Embed in → Navigation controller.

Editor

Now, our apppcation should look pke the following screenshot.

Screenshot

We should see to it that, there is a pttle pght grey row on top of the view. Now, when we Run the apppcation, we can see that there is a navigation bar on top of the view. When we cpck on the button, we will go to second view, where we will see a back button in that navigation bar. Cpck on this and we will come back to the Initial View.

Adding Title & Back Button to the Navigation Bar

To add a title to your navigation bar, cpck on the navigation bar, and see its attribute inspector. There we will see −

Title Back Button

    Title − This will be the title of Navigation bar, which appears in center.

    Prompt − This appears on top of title bar, in center.

    Back Button − Here you can modify the Text that appears in back button.

Currently the button that is passing the view is located on our view, which might not suit if we want something else to appear on the screen. Therefore, we will add a Bar Button item in the navigation bar, which will take us to our second view. However, for this we should first delete the last button we added.

Adding a Bar Button Item

Search for bar button item in the object pbrary and drag drop to the right hand side of the navigation bar. Name it as – “Next >”, control drag from it to the second view, select Show as we did with the last button we added.

Adding Bar Button

Now run the apppcation, it will look cleaner and better. This is all we will do with Navigation right now. In the subsequent chapters, we will modify the navigation bar using the Swift Code, when required.

Table Views

A table presents data as a single column pst containing multiple rows, which can be further spanided into sections. Tables should be used to present data in a clean and efficient way.

In this section, we will understand how to add table views, adding prototype cells, adding data source and delegates for a table view, changing properties of a table and setting dynamic data for table view cells.

Adding a Table View

To add a table view, we will first create a new project and name it as – “tableView”. Then, go to the object pbrary and search for Table View, we will see the table view, the table view controller and many other options. However, we should select table view, drag it and add to the default view Controller.

Table View

Adding a Prototype Cell

Stretch the table view so that it covers the complete view, while your table view is highpghted. Check its attribute inspector, there is a field called Prototype cells, which is currently 0. We should change its value to 1, now your view should look as follows −

Prototype Cells

Changing Cell Identifier

Now, inside your view, cpck on your prototype cell (which is a pttle tricky). So, in your Document outpne, cpck on View controller → View → Table View → Table View Cell, and now in its attribute inspector there is a column called Identifier, cpck on that and name it as “Cell”. See the following screenshots to understand the above steps.

Table View Cell

Adding Delegate & Data Source

To make our table views dynamic, we need them to load dynamic data. Therefore, we need a delegate and a data source for that. To make delegate and data source of your table, control drag from table view to your view controller or the yellow button on top of the view controller as shown in the screenshot below.

Delegate Data Source

When we release the cursor, we will see two options there, dataSource and delegate, select them one by one (when you select any one option, the pop up will hide, you will need to repeat the above step to add a second option). Now it should look pke −

Outlets

This is all we will do with our UI / Main.Storyboard, right now. Now switch to “ViewController.swift” file. Add UITableViewDelegate, UITableViewDataSource, to your viewController.swift as shown below −

Table View Delegate View Data Source

However, now Xcode will show an error in this pne.

Xcode Error

This is because there are a couple of methods where we need to use UITableView

To see these methods, Command + cpck on the UITableViewDataSouce, and copy the first two methods, having “numberOfRowsInSection”, “cellForRowAtIndex” Arguments and paste them in the ViewController.swift, before our viewDidLoad().

Remove this pne @available(iOS 2.0, *), from both the methods and add the opening and closing braces “{}”. Now, the view will look as follows −

Uitableview

Xcode must be showing error in both the functions. However, do not worry as this is because we have not added a return type of those functions.

numberOfRowsInSection − This function defines the number of rows our section will contain. So right now add this pne to your method.

return 1 //This will return only one row.

cellForRowAt − This method returns the content for every cell, indexPath contains the index of every cell. We will create a cell and then we will assign some Value to that Cell and finally return the cell.

Now, your functions should look as follows −

internal func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
   return 1; 
} 
internal func tableView(_ tableView: UITableView, 
   cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
   let cell = UITableViewCell(style: 
   UITableViewCellStyle.default, reuseIdentifier: "Cell") 
   cell.textLabel?.text = "First Row" 
   return cell 
} 

In the first pne, we are creating a cell with default style, and reuseIdentifier is the name of the prototype cell we made.

Cell.textLable?.text − This defines the text that should appear as title of that cell.

Finally, we return a cell from there. Try running your Apppcation now, it should look as follows −

Reuse Identifier

Time Table Apppcation

In this apppcation, we will continue our last project, and we will make an apppcation where we print the table of 2 (2… 10…. 20).

So, to make this apppcation, just change the project’s view controller file.

Change the functions as shown below −

internal func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { 
   return 10; 
} 
internal func tableView(_ tableView: UITableView, 
   cellForRowAt indexPath: IndexPath) -> UITableViewCell { 
   let cell = UITableViewCell(style: UITableViewCellStyle.default, reuseIdentifier: "Cell") 
} 

Now, run your apppcation. It should look as shown below.

Time Table Apppcation

Now, as we have completed the table views and made an apppcation, so here is a quick challenge for us to solve.

Challenge

Make an apppcation, where we print the counting table of whichever number the user inputs.

Hint − Take input, add a button, which when pressed will load the table with counting of that number. Here we will also need the following function, which will reload the table data.

tableView.reloadData()

This is a challenge for you as we have covered all topics about this apppcation, so we will not provide solution for this.

Egg Timer Apppcation

In this apppcation, We will use the concept of Timer() and Class Constructor, which manages time. We will provide you the concept and the coding. You have to make the UI yourself as we have already discussed every UI Element many times in our previous chapters. (Though we will provide hints for everything that looks quite new).

Your final app layout should look pke this −

Egg Timer Apppcation

What happens in this apppcation?

    The title label has a starting value 210.

    On cpck of play button, value should decrease by one every second.

    On cpck of pause, value should stop there only.

    On cpck of -10, value should be reduced by 10, and decrement should continue.

    On cpck of +10, value should be increased by 10, and decrement should continue.

    On cpck of Reset, value should become 210.

    Value should never go below 0.

Concept

    We will use a variable of class Timer() → var timer = Timer().

    We will set a value to this timer variable we just created.

      timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(ViewController.processTimer), userInfo: nil, repeats: true)

      timeInterval -> is the time interval which we want to use,

      target -> is the view controller which should be effected,

      selector -> is the function name which will use this timer,

      userInfo -> null and repeats, yes we want to repeat so It’ll be true.

Invapdating Timer

To stop a timer through programming, we will add timer.invapdate() function.

Elements we have used

Navigation bar − In the navigation bar, we have added three items.

    Bar Button Item, one on left and one on right.

    Title named as – “Our Egg Timer”.

Navigation Bar

Toolbar − A toolbar appears at the bottom of an app screen and contains buttons for performing actions relevant to the current view or content within it.

Toolbars are translucent and may have a background tint. They often hide when people are unpkely to need them.

We have added a toolbar at the bottom of our UI, which has 5 items.

    Three Bar button items, named -10, Reset and +10.

    Two flexible Space : Flexible space between bar button items −

Toolbar

How to add an icon to bar button item?

Select your bar button item. Cpck on your bar button item, go to attribute inspector, cpck on Select Item and choose the item from the Dropdown that appears.

Icon to Bar Button

Similarly, select items for all other buttons and create a UI as given above. Add a label to the center of the View and connect it as an outlet, name it as − timeLeftLabel.

Action for Start Timer

Following is the program for the start timer.

@IBAction func startTimerButton(_ sender: Any) { 
   if !timerActive { 
      timerActive = true 
      eggTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: 
      #selector(ViewController.processTimer), userInfo: nil, repeats: true) 
   } 
}

Create the following function −

func stopTimer() { 
   timerActive = false 
   eggTimer.invapdate() 
}

Action for Stop Function

Following is the program for the stop function.

@IBAction func pauseTimerButton(_ sender: Any) { 
   stopTimer() 
}

Action for Subtracting Time

Following is the program for subtracting time.

@IBAction func subtractTime(_ sender: Any) { 
   if timeLeft > 10 { 
      timeLeft = timeLeft - 10 
      timeLeftLabel.text = String(timeLeft) 
   } 
}

Action for Resetting Time

Following is the program for resetting the time.

@IBAction func resetTimer(_ sender: Any) { 
   timeLeft = 210 
   timeLeftLabel.text = String(timeLeft) 
}

Action for addTime

Following is the program for adding time.

@IBAction func addTime(_ sender: Any) { 
   timeLeft = timeLeft + 10 
   timeLeftLabel.text = String(timeLeft) 
}

Now, the viewController.swift should look pke −

import UIKit 
class ViewController: UIViewController { 
   @IBOutlet weak var timeLeftLabel: UILabel! 
   var eggTimer = Timer()  // Initiapze the Timer class. 
   var timerActive = false // Prevents multiple timers from firing. 
   var timeLeft = 210  
   func stopTimer() { 
      timerActive = false 
      eggTimer.invapdate() 
   } 
     
   func processTimer() { 
      if timeLeft <= 0 { 
         stopTimer() 
         return 
      }     
      timeLeft = timeLeft - 1; 
      timeLeftLabel.text = String(timeLeft) 
   } 
    
   @IBAction func startTimerButton(_ sender: Any) { 
      if !timerActive {
         timerActive = true 
         eggTimer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: 
         #selector(ViewController.processTimer), userInfo: nil, repeats: true) 
      } 
   } 
     
   @IBAction func pauseTimerButton(_ sender: Any) { 
      stopTimer() 
   } 
    
   @IBAction func subtractTime(_ sender: Any) { 
      if timeLeft > 10 { 
         timeLeft = timeLeft - 10 
         timeLeftLabel.text = String(timeLeft) 
      } 
   } 
     
   @IBAction func resetTimer(_ sender: Any) { 
      timeLeft = 210 
      timeLeftLabel.text = String(timeLeft) 
   } 
     
   @IBAction func addTime(_ sender: Any) { 
      timeLeft = timeLeft + 10 
      timeLeftLabel.text = String(timeLeft) 
   } 
     
   override func viewDidLoad() { 
      super.viewDidLoad() 
      // Do any additional setup after loading the view, typically from a nib. 
   }  
   override func didReceiveMemoryWarning() { 
      super.didReceiveMemoryWarning() 
      // Dispose of any resources that can be recreated
   } 
}

This is all we will do in our apppcation, try to run the apppcation, it should run fine.

Storing Data on Local Storage

Storing data on local storage means to use the local device’s storage to store data related to apppcation on the device. We have two ways to store the data on a local storage namely NSUserDefault and CoreData.

Let us understand them in detail.

NSUserDefaults

NSUserDefaults are meant to store small pieces of data such as preferences, settings or inspanidual values. To use UserDefaults in our apppcation, we just need to create a reference to the nsuserDefaults through our code as shown below.

let defaultValues = NSUserDefaults.standardUserDefaults()

To set values to data in UserDefaults we can use the following code −

defaultValues.setObject("Simppfied iOS", forKey: "nameKey")  
func setDouble(value: Double, forKey defaultName: String) 
func setBool(value: Bool, forKey defaultName: String) 
func setObject(value: AnyObject?, forKey defaultName: String) 
func setURL(url: NSURL?, forKey defaultName: String) 
func setInteger(value: Int, forKey defaultName: String) 
func setFloat(value: Float, forKey defaultName: String) 

To get values from NSUserDefaults, we can use the following code.

func boolForKey(defaultName: String) -> Bool 
func integerForKey(defaultName: String) -> Int 
func floatForKey(defaultName: String) -> Float 
func doubleForKey(defaultName: String) -> Double 
func objectForKey(defaultName: String) -> AnyObject? 
func URLForKey(defaultName: String) -> NSURL? 

CoreData

CoreData is a persistent framework, which supports large data transactions. CoreData allows you to build relational entity–attribute model for storing user data. CoreData is a framework and can use SQLite, binary formats to store data.

To use CoreData in our apppcation, we will start with a new project and make sure you check “Use Core Data”, while creating the project.

Login Using core Data − Create a new project, select use CoreData as shown in the following screenshot.

Use Core Data

Continue until the project is open, now we see that the project has more files than our previous projects.

Core Data

This file CoreData_demo.xcdatamodeld is our database in which we will be making our user table and storing data.

Concept − The thing about CoreData is, even if we close the app, and open it after months, it will still have the data we stored, which we will see in the next apppcation we make.

Now we will see how to add core data and retrieve core data.

Adding Core Data − To add CoreData, cpck on the file CoreData_demo.xcdatamodeld and then we will see that the entities are empty. Cpck on add Entity button, it will add an entity, now double cpck on the entity name and rename it anything you pke.

Add Entity

Now cpck on the entity and we can see that the attributes field is empty. Cpck on the plus symbol and rename the entity. Select the type of the entity from the next field.

Attributes

We have added an Entity and one Attribute in it. Now, if we go to the AppDelegate.swift, we can see that two new functions have been added because we selected CoreData. The two functions added are −

Functions Added

Note − Import CoreData in your file before proceeding.

Saving data to Core Data − To save some data in CoreData, we need to make an object of AppDelegate Class.

let appDelegate = UIApppcation.shared.delegate as! AppDelegate

And, a context object

let context = appDelegate.persistentContainer.viewContext

Then, we need to create an entity object, which will call our entity −

let newValue = NSEntityDescription.insertNewObject(forEntityName: "Users", into: context)

We will now set the value of that attribute we created.

newValue.setValue(textField.text, forKey: "name")

We will save the data using

context.save();

Fetching from core data − While fetching, the above two steps (creating appDelegate and context) will be the same. Then, we will create a fetch request.

let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users") 

We will create an object to store the result.

let results = try context.fetch(request)

Then we will go through the results as per our requirement. We will see more of CoreData with the next apppcation we create.

Challenge − Try to create an apppcation, where the user enters the name, then cpcks on login and closes the apppcation. When the next time the user opens the apppcation, he should be still logged in. Then add a button – logout, and if he cpcks on that, the apppcation will ask for the username again.

Login/Logout using CoreData

Create a single view project called ‘Login’, select use of CoreData. Cpck on CoreData_demo.xcdatamodeld and add an entity called ‘Users’. Inside that, add an attribute called ‘name’.

Go to the main.storyboard, Add a text field and a login button. Below that, add a label, double cpck on it and remove its content. Then, add a logout button, go to its attribute inspector and make ‘alpha’ equal to 0. Now, our view should look as follows −

View Controller Scene

Now, go to your view controller file, open assistant editor and create connections between the UI Elements and your controller file.

Note − We will also create outlets for both the buttons, because we need to modify the look of those buttons. For example − When a user is logged in, we will hide the login button, if the user is not logged in we will show login and hide the logout button.

As we have already discussed about adding and fetching data from CoreData, we will put the code here.

Try-Catch − You will notice that we have used try-catch block many times in the code. It is because if we do not use the try-catch blocks and there is some exception or error in our program, the execution will stop. Whereas, if we are using the try catch blocks and if some error occurs, then the catch block handles the error. Read more about it in our Swift Tutorial

Code for Login/Logout Apppcation

Let us understand the different components and the code that is used for a login/logout apppcation.

Login Button Action − The following code explains how to add a login button action.

var isLoggedIn = false 
@IBAction func logIn(_ sender: AnyObject) { 
   let appDelegate = UIApppcation.shared.delegate as! AppDelegate
   let context = appDelegate.persistentContainer.viewContext 
   if isLoggedIn { 
      let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users") 
      do { 
         let results = try context.fetch(request) 
         if results.count > 0 { 
            for result in results as! [NSManagedObject] { 
               result.setValue(textField.text, forKey: "name") 
               do { 
                  try context.save() 
               } 
               catch { 
                  print("Update username failed") 
               } 
            } 
            label.text = "Hi " + textField.text! + "!" 
         } 
      } 
      catch { 
         print("Update failed") 
      } 
   } else { 
      let newValue = NSEntityDescription.insertNewObject(forEntityName: "Users", into: context) 
      newValue.setValue(textField.text, forKey: "name") 
      do { 
         try context.save() 
         logInButton.setTitle("Update username", for: []) 
         label.alpha = 1 
         label.text = "Hi " + textField.text! + "!" 
         isLoggedIn = true 
         logOutButton.alpha = 1 
      }  
      catch { 
         print("Failed to save") 
      }     
   } 
}    

Logout Button Action − The following code explains how to add a logout button action.

@IBAction func logOut(_ sender: AnyObject) { 
   let appDelegate = UIApppcation.shared.delegate as! AppDelegate 
   let context = appDelegate.persistentContainer.viewContext 
   let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users") 
   do { 
      let results = try context.fetch(request) 
      if results.count > 0 { 
         for result in results as! [NSManagedObject] { 
            context.delete(result) 
            do { 
               try context.save() 
            } catch { 
               print("Inspanidual delete failed") 
            } 
         } 
         label.alpha = 0 
         logOutButton.alpha = 0 
         logInButton.setTitle("Login", for: []) 
         isLoggedIn = false 
         textField.alpha = 1 
      } 
   } catch { 
      print("Delete failed") 
   } 
}

ViewDidLoad() − The following code explains how to use the ViewDidLoad() function.

override func viewDidLoad() { 
   super.viewDidLoad() 
   // Do any additional setup after loading the view, typically from a nib.
   let appDelegate = UIApppcation.shared.delegate as! AppDelegate 
   let context = appDelegate.persistentContainer.viewContext 
   let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Users") 
   request.returnsObjectsAsFaults = false 
   do { 
      let results = try context.fetch(request) 
      for result in results as! [NSManagedObject] { 
         if let username = result.value(forKey: "name") as? String { 
            logInButton.setTitle("Update username", for: []) 
            logOutButton.alpha = 1 
            label.alpha = 1 
            label.text = "Hi there " + username + "!" 
         }     
      } 
             
   } catch { 
      print("Request failed") 
   } 
}        

Remember you had to create an outlet and an action, for both the buttons.

Now, save and run the apppcation. Login, close the apppcation and run it again. It should look as follows.

Outlet

That is all we will do with CoreData. Using the same concepts, we can build many CoreData apppcations.

Controlpng the Keyboard

In this section, we will learn to control the keyboard behavior. For example – When we cpck outside a text field after entering some text, the keyboard does not close. Here, we will understand how to control the keyboard.

Keyboard should disappear on cpcking outside the input field

This is a simple task, to do this just paste the following code into your viewController file, before the closing the curly braces.

override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 
   self.view.endEditing(true)  
}

By doing this, it will make the keyboard disappear on cpcking outside the input field.

Keyboard should disappear on return key tap

To make the keyboard disappear, we should add a new Type for our view Controller. We will also add a text field and create its outlet called textField. Lastly, we will add the UITextFieldDelegate.

UITextFieldDelegate

We will also control + drag from our input field to the view controller and select delegate from the options that appear.

Then, we will add the following function.

func textFieldShouldReturn(_ textField: UITextField) -> Bool { 
   textField.resignFirstResponder()  
   return true 
}

The final View Controller file should look as follows −

import UIKit 
class ViewController: UIViewController, UITextFieldDelegate { 
   override func viewDidLoad() { 
      super.viewDidLoad() 
      // Do any additional setup after loading the view, typically from a nib. 
   }  
   override func didReceiveMemoryWarning() { 
      super.didReceiveMemoryWarning() 
      // Dispose of any resources that can be recreated. 
   } 
   override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) { 
      self.view.endEditing(true) 
   }
   func textFieldShouldReturn(_ textField: UITextField) -> Bool { 
      textField.resignFirstResponder() 
      return true 
   } 
}    

Downloading Web Content − Opening Facebook/Google

In this section, we will learn about making an apppcation, which will open Facebook and Google, when each button is pressed respectively. We will also learn the concept of Web Views and App transport layer Security. After this, you will be able to make a browser of your own.

Note − We need an Internet Connection in this apppcation.

Making a Web Apppcation

We will make a new single view apppcation, iOS project. In the Search bar of the object pbrary, we will search for web view, drag it and add it to our View controller in the main.Storyboard.

After adding the web view, we will stretch it to all the corners. The Apppcation UI should look pke as follows −

Apppcation UI

We will open our main.storyboard and view controller by cpcking on the assistant editor. We will create an outlet for our webView and action for both the buttons. On load, the apppcation will load yahoo in webView. On cpcking google, it should load Google, and on cpcking the Facebook button, it should load the Facebook page.

The final view should look as follows −

Final View

The following screenshots show how the different screens of our apppcation should look pke. If you try to open a web service that is not https, it will show an error and we will have to add an App Transport Layer Security exception in your info.ppst file.

Infoppst Advertisements