我正在尝试将信息从控制器 A传递到控制器B 。问题是,我想:
简明:最小化从XCode
到某些关键信息的自动完成功能。我想以简单的方式知道在将控制器推到堆栈之前所需的确切参数。
避免segues 。根据我的理解,segues在故事板中创建了很多紧密耦合。我不想依赖故事板来传递信息。 (每次我想将控制器A切换到另一个时,我都要去故事板进行一些更改)。我可能会在某些时候在几个故事板中拆分我的应用程序,并且segues可能会非常讨厌处理。
美丽:也许Swift可以提供我没想过的Swifty解决方案。
我最初想要完成的是将控制器作为协议推送。即使不可能,让我解释一下:
将控制器作为协议推送,可以让我对我的属性有确切的可见性。
没有与故事板相关的紧密耦合
许多控制器(A,C,D)可能想要推送B控制器,我可能会给他们每个人一个不同的协议来推动控制器B.也许B可能出现在不同的情况下。
首先,我的代码看起来像那样(故事板扩展工作):
if let myBCustomVC = storyboard.instanciateControllerWithIdentifier(MyBCustomVC.self) as? myVCustomFromAProtocol{
myBCustomVC.AToB = self.data.count
self.navigationController?.pushViewController(myBCustomVC, animated: true)
}
protocol myVCustomFromAProtocol {
var AToB: Int {get set}
}
问题是,我无法将视图控制器向下推送到协议。我不得不通过一个丑陋的UINavigationController
扩展来。这是完整的结果。
if let myBCustomVC = storyboard.instanciateControllerWithIdentifier(MyBCustomVC.self) as? myVCustomFromAProtocol{
myBCustomVC.AToB = self.data.count
self.navigationController?.pushViewController(vcToPush: myBCustomVC, animated: true)
}
extension UINavigationController{
func pushViewController(vcToPush: Any, animated: Bool){
if let vc = vcToPush as? UIViewController{
self.pushViewController(vc, animated: animated)
}
}
}
让我们面对现实,在实现我的前两个目标的过程中,我已经将一个Any低估了UIViewController
,这是一个很好的结果。
有没有办法避免紧耦合并以漂亮方式在堆栈上推送控制器,同时在参数上保持有限的可见性从第一视图控制器(A)传递到第二视图(B)。你的想法是什么?为什么我不想这样做?
答案 0 :(得分:2)
我会从另一侧(即你正在呈现的控制器的一侧)接近这个。
您可以执行类似创建Presenter
协议的操作。
protocol Presenter {
func present(inContext context: UIViewController)
// possibly with some data in it too (if it's across all instances)...
var count: Int {get set}
}
并且每个都有一些工厂结构...
struct BVCPresenter: Presenter {
var count: Int = 0
func present(inContext context: UIViewController) {
// create the BViewController here
let controller = ...
context.push(controller, animated: true)
}
}
或者那些东西。这实际上取决于用例和传递的数据等......
所以现在A可以做......
someGenericPresenter.present(inContext: navigationController)
通用演示者可以作为属性传递给A,也可以作为参数等传递给函数......
或其他什么。
您甚至可以创建一个“FlowController”来管理这些转换和数据......
self.flowController.presentB()
flowController
然后知道B需要什么以及如何以及在何处呈现它并用数据填充它。各个视图控制器实际上并不需要了解彼此的任何信息。
我认为没有适合所有情况的解决方案。它需要大量的思考和设计。但是有很多选择。想想你在视图控制器之间需要做什么以及从那里开始工作。
此外,不要太担心创造“正常工作”的东西,即使它不是教科书通用,“Swifty”,优雅,漂亮的代码。拥有有效的代码要比设计精美的系统好得多。
:)
答案 1 :(得分:1)
在Fogmeister的帮助下,我想出了这个答案。与使用从协议继承的Presenter对象相比,它有几个优点和缺点。
解决方案:使用位于控制器中的静态工厂方法(或几个用户的方法)进行实例化。
<强>优点强>:
<强>缺点强>:
这是我班上当前的实现:
在控制器B(静态功能)中:
static func prepareController(originController: UIViewController, AToB: Int) -> bVC? {
if let bVC = originController.storyboard?.instanciateControllerWithIdentifier(self) as? bVC{
bVC.AToB = AToB
return bVC
}
else{
return nil
}
}
在控制器A中(将控制器推到堆栈上):
if let bVC = bVC(originController: self, AToB: *someValue*){
self.navigationController?.pushViewController(bVC, animated: true)
}
解决方案必须采取一些盐,让我知道你的想法@Fogmeister?
两种解决方案都可以结合使用。使用 protocoled结构,它将使用控制器提供的静态方法。问题是,对于您引入项目的人来说,它很快就会变得过于复杂。这就是为什么我现在坚持我的解决方案的原因。我正在研究依赖注入的框架。