Interface Builder (IB) 只是一个用于程序开发的 GUI。您在 IB 中可以做的任何事情都绝对可以通过编程方式完成,但并非所有您可以通过编程方式在 IB 中完成的事情,因为 IB 只是用于界面构建——而且只是一些界面构建,而不是全部。
segue 只是 IB 术语。在 iOS 中,您只能以三种方式显示视图控制器:push(通过UINavigationController)、present(通过演示对象供应商UIViewControllerTransitioningDelegate)或show(一种更通用的显示视图的方法控制器)。
由于您不熟悉程序化 iOS 开发(最好的一种,IMO),所以快速 101:
class ProgrammaticViewController: UIViewController {
override func loadView() {
// do not call super.loadView()
// most IB developers don't even know this method exists
// because this is where IB does its work
// add all of your view objects here (scroll views,
// table views, buttons, everything)
setView()
addTableView()
...
}
override func viewDidLoad() {
super.viewDidLoad()
// do call super.viewDidLoad(), however
// do your post-view setup here, like adding observers
// or fetching data
// this method is called after the entire view
// has been loaded into memory so consider that
}
// other lifecycle events that come after viewDidLoad where you
// can perform last-second work include viewDidLayoutSubviews(),
// viewWillAppear(), viewDidAppear(), etc.
deinit {
// do any cleanup here like deactivating timers, removing
// observers, etc.
}
// MARK: Methods
func setView() {
// if you're creating your view controller programmatically,
// you must create the view controller's actual view property
// and it must be done before adding any subviews to the
// view controller's view
view = UIView()
view.frame = UIScreen.main.bounds
view.backgroundColor = UIColor.white
}
}
如果您使用自动布局(并且您可能应该这样做),您并不总是需要使用view.frame = UIScreen.main.bounds 显式设置视图的框架。如果它是应用程序的根视图控制器,则不需要它——窗口拥有该视图控制器,它会设置框架。如果您随后将UINavigationController 放在根目录中并且您正在使用自动布局,那么您推送的所有视图控制器都不需要它们的框架集。因此,您需要使用view.frame = UIScreen.main.bounds 之类的东西显式设置视图框架的唯一实时是当您以模态方式呈现视图控制器时。这是因为模态呈现的视图控制器不属于窗口或导航控制器;它暂时存在于瞬态容器视图中。在这种情况下,您必须设置它的框架。
以编程方式传递数据比 IB 开发人员更简单。只需实例化一个视图控制器,用一个值注入它的一个(非私有)属性,然后推送、呈现或显示它。以下是 UITableView 代表 didSelectRowAt 的样子:
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
let p = indexPath.row
let detailViewController = SomeDetailViewController()
detailViewController.someProperty = searchResults[p]
navigationController?.pushViewController(detailViewController, animated: true)
}
这显然是可行的,因为您已经在该视图控制器中创建了该属性,并且没有给它一个私有访问修饰符。
class SomeDetailViewController: UIViewController {
var dataObject: SomeType? // injectable
private var notInjectable: SomeType?
}
更新: 就 Apple 而言,IB 显然不是 iOS 开发的未来,因为 SwiftUI 的引入是另一种以编程方式开发 iOS 的方式。就个人而言,我讨厌 GUI 编程,我很高兴看到它慢慢被淘汰。