2014-06-12 15 views
15
@objc(SEPushNoAnimationSegue) 
class SEPushNoAnimationSegue: UIStoryboardSegue { 
    override func perform() { 
     self.sourceViewController.navigationController.pushViewController(self.destinationViewController, animated:false) 
    } 
} 

W powyższym kodzie mam 2 pytania: 1). ma błąd kompilacji: "UINavigationController!" nie ma członka o nazwie "pushViewController"Custom Segue w Swift

Ale w tej klasie miał on metodę pushViewController.

2). Muszę dodać adnotację: @objc (SEPushNoAnimationSegue), inaczej, w storybooku rozpoznaje tylko losową nazwę, np. _tcxxxxSEPushNoAnimationSegue.

dlaczego te 2 problemy zdarzają się tutaj?

Odpowiedz

32

Issue # 1

UIStoryboardSegue ma irytującą wadę: jego sourceViewController i destinationViewController właściwości są wpisane jako AnyObject! (tak jest w przypadku nawet w Objective-C (typ Id)), a nie jako UIViewController, jak powinno być.

Ta sama wada powoduje spustoszenie w Twoim idealnym i prostym kodzie. Oto jak do przerobienia go w celu ustalenia błędy kompilacji:

@objc(SEPushNoAnimationSegue) 
class SEPushNoAnimationSegue: UIStoryboardSegue { 
    override func perform() { 
     let src = self.sourceViewController as UIViewController 
     let dst = self.destinationViewController as UIViewController 
     src.navigationController.pushViewController(dst, animated:false) 
    } 
} 

UWAGA: Jabłko stałe tę rzecz w iOS 9. sourceViewController i destinationViewController są teraz poprawnie zadeklarowane jako UIViewController.

Issue # 2

Swift kompilator przechowuje symbole za pomocą własnych name mangling i dobre ol”Objective-C nie rozpoznaje go w Xcode. Użycie jawnego @obj() rozwiązuje problem.

+0

mam to: Nie można rozpakować Optional.None – fabian

+4

wyraźny @objc() - świetna sugestia - właśnie to dla mnie zrobiła – FiddleMeRagged

+1

Konwencja o szybkiej nazwie ma na celu unikanie konfliktów z innymi importami. – Karsten

5

Działa to dobrze dla mnie

@objc(SEPushNoAnimationSegue) class SEPushNoAnimationSegue: UIStoryboardSegue { 

override func perform() { 
    let sourceViewController = self.sourceViewController as UIViewController 
    let destinationViewController = self.destinationViewController as UIViewController 

    sourceViewController.presentViewController(destinationViewController, animated: true, completion: nil) 
} 

} 
1

Even Better:

import UIKit 

class CustomSegue: UIStoryboardSegue { 
    override func perform() { 
     self.sourceViewController.presentViewController(self.destinationViewController as UIViewController, animated: false, completion: nil) 
    } 
} 
0

Swift 3.0:

import UIKit 

class CustomNoAnimationSegue: UIStoryboardSegue { 

    override func perform() { 
     if let navigation = source.navigationController { 
      navigation.pushViewController(destination, animated: false) 
     } 
    } 
}