IOS - як програматизувати програмно за допомогою швидкого переходу


185

Я створюю додаток, який використовує SDK Facebook для аутентифікації користувачів. Я намагаюся закріпити логіку 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???
        }
    }
}

Я використовую вищевказаний метод класу для перевірки змін стану сеансу, і він працює добре.

Питання: Як тільки я отримаю дані користувача, як я можу перейти до наступного перегляду з цього спеціального класу?

EDIT: просто для того, щоб було зрозуміло, у мене є segue з ідентифікатором на табло, і я намагаюся знайти спосіб виконати segue з класу, який не є контролером перегляду


2
Як performSegue:?
ВІД

Так, але код відсутній у viewController, як я можу це досягти?
Шломі Шварц

Ну, у такому випадку вам слід делегувати цю роботу (відшарування) від об'єкта, в якому ви виконуєте роботу, до контролера перегляду (через блок завершення або метод делегування).
ВІД

отримання виключення з
Chris Hayes

Відповіді:


340

Якщо ваш виразник існує у рекламній дошці з ідентифікатором segue між вашими двома видами перегляду, ви можете просто зателефонувати за допомогою програмного забезпечення:

performSegue(withIdentifier: "mySegueID", sender: nil)

Для старих версій:

performSegueWithIdentifier("mySegueID", sender: nil)

Ви також можете зробити:

presentViewController(nextViewController, animated: true, completion: nil)

Або якщо ви перебуваєте у контролері навігації:

self.navigationController?.pushViewController(nextViewController, animated: true)

7
Дякую за відповідь, як я можу викликати performSegueWithIdentifier з користувацького класу, який не є переглядом?
Шломі Шварц

2
Якщо я використовую ваш другий метод. Як передати дані до наступного перегляду?
iamprem

2
Ви б використовували функцію pripravForSegue (segue: UIStoryboardSegue, відправник: AnyObject?) Та встановлювали властивості.
Ллойд Сарджент

1
Зауважте, що при виклику performSequeWithIdentifer () буде викликана реалізація PrepaForSeque () у вашому контролері виклику, і ви можете робити різні дані, що передаються туди - адже параметр відправника, отриманий у PripravForSeque (), це просто те, що передається параметру відправника в performSequeWithIdentifier ()
тембо

1
Що робити, якщо зразка не існує в розкадровці? Наприклад, якщо ви хочете створити вираз для самого ViewController?
scaryguy

20

Ви можете використовувати NSNotification

Додайте метод публікації у свій спеціальний клас:

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)
}

1
Будь ласка, не зловживайте подібними сповіщеннями. Використовуйте делегат і зробіть з'єднання між контролером перегляду та вашим класом явним. Спостерігати контрольний потік сповіщення майже неможливо, оскільки може бути декілька підписників, а екземпляри можуть підписатися / скасувати підписку за бажанням.
uliwitness

17

Якщо ваш виразник існує у дошці розкадрівки з ідентифікатором виду між вашими двома переглядами, ви можете просто зателефонувати за допомогою програмного забезпечення

self.performSegueWithIdentifier("yourIdentifierInStoryboard", sender: self)

Якщо ви перебуваєте в контролері навігації

let viewController = YourViewController(nibName: "YourViewController", bundle: nil)        
self.navigationController?.pushViewController(viewController, animated: true)

Я порекомендую вам другий підхід за допомогою контролера навігації


self.performSegue (withIdentifier: "yourIdentifierInStoryboard", відправник: self)
Rajneesh071

14

Ви можете використовувати segue так:

self.performSegueWithIdentifier("push", sender: self)
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
    if segue.identifier == "push" {

    }
}

Дякую за відповідь, але performSegueWithIdentifier є методом viewController, і мій код працює у зовнішньому класі
Shlomi Schwartz

13

Swift 3 - також працює зі SpriteKit

Ви можете використовувати NSNotification .

Приклад:

1.) Створіть segue у дошці розкадрування та назвіть ідентифікатор "segue"

2.) Створіть функцію в ViewController, з якого ви переходите.

func goToDifferentView() {

    self.performSegue(withIdentifier: "segue", sender: self)

}

3.) У ViewDidLoad () вашого ViewController ви переслідуєте створити спостерігача.

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 або Сцена, яку ви переглядаєте, додайте метод публікації там, де ви хочете, щоб запускати сегмент.

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)
Михайло Самойлов

3

Те, що ви хочете зробити, дійсно важливо для тестування одиниць. В основному вам потрібно створити невелику локальну функцію в контролері перегляду. Назвіть функцію що завгодно, просто включіть performSegueWithIndentifier.

func localFunc() {
    println("we asked you to do it")
    performSegueWithIdentifier("doIt", sender: self)
}

Далі змініть клас утиліти, FBManagerщоб включити ініціалізатор, який приймає аргумент функції та змінну, щоб утримувати функцію ViewController, яка виконує segue.

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 - це ваша fbsesionstatechange і UtilClassFBManager.

Для власного коду просто перейдіть localFunc(без дужок) до класу FBManager.


2

Це працювало для мене.

Перш за все, надайте контролеру перегляду у вашій рекламній дошці ідентифікатор аркуша розкадрування всередині інспектора посвідчення особи. Потім скористайтеся наступним прикладом коду (гарантуючи, що назва класу, дошки розповідей та ідентифікаційна дошка збігаються з тими, які ви використовуєте):

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 найкращі побажання


1

Це можна зробити за допомогою performSegueWithIdentifierфункції.

Знімок екрана

Синтаксис:

func performSegueWithIdentifier(identifier: String, sender: AnyObject?)

Приклад:

 performSegueWithIdentifier("homeScreenVC", sender: nil)

1

Ще один варіант - використовувати модальний segue

КРОК 1: Перейдіть до рекламної дошки та надайте Контролеру подання ідентифікатор розкадрування . Дізнатися, де можна змінити ідентифікатор розкадровки в Інспекторі посвідчень справа. Дозволяє зателефонувати ідентифікатору розкадруванняModalViewController

КРОК 2: Відкрийте контролер подання 'відправника' (назвемо його 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)
    }
  }
}

Зверніть увагу, що контролер перегляду, який ми хочемо відкрити, також називається ModalViewController

КРОК 3: Щоб закрити ModalViewController, додайте це до нього

public class ModalViewController {
   @IBAction func closeThisViewController(_ sender: Any?) {
      self.presentingViewController?.dismiss(animated: true, completion: nil)
   }
}

0

Це працювало для мене:

//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)
        }


    }
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.