Ответ 1
В Swift 4 вы можете сделать это:
let viewController: UIViewController & UISplitViewDelegate
В Objective-C для свойств может потребоваться реализация классов и дополнительных протоколов:
@property (nonatomic) UIViewController<UISplitViewDelegate> *viewController;
Возможно ли это в Swift? Из документации похоже, что вам может потребоваться только класс или протокол.
В Swift 4 вы можете сделать это:
let viewController: UIViewController & UISplitViewDelegate
В Swift существует два способа достижения этой цели:
Использование пустого протокола < phantom. Создайте пустой протокол и совместите с ним UIViewController
. Это самый "быстрый" метод, он безопасный и динамический (не требует указания класса во время компиляции).
protocol _UIViewControllerType {}
extension UIViewController: _UIViewControllerType {}
class MyClass {
weak var viewController: protocol<UISplitViewControllerDelegate, _UIViewControllerType>?
}
Вы также можете объявить typealias
для этого типа (просто чтобы уменьшить беспорядок кода).
class MyClass {
typealias ViewControllerType = protocol<UISplitViewControllerDelegate, _UIViewControllerType>
weak var viewController: ViewControllerType?
}
Использование общих ограничений. Как упоминалось fnc12 и Константин Коваль. Это безопасно, но не позволяет вам "заменять" экземпляр контроллера представления во время выполнения.
class MyClass<T: UIViewController where T: UISplitViewControllerDelegate> {
weak var viewController: T?
}
Я надеюсь, что следующий выпуск Swift добавит способ указать оба ограничения без использования протокола phantom...
typealias ViewControllerType = UIViewController: UISplitViewControllerDelegate // wish
Да, вы можете это сделать
class A < T : SomeClass where T: Comparable> {
var myProperty: T
init(t :T) {
myProperty = t
}
}
Объявить класс A
, который имеет свойство типа T. T является SomeClass
или подклассом, и он должен принять протокол Comparable
При объявлении свойства вы можете использовать протокол типа
class MyClass {
var nsobject: NSObjectProtocol
init(object : NSObjectProtocol) {
nsobject = object
}
}
// Pure Swift
protocol RandomNumberGenerator {
}
class Dice {
let generator: RandomNumberGenerator
//specify many protocols
let printer: protocol<Printable, NicePrintable>
}
Вы можете прочитать здесь
То же, что и @akashivskyy, используя пустой протокол phantom
Но здесь я делаю это как отдельный класс, который реализует это protocol - MyViewController, который может использоваться как тип для var декларация. Что упрощено в моей реализации.
@objc protocol MySplitViewControllerDelegate : NSObjectProtocol {
func controllerTitle() -> String
optional func mySplitView() // write delegates
}
class MyViewController: UIViewController, MySplitViewControllerDelegate {
func controllerTitle() -> String {
return ""
}
}
class ViewController: UIViewController {
private(set) weak var viewController: MyViewController?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
Здесь нужны дженерики.
@property (nonatomic) UIViewController<UISplitViewDelegate> *viewController;
Предположим, что класс с именем MyClass имеет свойство, называемое viewController, с типом UIViewController (или подкласса) и которое соответствует протоколу UISplitViewDelegate. В Swift ваш код будет выглядеть как
class MyClass<T:UIViewController where T:UISplitViewControllerDelegate>:NSObject{
var viewController:T?
override init(){
super.init()
//..
}
// etc..
}
Примечание
class MyClass<T:UIViewController where T:UISplitViewControllerDelegate>:NSObject
линии. Здесь вы указываете случайный тип T, но вы также указываете, что вы хотите получить T из UIViewController и соответствовать UISplitViewControllerDelegate. Это условие будет проверено во время компиляции. И вы объявляете свойство в этой строке
var viewController:T?
и укажите его тип как T. И остался один вопрос - как объявить переменную типа MyClass? Я предоставляю минимальный код из примера проекта, чтобы проиллюстрировать его более четко.
class MyClass<T:UIViewController where T:UISplitViewControllerDelegate>:NSObject{
var viewController:T?
override init(){
super.init()
//..
}
// etc..
}
class ViewController: UIViewController,UISplitViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
var a=MyClass <ViewController> ()
a.viewController=self
//..
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//..
}
Дополнительная информация здесь
Удачи вам в дженериках.