使用Swift2进行iOS开发 - 高级iOS

在本章中,我们将介绍一些高级功能,如在我们的应用程序上创建多个视图,添加导航栏,添加表视图,在应用程序中存储数据,制作Web应用程序等等.

<请仔细阅读每一部分,因为本章包含开发应用程序时所需的大部分内容.

多视图控制器

在我们之前的应用程序中,我们只提供了一个视图/视图控制器.但是,我们可以在我们的应用程序中拥有多个视图,我们可以独立执行任何视图.

因此,我们将首先创建一个新项目;该项目的名称有多个视图.与其他项目一样,该项目还有一个View Controller和一个Swift文件. (您可以通过在Identity Inspector中选择查看和查看其属性来查看.)

以下屏幕截图显示了我们当前视图的显示方式 :

入口点

在右侧(身份检查员),我们可以看到与我们的视图控制器相关.左侧的箭头是入口点.这是应用程序开始运行后显示的应用程序的第一个视图.

添加第二个多视图控制器

添加其他视图控制器我们的应用程序,我们将在对象库中搜索视图控制器.一旦找到它,我们将视图控制器拖到我们的main.stroryboard,就在任何其他视图之外.

第二个多视图控制器

这就是你的应用程序的样子.现在,我们添加了一个视图控制器,但现在我们还需要为新添加的视图创建一个视图控制器类.

右键单击您的项目 → 新文件 →  cocoa Touch Class →  将它命名为任意名称,我们将其命名为"SecondViewController".

这是为视图控制器创建类文件的方法.现在,返回"main.storyboard",单击第二个视图控制器并查看其Identity Inspector.

类字段现在必须为空,所以单击该字段开始输入您在上一步中添加的类名.如果出现,请单击回车.

Second View Controller

我们有现在创建了一个多视图控制器并为该视图添加了控制器类文件.但是,如果您运行该应用程序,它将不会显示您的第二个视图.为什么?

因为我们还没有添加一个函数,它将把我们带到那个视图.简而言之,我们尚未向我们的应用程序添加导航.别担心;我们将在下一节中介绍它.

向应用程序添加导航

从一个视图转换到另一个视图的过程称为 Segueing ,即通过在两个视图之间创建segue来完成.为此,在第一个视图控制器中添加一个按钮,并控制从它拖动到第二个视图.当您释放按钮时,您将看到一些选项,如下面的屏幕截图所示.

添加导航到应用程序

从Action Segue中选择Show选项.现在运行你的应用程序,你会看到点击一个按钮,你会看到第二个视图(要在第二个视图中看到更清楚的东西,以便你可以识别).

但是,现在你无法回到第一个视图.为此,我们有导航控制器.

添加导航控制器

选择您的第一个视图控制器并在顶部栏,点击 Editor → 嵌入 → 导航控制器.

编辑

现在,我们的应用程序应该看起来像下面的截图.

Screenshot

我们应该看到它,在视图顶部有一个浅灰色的行.现在,当我们运行应用程序时,我们可以看到视图顶部有一个导航栏.当我们点击按钮时,我们将转到第二个视图,在那里我们将看到该导航栏中的后退按钮.单击此按钮,我们将返回初始视图.

添加标题&导航栏的后退按钮

要在导航栏中添加标题,请单击导航栏,然后查看其属性检查器.在那里我们将看到 :

Title Back Button

  • 标题 : 这将是导航栏的标题,它出现在中心.

  • 提示 : 它出现在标题栏的顶部,位于中心.

  • 后退按钮 : 在这里,您可以修改后退按钮中显示的文本.

目前,传递视图的按钮位于我们的视图中,如果我们想要在屏幕上显示其他内容,则可能不合适.因此,我们将在导航栏中添加一个Bar Button项,它将带我们进入第二个视图.但是,为此我们应该首先删除我们添加的最后一个按钮.

添加一个条形按钮项

在对象库中搜索条形按钮项并拖放到导航栏的右侧.将其命名为 - "下一步>",控制从它拖动到第二个视图,选择显示,就像我们添加的最后一个按钮一样.

添加栏按钮

现在运行应用程序,它看起来更干净,更好.这就是我们现在要做的所有导航.在随后的章节中,我们将在需要时使用Swift代码修改导航栏.

表格视图

表格将数据显示为单个包含多行的列列表,可以进一步划分为多个部分.表应该用于以干净有效的方式呈现数据.

在本节中,我们将了解如何添加表视图,添加原型单元,添加数据源和表的委托查看,更改表的属性以及为表视图单元设置动态数据.

添加表视图

要添加表视图,我们将首先创建一个新项目并将其命名为 - "tableView".然后,转到对象库并搜索Table View,我们将看到表视图,表视图控制器和许多其他选项.但是,我们应该选择表视图,拖动它并添加到默认视图Controller.

Table View

添加原型单元格

拉伸表格视图,使其覆盖整个视图,同时突出显示表格视图.检查其属性检查器,有一个名为Prototype cells的字段,当前为0.我们应将其值更改为1,现在您的视图应如下所示 :

原型单元格

更改单元格标识符

现在,在视图中,单击原型单元格(这有点棘手).因此,在您的文档大纲中,单击View controller → 查看 → 表视图 → 表视图单元格,现在在其属性检查器中有一个名为Identifier的列,单击该列并将其命名为"Cell".请参阅以下屏幕截图以了解上述步骤.

Table View Cell

添加代表&数据源

为了使我们的表视图动态化,我们需要它们来加载动态数据.因此,我们需要一个委托和数据源.要创建表的委托和数据源,请控制从表视图拖动到视图控制器或视图控制器顶部的黄色按钮,如下面的屏幕截图所示.

委托数据源

当我们发布游标时,我们会看到两个选项,dataSource和delegate,逐个选择它们(当您选择任何一个选项时,弹出窗口将隐藏,您需要重复上述步骤以添加第二个选项).现在它应该看起来像 :

奥特莱斯

这就是我们所有我们将使用我们的UI/Main.Storyboard.现在切换到"ViewController.swift"文件.将 UITableViewDelegate,UITableViewDataSource 添加到viewController.swift中,如下所示 :

表视图委托视图数据源

但是,现在Xcode将在此行中显示错误.

Xcode Error

这是因为有几种方法我们需要使用 UITableView

要查看这些方法,请按住Command键并单击UITableViewDataSouce,然后复制前两个方法,使用"numberOfRowsInSection","cellForRowAtIndex"参数并将它们粘贴到ViewController.swift中,然后再放入viewDidLoad().

从这两种方法中删除此行 @available(iOS 2.0,*),并添加左右括号"{}".现在,视图将如下所示 :

Uitableview

Xcode必须在两个函数中显示错误.但是,请不要担心,因为我们没有添加这些函数的返回类型.

numberOfRowsInSection : 此函数定义我们的部分将包含的行数.所以现在将此行添加到您的方法中.

return 1 //This will return only one row.

cellForRowAt : 此方法返回每个单元格的内容, indexPath 包含每个单元格的索引.我们将创建一个单元格然后我们将为该单元格分配一些值并最终返回单元格.

现在,您的函数应如下所示 :

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 
}

在第一行中,我们创建一个具有默认样式的单元格, reuseIdentifier 是原型的名称我们制作的单元格.

Cell.textLable?.text : 这定义了应该显示为该单元格标题的文本.

最后,我们从那里返回一个单元格.现在尝试运行你的应用程序,它应该如下 :

重用标识符

时间表应用程序

在这个应用程序中,我们将继续我们的最后一个项目,我们将创建一个应用程序,我们打印2(2 ... 10 ... .20)的表.

因此,要创建此应用程序,只需更改项目的视图控制器文件.

更改功能如下所示 :

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") 
}

现在,运行你的应用.它应该如下所示.

时间表应用程序

现在,因为我们已经完成了表格视图并制作了一个应用程序,所以这是我们要解决的快速挑战.

挑战

制作一个应用程序,我们打印用户输入的数字的计数表.

提示 : 取输入,添加一个按钮,按下该按钮将加载该表并计算该数字.这里我们还需要以下函数,它将重新加载表数据.

 
 tableView.reloadData()

这对您来说是一个挑战,因为我们已经涵盖了有关此应用程序的所有主题,因此我们不会为此提供解决方案.

Egg计时器应用程序

在这个应用程序中,我们将使用 Timer()类构造函数的概念来管理时间.我们将为您提供概念和编码.您必须自己创建UI,因为我们已经在前面的章节中多次讨论过每个UI元素. (虽然我们会为看起来很新的所有内容提供提示.)

您的最终应用布局应如下所示;

Egg Egg Application

这个应用程序会发生什么?

  • 标题标签的起始值为210.

  • 点击播放按钮后,值应每秒减少一次.

  • 点击暂停时,价值应仅在那里停止.

  • 点击 - 10,值应减少10,减量应继续.

  • 点击+10,值应增加10,减量应继续.

  • 点击重置后,价值应变为210.

  • 价值永远不会消失低于0.

概念

  • 我们将使用Timer()&rarr类的变量; var timer = Timer().

  • 我们将为刚刚创建的这个计时器变量设置一个值.

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

    • timeInterval  - >是我们想要使用的时间间隔,

    • target  - >是应该实现的视图控制器,

    • selector  - >是将使用此计时器的函数名称,

    • userInfo  - > null和重复,是的,我们想重复一遍这是真的.

定时器无效

要通过编程停止定时器,我们将添加 timer.invalidate()功能.

我们使用的元素 :

导航栏 : 在导航栏中,我们添加了三项.

  • 条形按钮项目,左侧一个,右侧一个.

  • 标题为 - "我们的蛋计时器".

导航栏

工具栏 : 工具栏的底部会显示一个工具栏,其中包含用于执行与当前视图或其中内容相关的操作的按钮.

工具栏是半透明的,可能具有背景色调.当人们不太可能需要它们时,它们经常隐藏.

我们在UI的底部添加了一个工具栏,它有5个项目.

  • 三个条形按钮项目,名为-10,重置和+10.

  • 两个灵活空间:条形按钮项目之间的灵活空间和减号;

工具栏

如何添加图标到条形按钮项目?

选择条形按钮项目.单击您的栏按钮项,转到属性检查器,单击选择项并从显示的下拉列表中选择项目.

按钮的图标按钮

同样,为所有其他按钮选择项目并创建上面给出的UI.将标签添加到视图的中心并将其作为插座连接,将其命名为 :   timeLeftLabel .

启动计时器的操作

以下是启动计时器的程序.

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

创建以下函数 :

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

停止功能的动作

以下是程序停止函数.

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

时间的行动

以下是程序gtime.

@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) 
}

行动for addTime

以下是添加时间的程序.

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

现在, viewController.swift应该看起来像 :

import UIKit 
class ViewController: UIViewController { 
   @IBOutlet weak var timeLeftLabel: UILabel! 
   var eggTimer = Timer()  // Initialize the Timer class. 
   var timerActive = false // Prevents multiple timers from firing. 
   var timeLeft = 210  
   func stopTimer() { 
      timerActive = false 
      eggTimer.invalidate() 
   } 
     
   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
   } 
}

我们将在我们的应用程序中执行所有操作,尝试运行应用程序,运行正常.

存储数据本地存储

在本地存储上存储数据意味着使用本地设备的存储来存储与设备上的应用程序相关的数据.我们有两种方法可以将数据存储在本地存储上,即 NSUserDefault CoreData .

让我们详细了解它们.

NSUserDefaults

NSUserDefaults用于存储小块数据,例如首选项,设置或单个值.要在我们的应用程序中使用UserDefaults,我们只需要通过我们的代码创建对nsuserDefaults的引用,如下所示.

 
 let defaultValues = NSUserDefaults. standardUserDefaults()

要在UserDefaults中设置数据值,我们可以使用以下代码 :

defaultValues.setObject("Simplified 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)

要从NSUserDefaults获取值,我们可以使用以下代码.

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是一个持久框架,支持大数据事务. CoreData允许您构建用于存储用户数据的关系实体属性模型. CoreData是一个框架,可以使用SQLite,二进制格式来存储数据.

要在我们的应用程序中使用CoreData,我们将从一个新项目开始,并确保选中"使用核心数据" ,在创建项目时.

使用核心数据登录 : 创建一个新项目,选择使用CoreData,如下面的屏幕截图所示.

使用核心数据

继续直到项目打开,现在我们看到项目的文件比以前的项目多.

核心数据

此文件 CoreData_demo.xcdatamodeld 是我们的数据库,我们将在其中创建用户表并存储数据.

概念 : 关于CoreData的事情是,即使我们关闭应用程序,并在几个月后打开它,它仍然会有我们存储的数据,我们将在下一个应用程序中看到.

现在我们将看到如何添加核心数据和检索核心数据.

添加核心数据 : 要添加CoreData,请单击CoreData_demo.xcdatamodeld文件,然后我们将看到实体为空.点击添加实体按钮,它将添加一个实体,现在双击实体名称并将其重命名为您喜欢的任何内容.

添加实体

现在点击实体,我们可以看到属性字段为空.单击加号,然后重命名该实体.从下一个字段中选择实体的类型.

Attributes

我们在其中添加了一个实体和一个属性.现在,如果我们转到 AppDelegate.swift ,我们可以看到添加了两个新函数,因为我们选择了CoreData.添加的两个函数是 :

添加的功能

注意 : 在继续之前在文件中导入CoreData.

将数据保存到核心数据 : 要在CoreData中保存一些数据,我们需要创建一个AppDelegate类的对象.

 
让appDelegate = UIApplication.shared.delegate as! AppDelegate

并且,上下文对象

 
 let context = appDelegate. persistentContainer.viewContext

然后,我们需要创建一个实体对象,它将调用我们的实体 :

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

我们现在设置值我们创建的那个属性.

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

我们将使用

 
 context.save();来保存数据.

从核心数据中获取 : 在获取时,上述两个步骤(创建appDelegate和context)将是相同的.然后,我们将创建一个获取请求.

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

我们将创建一个对象来存储结果.

 
 let results = try context.fetch (请求)

然后我们将根据我们的要求查看结果.我们将在下一个应用程序中看到更多CoreData.

挑战 : 尝试创建一个应用程序,用户输入名称,然后单击登录并关闭应用程序.当用户下次打开应用程序时,他应该仍然登录.然后添加一个按钮 - 注销,如果他点击该按钮,应用程序将再次询问用户名.

使用CoreData登录/注销

创建一个名为"Login"的单个视图项目,选择使用CoreData.单击CoreData_demo.xcdatamodeld并添加名为"Users"的实体.在其中,添加一个名为'name'的属性.

转到main.storyboard,添加文本字段和登录按钮.在其下方,添加标签,双击它并删除其内容.然后,添加一个注销按钮,转到其属性检查器并使'alpha'等于0.现在,我们的视图应如下所示 :

查看控制器场景

现在,转到视图控制器文件,打开助理编辑器,并在UI元素和控制器文件之间建立连接.

注意 : 我们还将为这两个按钮创建插座,因为我们需要修改这些按钮的外观.例如 : 当用户登录时,我们将隐藏登录按钮,如果用户未登录,我们将显示登录并隐藏登出按钮.

我们已经讨论了添加和从CoreData获取数据,我们将把代码放在这里.

Try-Catch : 您会注意到我们在代码中多次使用了try-catch块.这是因为如果我们不使用try-catch块并且程序中存在一些异常或错误,则执行将停止.然而,如果我们使用try catch块并且如果发生某些错误,则catch块处理错误.在我们的 Swift教程中了解更多相关信息

登录/退出应用程序代码

让我们了解用于登录/注销应用程序的不同组件和代码.

登录按钮操作 : 以下代码说明了如何添加登录按钮操作.

var isLoggedIn = false 
@IBAction func logIn(_ sender: AnyObject) { 
   let appDelegate = UIApplication.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") 
      }     
   } 
}

退出按钮操作 : 以下代码说明了如何添加注销按钮操作.

@IBAction func logOut(_ sender: AnyObject) { 
   let appDelegate = UIApplication.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("Individual 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 = UIApplication.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 application. Login, close the application 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 applications.

Controlling the Keyboard

In this section, we will learn to control the keyboard behavior. For example – When we click 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 clicking 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 clicking 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 application, 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 application.

Making a Web Application

We will make a new single view application, iOS project. In the Search bar of the object library, 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 Application UI should look like as follows  :

Application UI

We will open our main.storyboard and view controller by clicking on the assistant editor. We will create an outlet for our webView and action for both the buttons. On load, the application will load yahoo in webView. On clicking google, it should load Google, and on clicking 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 application should look like. 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.plist file.

Infoplist