首页 iOS.& Swift Books 教程设计模式

6
单身图案 由约书亚格林写

单身模式仅限课程 实例。对类的每次引用都是指相同的底层实例。这种模式在iOS应用程序开发中非常常见,因为Apple广泛使用它。

“Singleton Plus”模式也是常见的,它提供了一个共享的单身实例,允许创建其他实例。

你什么时候应该用它?

在具有类的多个实例时使用单例模式会导致问题,或者何时不会逻辑。

如果共享实例很有用,则使用单例加图案 最多 of the time, but you also want to allow custom instances to be created. An example of this is FileManager, which handles everything to do with filesystem access. There is a “default” instance which is a singleton, or you can create your own. You would usually create your own if you’re using it on a background thread.

操场例子

打开 阅读centraledesignpatters.xcWorkspace. 在里面 起动机 目录和打开的目录 概述 page.

import UIKit

// MARK: - Singleton
let app = UIApplication.shared
// let app2 = UIApplication()
public class MySingleton {
  // 1
  static let shared = MySingleton()
  // 2
  private init() { }
}
// 3
let mySingleton = MySingleton.shared
// 4
// let mySingleton2 = MySingleton()
// MARK: - Singleton Plus
let defaultFileManager = FileManager.default
let customFileManager = FileManager()
public class MySingletonPlus {
  // 1
  static let shared = MySingletonPlus()
  // 2
  public init() { }
}
// 3
let singletonPlus = MySingletonPlus.shared

// 4
let singletonPlus2 = MySingletonPlus()

你要小心的是什么?

单身图案非常远离。

教程项目

您将继续从上一章中建立rabble wabble。

创建Apptings Singleton

您需要做的第一件事是在某处存储应用设置。你要为这个创造一个单身人士!

import Foundation

public class AppSettings {
  // MARK: - Static Properties
  public static let shared = AppSettings()
  
  // MARK: - Object Lifecycle
  private init() { }
}
// MARK: - QuestionStrategyType
public enum QuestionStrategyType: Int, CaseIterable {    
  
  case random
  case sequential
  
  // MARK: - Instance Methods    
  public func title() -> String {
    switch self {
    case .random:
      return "Random"
    case .sequential:
      return "Sequential"
    }
  }
  
  public func questionStrategy(
    for questionGroup: QuestionGroup) -> QuestionStrategy {
    switch self {
    case .random:
      return RandomQuestionStrategy(
        questionGroup: questionGroup)
    case .sequential:
      return SequentialQuestionStrategy(
        questionGroup: questionGroup)
    }
  }
}
// MARK: - Keys
private struct Keys {
  static let questionStrategy = "questionStrategy"
}
// MARK: - Instance Properties
public var questionStrategyType: QuestionStrategyType {
  get {
    let rawValue = userDefaults.integer(
      forKey: Keys.questionStrategy)
    return QuestionStrategyType(rawValue: rawValue)!
  } set {
    userDefaults.set(newValue.rawValue,
                     forKey: Keys.questionStrategy)
  }
}
private let userDefaults = UserDefaults.standard
// MARK: - Instance Methods
public func questionStrategy(
  for questionGroup: QuestionGroup) -> QuestionStrategy {
  return questionStrategyType.questionStrategy(
    for: questionGroup)
}

选择策略

您接下来需要创建一个新的视图控制器,以便用户可以选择所需的问题策略。

import UIKit

// 1
public class AppSettingsViewController: UITableViewController {
  // 2
  // MARK: - Properties
  public let appSettings = AppSettings.shared
  private let cellIdentifier = "basicCell"

  // MARK: - View Life Cycle
  public override func viewDidLoad() {
    super.viewDidLoad()
    
    // 3
    tableView.tableFooterView = UIView()
    
    // 4
    tableView.register(UITableViewCell.self,
                       forCellReuseIdentifier: cellIdentifier)
  }
}
// MARK: - UITableViewDataSource
extension AppSettingsViewController {

  public override func tableView(
    _ tableView: UITableView,
    numberOfRowsInSection section: Int) -> Int {
    
      // 1
      return QuestionStrategyType.allCases.count
  }
  
  public override func tableView(
    _ tableView: UITableView,
    cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    
    let cell = tableView.dequeueReusableCell(
      withIdentifier: cellIdentifier, for: indexPath)

    // 2
    let questionStrategyType = 
      QuestionStrategyType.allCases[indexPath.row]

    // 3
    cell.textLabel?.text = questionStrategyType.title()

    // 4
    if appSettings.questionStrategyType == 
      questionStrategyType {
      cell.accessoryType = .checkmark
    } else {
      cell.accessoryType = .none
    }
    return cell
  }
}
// MARK: - UITableViewDelegate
extension AppSettingsViewController {
  public override func tableView(
    _ tableView: UITableView,
    didSelectRowAt indexPath: IndexPath) {

    let questionStrategyType = 
      QuestionStrategyType.allCases[indexPath.row]
    appSettings.questionStrategyType = questionStrategyType
    tableView.reloadData()
  }
}

private let appSettings = AppSettings.shared
viewController.questionStrategy =
  SequentialQuestionStrategy(
    questionGroup: selectedQuestionGroup)
viewController.questionStrategy =
      appSettings.questionStrategy(for: selectedQuestionGroup)

关键点

您在本章中了解了Singleton模式。以下是其关键点:

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

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

© 2021 Razeware LLC

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

现在解锁

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