iOS.& Swift Books iOS.Apprentice

22
导航控制器 由Eli Ganim撰写

此时,高分屏幕包含显示少数固定数据行的表视图。然而,这个想法是,当玩家分数它们时,高分就会更新。因此,您需要实现添加项目的能力。

在本章中,您将扩展应用程序拥有 导航栏 在顶部。每当单击行时,将显示一个新屏幕,允许用户插入高分器的名​​称。点击完成后,将添加新项目将添加到列表中。

本章涵盖以下内容:

  • 导航控制器:将导航控制器添加到应用程序以允许在屏幕之间导航。
  • 删除行 :添加通过表视图呈现的项目列表中删除行的功能。
  • 添加项目屏幕:创建一个新屏幕,玩家可以插入他们的名称。

导航控制器

首先,让我们添加导航栏。您可能已经在对象库中看到有一个名为Navigation Bar的对象。您可以将其拖到您的视图中并将其放在顶部,但在此特定实例中,您将无法执行此操作。

相反,您将嵌入您的视图控制器 导航控制器.

在表视图旁边,导航控制器可能是第二个最常用的IOS用户界面组件。这是让你从一个屏幕到另一个屏幕的东西:

行动中的导航控制器
行动中的导航控制器

The UINavigationController object takes care of most of this navigation stuff for you, which saves a lot of programming effort. It has a navigation bar with a title in the middle and a “back” button that automatically takes the user back to the previous screen. You can put a button (or several buttons) of your own on the right.

添加导航控制器

添加导航控制器真的很容易。

将视图控制器置于导航控制器内
Kinxuzw Hho Peid Miqjcustam agpahi i xisiteguac gacjfuszoh

导航控制器现在与您的视图控制器相关联
Zbo Weciwuhiuk Jatcculvek UG Say Vobgem Xany Boag Feec TuqqWomdas

SEGUE类型

什么是可能的SEGUUS,它们的意思是什么?以下是对每种类型的SEGUE的简要说明:

设置导航栏标题

➤返回故事板,选择 导航项目 在下面 查看控制器场景 在文档大纲中,切换到右侧窗格上的属性检查器,并设置值 标题 靶心 .

在导航栏中更改标题
rhuzdasp mdu podki uq rbe gikarakuok ciw

将导航项添加到视图控制器
Eyz a sesuvunoiz aqip mo tba tauw qoflmixsoj

标题导航栏
zulununeiq tat weyb fidri

删除行

想象一下,你让朋友在你的iPhone上享受惊人的靶心游戏,他达到了一个高分,你不能击败。这真的很烦人!

在操作中滑动到删除
Drecu-ri-hikanu ib ohteuq

滑动到删除

滑动到删除非常易于实现。

override func tableView(
                _ tableView: UITableView, 
        commit editingStyle: UITableViewCell.EditingStyle,
         forRowAt indexPath: IndexPath) {
  // 1
  items.remove(at: indexPath.row)
  
  // 2  
  let indexPaths = [indexPath]
  tableView.deleteRows(at: indexPaths, with: .automatic)
}

添加导航按钮

既然可以从列表中删除项目,也有助于将高分列表重置为其初始状态是有用的。您将在导航栏右侧添加一个按钮以将高分列表重置为其初始状态。

将栏按钮项拖动到导航栏中
dcovzurs我wox qukpuc ubif uzpa vma ziqotaraiv yud

带有重置按钮的应用程序
TSE eNB Wenq Fra Revej Fojmew

使导航按钮做点什么

如果点击新的重置按钮,它实际上并没有做任何事情。那是因为你没有把它联系到一个动作。你有很多运动 靶心 ,所以它现在应该是孩子对你的娱乐。

// MARK:- Actions
@IBAction func resetHighScores() {
}
从重置按钮控制 - 拖动到高分视图控制器
MICBVEF-YSUG JXOQ今天GUXSOG是NUYPGEG HEAD KEGLFAWMIK

  override func viewDidLoad() {
    super.viewDidLoad()
    resetHighScores()
  }
  
  // MARK:- Actions
  @IBAction func resetHighScores() {
    items = [HighScoreItem]()
    let item1 = HighScoreItem()
    item1.name = "The reader of this book"
    item1.score = 50000
    items.append(item1)
    
    . . .
    
    let item5 = HighScoreItem()
    item5.name = "Eli"
    item5.score = 500
    items.append(item5)
    tableView.reloadData()
  }

保存和加载高分

您可能注意到,每次重新启动应用程序时都会重置高分数据。那是因为你没有保存或加载数据。

class HighScoreItem : Codable
class PersistencyHelper {
  static func saveHighScores(_ items: [HighScoreItem]) {
    let encoder = PropertyListEncoder()
    do {
      let data = try encoder.encode(items)
      try data.write(to: dataFilePath(), options: Data.WritingOptions.atomic)
    } catch {
      print("Error encoding item array: \(error.localizedDescription)")
    }
  }
  
  static func loadHighScores() -> [HighScoreItem] {
    var items = [HighScoreItem]()
    let path = dataFilePath()
    if let data = try? Data(contentsOf: path) {
      let decoder = PropertyListDecoder()
      do {
        items = try decoder.decode([HighScoreItem].self, from: data)
      } catch {
        print("Error decoding item array: \(error.localizedDescription)")
      }
    }
    return items
  }
  
  static func dataFilePath() -> URL {
    let paths = FileManager.default.urls(for: .documentDirectory,
                                          in: .userDomainMask)
    return paths[0].appendingPathComponent("HighScores.plist")
  }
}
  override func viewDidLoad() {
    super.viewDidLoad()
    items = PersistencyHelper.loadHighScores()
    if (items.count == 0) {
      resetHighScores()
    }
  }

添加新的高分

有一件丢失:你如何为列表添加新的高分?显然,当游戏结束时需要发生。

@IBAction func startNewGame() {
    addHighScore(score)
    . . .
}
func addHighScore(_ score:Int) {
  // 1
  guard score > 0 else {
    return;
  }

  // 2
  let highscore = HighScoreItem()
  highscore.score = score
  highscore.name = "Unknown"

  // 3
  var highScores = PersistencyHelper.loadHighScores()
  highScores.append(highscore)
  highScores.sort { $0.score > $1.score }
  PersistencyHelper.saveHighScores(highScores)
}

编辑高分屏幕

您已经学会了如何添加新的高分,但所有这些都包含同一个玩家名称 - “未知”。您需要提供一种改变名称的方法。为此,您将使用文本字段创建一个新屏幕以更改播放器的名称。它看起来像这样:

编辑高分屏幕
Kje Inad Qawl Dlole Hjjiir

向故事板添加新视图控制器

➤转到对象库并拖动新 表视图控制器 (不是常规视图控制器)上的故事板画布。

将新表视图控制器拖入画布中
vgibnonw e kay johva qaiq nocrmuwxiy emki rre gatxap

从添加按钮控制 - 拖动到新表视图控制器
Zagqxok-Qrod Fdel Pre Unk Vabrac Co QFI Faz Pisyo Keh Geyhfanxoy

行动segue弹出窗口
ZPA IHKEOB GAHIO套件

在两个视图控制器之间添加新的SEGUE
O JEF Zixei Es Uhwom Pittoav FVU TQO CAAV MELFHONWIFC

自定义导航栏

所以现在您有一个新的表视图控制器,当按下单元格时幻灯片进入屏幕。但是,这个屏幕是空的。数据输入屏幕通常具有导航栏,左侧的取消按钮以及右侧的完成按钮。在某些应用中,右侧的按钮称为保存或发送。按下这些按钮中的任何一个将关闭屏幕,但只完成将保存更改。

新屏幕的导航栏项
yvu meziyotaic reghyevh zuy xgo bip drdaan

应用程序中的取消和完成按钮
xpo goxsun arc gela sifnorp od bru anf

制作自己的视图控制器类

您为关于屏幕创建了一个自定义视图控制器。你还记得自己是如何自己做的吗?如果没有,这里有以下步骤:

import UIKit

class EditHighScoreViewController: UITableViewController {
  override func viewDidLoad() {
    super.viewDidLoad()
  }
}

使导航按钮工作

还有一个问题 - 取消和完成按钮应该关闭添加项目屏幕并将应用程序返回到主屏幕,但仍然没有效果。

// MARK:- Actions
@IBAction func cancel() {
  navigationController?.popViewController(animated: true)
}

@IBAction func done() {
  navigationController?.popViewController(animated: true)
}
从栏按钮拖动到视图控制器
Revgtoj-Vfulgokb xqiz bri xow yexjes fo dgi waos yohztaktuc

容器视图控制器

您已读取一个视图控制器代表一个屏幕,但在此处为每个屏幕实际上有两个视图控制器:在导航控制器内部的表视图控制器。

有一个技术问题?想报告一个错误吗? 您可以向官方书籍论坛中的书籍作者提出问题和报告错误 这里 .

有反馈分享在线阅读体验吗? 如果您有关于UI,UX,突出显示或我们在线阅读器的其他功能的反馈,您可以将其发送到设计团队,其中表格如下所示:

© 2021 Razeware LLC

您可以免费读取,本章的部分显示为 混淆了 文本。解锁这本书,以及我们整个书籍和视频目录,带有Raywenderlich.com的专业订阅。

现在解锁

要突出或记笔记,您需要在订阅中拥有这本书或自行购买。