我喜欢在Cocoa应用程序中使用模型 - 视图 - 控制器设计模式(用Swift编写)。让我们假设着名人物示例:应用程序应显示文本字段和添加按钮。可以将人名放入文本字段,然后通过单击添加按钮将其存储在数组中(并且可以在表视图中显示数组内容)。现在,故事板包含我所有与View相关的内容,而类Person(具有变量名)构成了Model类。视图控制器将负责接收显示数据(例如表视图委托和数据源)并具有提取名称并将其放在某处的IBAction。但是,我不知道在哪里实际放置包含所有名称的数组。我是否也可以在视图控制器中使用它(这是我认为最简单的解决方案)?或者别的地方?如果应用程序在不同视图中使用多个数据保持结构(使用不同的视图控制器)变得越来越复杂,该怎么办?
答案 0 :(得分:0)
1)ViewController(来自UITableViewController或UIViewController):
class ViewController: UITableViewController, UITextFieldDelegate {
var model = ViewModel()
override func viewDidLoad() {
super.viewDidLoad()
tableView.register(UITableViewCell.self, forCellReuseIdentifier: "personCell")
let nib = UINib(nibName: "InputTableViewCell", bundle: nil)
tableView.register(nib, forCellReuseIdentifier: "inputCell")
// Request or load the data into model
// requestData() & tableView.reloadData() here
}
// MARK: - UITableViewDataSource
override func numberOfSections(in tableView: UITableView) -> Int {
return 2
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return section == 0 ? 1 : model.persons?.count ?? 0
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
if indexPath.section == 0 {
let cell = tableView.dequeueReusableCell(withIdentifier: "inputCell", for: indexPath)
if let inputCell = cell as? InputTableViewCell {
inputCell.textField.text = model.input
inputCell.textField.delegate = self
inputCell.textField.addTarget(self, action: #selector(textFieldEditing(_:)), for: .editingChanged)
inputCell.buttonAdd.addTarget(self, action: #selector(buttonAddTapped(_:)), for: .touchUpInside)
}
return cell
} else {
let cell = tableView.dequeueReusableCell(withIdentifier: "personCell", for: indexPath)
let person = model.persons?[indexPath.row]
cell.textLabel?.text = person?.name
return cell
}
}
// MARK: - Event Handler
func textFieldEditing(_ sender: UITextField) {
model.input = sender.text
}
func buttonAddTapped(_ sender: UIButton) {
if let name = model.input, name.characters.count > 0 {
let person = Person()
person.name = name
model.addPerson(person)
model.input = nil
// Also save data to CoreData if you want to retrieve them again later
// saveData()
}
tableView.reloadData()
}
}
2)定义单元格:包括输入单元格或Person单元格(如果需要)。创建新类时,请检查"还要创建XIB文件"也是连接和用户界面。
class InputTableViewCell: UITableViewCell {
@IBOutlet weak var textField: UITextField!
@IBOutlet weak var buttonAdd: UIButton!
}
3)定义视图模型:
class ViewModel {
var persons: [Person]?
var input: String?
func addPerson(_ person: Person) {
if persons == nil { persons = [] }
persons?.append(person)
}
}
4)定义模型:
class Person {
var name: String?
}
答案 1 :(得分:0)
<强>型号:强>
您需要一个数据库或核心数据。
我将CD分离出来,因为在IT的某些角落,它被认为更像是一个&#34;模型&#34;使用mySQL数据库或后面的XML文件。就像任何可供讨论的人一样,CD有它的优点和缺点。许多人认为实施后扩展事物的最大弱点之一就是。
如果应用程序在不同视图中使用多个数据保持结构(使用不同的视图控制器)变得越来越精细怎么办?
对我来说,这是Model的关键,这意味着一个简单的SQL(或关系型)数据库。如果你不知道我对关系的意思,请查阅,花几天时间学习它。 (提示:当你谈论一个&#34; person class&#34;。模型(看我在那里做了什么?)你的类匹配 - 通过名称,类型和属性 - 你的数据库表时,你已经在那里了。 1:1你可以做得越好。
但请记住可扩展性和层级(模型,视图,控制器)。 Swift计算了属性。如果你在查询类似于&#34;有多少人住在欧洲&#34;你最好使用SQL - 它使数据通过管道清洁器,并且表现更好。但是,如果你想展示类似于&#34; John Doe生日那天多少天&#34;你可能最好在控制器方面做一个计算属性或一个可调用函数。
您还想决定本地或云端。 Facebook显然在云中拥有一个数据库。但我的第三方播客应用程序(不是Overcast BTW)有一个本地数据库。
查看:强>
你似乎对此有了很好的把握。 Xcode在大多数情况下都很好地坚持使用MVC。如果您能够完全坚持使用Interface Builder,那么您已经完成了这项工作。
但有些程序员(像我一样)无法做到这一点。对于所有Apple在自动布局限制方面都做得很好,他们做出一些决定我并不知道背后的推理 - 比如iPad上的所有方向(不包括分屏或滑出时使用)目前正常尺寸。我的应用程序需要将UISlider控件从底部(纵向)移动到右侧(横向),以最大化我的GLKView的屏幕空间。这意味着代码至少有一些东西(方向变化和超视角界限)。由于IB无法在设计时处理代码,因此我决定将所有子视图移动到代码中并消除IB。我对Xcode 8充满希望,我可以使用IB,在玩了两个新的IB之后,我意识到它还不值得 - 我需要约束数组来激活/取消基于superview界限。
长话短说:IB运作良好,尽可能多地使用它。但请记住它的局限性,并且在必要时不要害怕放入视图层的代码中。
<强>控制器:强>
首先,请记住,一旦删除&#34;模型&#34;和&#34;查看&#34;来自事物,一切,左边是&#34;控制器&#34;。
当然。当然!您的视图控制器需要在其视图(和子视图)中显示数据。它还需要处理来自用户的操作,例如按钮按下滑块更改等。但是从数据库中检索数据呢?如何从第三方Web服务中检索价格或税务信息?或者对你来说,如何在UITableView中创建人员列表(联系人?)?
如果你把所有这些都放到你的视图控制器中祝贺!您刚刚了解了UIViewController&#34; cruft&#34;。我们都做到了这一点 - 它是学习Xcode MVC方式的一部分。它是一种科学的东西,也是一种了解什么有效的艺术。 (虽然它主要经历过。)
随着您的应用程序的增长,您肯定会拥有更多的UIViewControllers。您可能还有其他类,如Person,Country等。最终,您将开始创建各种类的扩展,并可能为您的类创建协议。现在,快速提问:你如何保持这些有条理的东西?单独的文件,组,什么?您可能会发现框架目标最有效。 (如果您打算使用Apple的许多应用扩展程序,那么您将会这样做。)
也许比确定你的&#34;模型更重要&#34;在编码之前,你的&#34;控制器&#34;组织。