如何使用 Swift 在 iOS 中以编程方式进行 segue
Posted
技术标签:
【中文标题】如何使用 Swift 在 iOS 中以编程方式进行 segue【英文标题】:How to segue programmatically in iOS using Swift 【发布时间】:2015-02-20 15:23:07 【问题描述】:我正在创建一个使用 Facebook SDK 对用户进行身份验证的应用。我正在尝试将 facebook 逻辑合并到一个单独的类中。这是代码(为简单起见,已删除):
import Foundation
class FBManager
class func fbSessionStateChane(fbSession:FBSession!, fbSessionState:FBSessionState, error:NSError?)
//... handling all session states
FBRequestConnection.startForMeWithCompletionHandler (conn: FBRequestConnection!, result: AnyObject!, error: NSError!) -> Void in
println("Logged in user: \n\(result)");
let storyboard = UIStoryboard(name: "Main", bundle: NSBundle.mainBundle())
let loggedInView: UserViewController = storyboard.instantiateViewControllerWithIdentifier("loggedInView") as UserViewController
loggedInView.result = result;
//todo: segue to the next view???
我正在使用上面的类方法来检查会话状态的变化,它工作正常。
问:获得用户数据后,如何从这个自定义类中转到下一个视图?
为了清楚起见,我在情节提要上有一个带标识符的转场,我正在尝试找到一种方法来从不是视图控制器的类中执行转场
【问题讨论】:
喜欢performSegue:
?
是的,但是代码不在viewController中,我怎样才能做到这一点?
好吧,在这种情况下,您应该将工作(转场)从您执行工作的对象委托给视图控制器(通过完成块或委托方法)。
获得非零布局异常
【参考方案1】:
如果您的 segue 存在于故事板中,并且您的两个视图之间有一个 segue 标识符,您可以使用以下方式以编程方式调用它:
performSegue(withIdentifier: "mySegueID", sender: nil)
对于旧版本:
performSegueWithIdentifier("mySegueID", sender: nil)
你也可以这样做:
presentViewController(nextViewController, animated: true, completion: nil)
或者如果您在导航控制器中:
self.navigationController?.pushViewController(nextViewController, animated: true)
【讨论】:
感谢您的回复,如何从不是视图的自定义类中调用 performSegueWithIdentifier? 如果我使用你的第二种方法。如何将数据传递给下一个视图? 您将使用 func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) 并设置属性。 注意在调用 performSequeWithIdentifer() 时,调用控制器中的 prepareForSeque() 实现将被调用,您可以在那里传递各种数据 - 实际上,prepareForSeque() 中接收到的 sender 参数很简单performSequeWithIdentifier() 中传递给 sender 参数的内容 如果故事板中不存在segue怎么办?例如,如果你想为 ViewController 本身创建一个 segue?【参考方案2】:如果您的 segue 存在于故事板中,并且您的两个视图之间有一个 segue 标识符,您可以使用编程方式调用它
self.performSegueWithIdentifier("yourIdentifierInStoryboard", sender: self)
如果你在导航控制器中
let viewController = YourViewController(nibName: "YourViewController", bundle: nil)
self.navigationController?.pushViewController(viewController, animated: true)
我会推荐你使用导航控制器的第二种方法。
【讨论】:
self.performSegue(withIdentifier: "yourIdentifierInStoryboard", sender: self)【参考方案3】:您可以使用 NSNotification
在你的自定义类中添加一个 post 方法:
NSNotificationCenter.defaultCenter().postNotificationName("NotificationIdentifier", object: nil)
在你的 ViewController 中添加一个观察者:
NSNotificationCenter.defaultCenter().addObserver(self, selector: "methodOFReceivedNotication:", name:"NotificationIdentifier", object: nil)
在你的 ViewController 中添加函数:
func methodOFReceivedNotication(notification: NSNotification)
self.performSegueWithIdentifier("yourIdentifierInStoryboard", sender: self)
【讨论】:
请不要滥用这样的通知。使用委托并使视图控制器和您的类之间的连接显式。观察通知的控制流程几乎是不可能的,因为可能有多个订阅者,并且实例可以随意订阅/取消订阅。【参考方案4】:你可以像这样使用segue:
self.performSegueWithIdentifier("push", sender: self)
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!)
if segue.identifier == "push"
【讨论】:
感谢回复,但是 performSegueWithIdentifier 是 viewController 方法,我的代码在外部类中运行【参考方案5】:Swift 3 - 也适用于 SpriteKit
您可以使用 NSNotification。
示例:
1.) 在情节提要中创建一个转场并将标识符命名为“转场”
2.) 在您要从中进行切换的 ViewController 中创建一个函数。
func goToDifferentView()
self.performSegue(withIdentifier: "segue", sender: self)
3.) 在您的 ViewController 的 ViewDidLoad() 中,您正在创建观察者。
NotificationCenter.default.addObserver(self, selector: #selector(goToDifferentView), name: "segue" as NSNotification.Name, object: nil)
更新 -
上次我使用它时,我不得不将 .addObserver
调用更改为以下代码以消除错误。
NotificationCenter.default.addObserver(self, selector: #selector(goToDifferentView), name: NSNotification.Name(rawValue: "segue"), object: nil)
4.) 在您要转场的 ViewController 或场景中,在您希望触发转场的任何位置添加 Post 方法。
NotificationCenter.default.post(name: "segue" as NSNotification.Name, object: nil)
更新 -
上次我使用它时,我不得不将 .post
调用更改为以下代码以消除错误。
NotificationCenter.default.post(NSNotification(name: NSNotification.Name(rawValue: "segue"), object: nil) as Notification)
【讨论】:
斯威夫特 3:NotificationCenter.default.addObserver(self, selector: #selector(goToDifferentView), name: NSNotification.Name(rawValue: "segue"), object: nil)
【参考方案6】:
您想要做的事情对于单元测试非常重要。基本上你需要在视图控制器中创建一个小的本地函数。将函数命名为任何名称,只需包含 performSegueWithIndentifier
。
func localFunc()
println("we asked you to do it")
performSegueWithIdentifier("doIt", sender: self)
接下来更改您的实用程序类 FBManager
以包含一个初始化程序,该初始化程序接受一个函数的参数和一个变量来保存执行 segue 的 ViewController 的函数。
public class UtilClass
var yourFunction : () -> ()
init (someFunction: () -> ())
self.yourFunction = someFunction
println("initialized UtilClass")
public convenience init()
func dummyLog () -> ()
println("no action passed")
self.init(dummyLog)
public func doThatThing() -> ()
// the facebook login function
println("now execute passed function")
self.yourFunction()
println("did that thing")
(方便的 init 允许您在不执行 segue 的情况下在单元测试中使用它。)
最后,如果你有 //todo: 继续下一个视图???
self.yourFunction()
在您的单元测试中,您可以简单地调用它:
let f = UtilClass()
f.doThatThing()
其中 doThatThing 是您的 fbsessionstatechange,UtilClass
是 FBManager。
对于您的实际代码,只需将 localFunc
(无括号)传递给 FBManager 类。
【讨论】:
【参考方案7】:这对我有用。
首先,在身份检查器中为情节提要中的视图控制器提供情节提要 ID。然后使用以下示例代码(确保类、故事板名称和故事板 ID 与您使用的匹配):
let viewController:
UIViewController = UIStoryboard(
name: "Main", bundle: nil
).instantiateViewControllerWithIdentifier("ViewController") as UIViewController
// .instantiatViewControllerWithIdentifier() returns AnyObject!
// this must be downcast to utilize it
self.presentViewController(viewController, animated: false, completion: nil)
更多详情见http://sketchytech.blogspot.com/2012/11/instantiate-view-controller-using.html 最好的祝福
【讨论】:
【参考方案8】:上面已经有很好的答案了,我想在执行 segue 之前将重点放在准备工作上。
override func prepare(for segue: UIStoryboardSegue, sender: Any?)
if segue.destination is YourDestinationVC
let vc = segue.destination as? YourDestinationVC
// "label" and "friends" are part of destinationVC
vc?.label = "someText"
vc?.friends = ["John","Mike","Garry"]
一旦你完成了你想要传递给你的destinationVC的数据,然后在适当的地方执行你的segue。 您可以在 StoryBoard ID 字段的 StoryBoard Identity 检查器中设置“IdentifierOfDestinationVC”
performSegue(withIdentifier: "IdentifierOfDestinationVC", sender: nil)
【讨论】:
【参考方案9】:你可以使用performSegueWithIdentifier
函数来做这件事。
语法:
func performSegueWithIdentifier(identifier: String, sender: AnyObject?)
示例:
performSegueWithIdentifier("homeScreenVC", sender: nil)
【讨论】:
【参考方案10】:另一种选择是使用模态转场
第 1 步:转到情节提要,并为视图控制器提供一个情节提要 ID。您可以在右侧的 Identity Inspector 中找到更改情节提要 ID 的位置。
让我们调用storyboard ID ModalViewController
第 2 步:打开 'sender' 视图控制器(我们称之为 ViewController
)并将此代码添加到其中
public class ViewController
override func viewDidLoad()
showModalView()
func showModalView()
if let mvc = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "ModalViewController") as? ModalViewController
self.present(mvc, animated: true, completion: nil)
注意我们要打开的View Controller也叫ModalViewController
第 3 步:要关闭 ModalViewController,请将其添加到其中
public class ModalViewController
@IBAction func closeThisViewController(_ sender: Any?)
self.presentingViewController?.dismiss(animated: true, completion: nil)
【讨论】:
【参考方案11】:这对我有用:
//Button method example
@IBAction func LogOutPressed(_ sender: UIBarButtonItem)
do
try Auth.auth().signOut()
navigationController?.popToRootViewController(animated: true)
catch let signOutError as NSError
print ("Error signing out: %@", signOutError)
【讨论】:
以上是关于如何使用 Swift 在 iOS 中以编程方式进行 segue的主要内容,如果未能解决你的问题,请参考以下文章
如何在ios swift中以编程方式创建自动布局等宽度约束?
在 iOS Swift 3 中以编程方式添加 Web 视图时如何在 UIWebView 中获取响应状态代码?
如何在 ios swift 中以编程方式将情节提要视图控制器加载到标签栏控制器中?
在 iOS 10 + Swift 3 中以编程方式在我的 WKWebView 上方添加 UILabel