有关如何在视图控制器之间导航的基本问题。说我有VC" A"和VC" B"都嵌入在导航控制器中。从A到B,我使用了一个segue。在我到达B之后,我点击一个按钮进行一些视觉上的改变,比如按钮的颜色。然后我点击导航控制器的后退按钮取消,然后返回A.然后我再次使用segue转到B,我得到一个新的VC" B" - 没有新的按钮颜色。我想这就是segues的工作方式。
但是,如何使用新的按钮颜色获得相同的VC B?
我的hack是保存VC B的实例变量(在VC A&#39的类中),并使用navigationController.pushViewController()导航到它。测试证实我的按钮颜色更改仍然在B的调用之间。但是这个解决方案感觉笨拙和hacky。
所以,在我充实这个代码之前,我需要问一下:有没有设计模式可以进行A-> B-> A-> B而不是第二次获得新的B?什么是首选方法?
答案 0 :(得分:3)
当您按下以查看控制器B时,会创建一个B实例,这就是您要推送的实例。当您回弹以查看控制器A时,视图控制器B的该实例被取消初始化,永远消失。当您回到视图控制器B时,您将创建一个新实例。因此,要使按钮的颜色保持不变,您需要保留视图控制器B的状态,以便其所有实例都能反映该更改。保留州有多种方法,您选择的方案将由项目和个人偏好决定。
答案 1 :(得分:1)
UINavigationController
释放弹出的视图控制器(VC B),因此当您尝试再次推送VC B时,会创建一个新实例。 除非您在VC A中保留对VC B的强引用。不建议这样做但VC A仍保留在导航堆栈中,因此如果它保留对VC B的引用,则该实例可以被推回。
推荐的方法是在弹出VC B时获取要维护的状态,并在推送新的VC B实例时将其设置回来。
解决方案1(不推荐):
class VCA: UIViewController {
lazy var vcB: VCB = VCB()
func presentVCB() {
navigationController?.pushViewController(vcB, animated: true)
}
}
class VCB: UIViewController {
var someState: String = ""
}
解决方案2,使用授权:
class VCA: UIViewController, VCBDelegate {
// This could be any data-structure in which you can store the states in VC B
var lastVCBState: String?
func presentVCB() {
let vcB: VCB = VCB()
vcB.delegate = self
lastVCBState != nil ? vcB.someState = lastVCBState! : ()
navigationController?.pushViewController(vcB, animated: true)
}
// MARK: VCBDelegate
func didPopWith(state: String) {
lastVCBState = state
}
}
protocol VCBDelegate: class {
func didPopWith(state: String)
}
class VCB: UIViewController {
weak var delegate: VCBDelegate?
// Any data-structure in which you can store the states
var someState: String = ""
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
delegate?.didPopWith(state: someState)
}
}
答案 2 :(得分:1)
Step1:当您更改底部的颜色时,请以任何持久的方式保存它。 例如Singleton Class或NSUserDefaults。
第2步:在VCB中加载已保存的颜色。
使用Singleton类的示例:
class VCB: UIViewController {
@IBOutlet weak var myButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
self.myButton.backgroundColor = UIHelper.sharedInstance.VCBButtonColor
}
@IBAction func changeColorButtonAction(_ sender: UIButton) {
//Save in the color in singleton class
UIHelper.sharedInstance.VCBButtonColor = UIColor.green
}
}
//Singleton Class
class UIHelper: NSObject {
var VCBButtonColor = UIColor.red
static let sharedInstance = UIHelperClass()
override init() {
...
}
}
注意:当您使用单例类并杀死应用程序时,您丢失了已保存的颜色。
使用用户默认值的示例:
class VCB: UIViewController {
@IBOutlet weak var myButton: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
if let savedColor = UserDefaults.standard.color(forKey: "SavedColor") {
self.myButton.backgroundColor = savedColor
}
}
@IBAction func changeColorButtonAction(_ sender: UIButton) {
UserDefaults.standard.set(color: UIColor.red, forKey: "SavedColor")
}
}
extension UserDefaults {
func color(forKey key: String) -> UIColor? {
var color: UIColor?
if let colorData = data(forKey: key) {
color = NSKeyedUnarchiver.unarchiveObject(with: colorData) as? UIColor
}
return color
}
func set(color: UIColor?, forKey key: String) {
var colorData: NSData?
if let color = color {
colorData = NSKeyedArchiver.archivedData(withRootObject: color) as NSData?
}
set(colorData, forKey: key)
}
}
答案 3 :(得分:0)
可以使用“ navigationController”作为入口点在viewController之间进行选择,您可以从中选择到根VCA,然后到VCB。在这种情况下,会保留VC的所有状态(但我认为是陀螺仪和加速度计)。在我所有的应用程序中都可以正常工作,甚至那些使用场景动画的应用程序:-)
亚历克斯