2015-05-19 5 views
6

У меня есть быстрый протокол, который содержит одно свойство:Swift понижающее приведение и протокольные переменные

protocol WireframeProtocol: class 
{ 
    var rootViewController: UIViewController { get } 
} 

я тогда класс, который реализует этот протокол как таковой:

class MenuWireframe : WireframeProtocol 
{ 
    let rootViewController: UIViewController 

    init() 
    { 
     self.rootViewController = MenuViewController(nibName: "MenuViewController", bundle: nil) 
     (self.rootViewController as! MenuViewController).presenter = MenuPresenter(interactor: MenuInteractor()) 
    } 
} 

В моем каркасном классе переменной фактически является типом MenuViewController, но вместо этого он должен быть объявлен как UIViewController для подтверждения протокола. Я должен использовать (self.rootViewController as! MenuViewController), чтобы понизить его до нужного класса, который я хочу, чтобы иметь доступ к его свойствам. Это хорошо в моем простом примере выше, но не очень читаемо, особенно в более сложных ситуациях. Есть ли лучший способ объявить переменную протокола?

Большое спасибо!

+1

Поскольку вы используете VIPER, вы можете/должны объявить RootViewController как протокол (Вид протокол), а также определить слабое свойство там, который будет ведущей , –

+0

Привет, Даниэль, это правда, но это дело для другой цели. Я хочу иметь протокол, который соответствует каждому каркасу, который предоставляет UIViewController, который я могу использовать для целей навигации. Я полагаю, что я мог бы использовать этот протокол просмотра для этого, если протокол для UIViewControllers только ... ммм. Я проверю это и вернусь к вам. – bennythemink

+0

@bennythemink, вы проверили мой ответ? –

ответ

3

Да, есть лучший путь и то, используя общие протоколы. Для реализации, что вы должны объявить ваш протокол, подобный как это:

protocol WireframeProtocol{ 

    typealias RootViewController : UIViewController 
    var rootViewController: RootViewController { get } 

} 

затем в своем классе принятие установленного типа RootViewController в MenuViewController

class MenuWireframe : WireframeProtocol{ 

let rootViewController: MenuViewController 

    init(){ 
     self.rootViewController = MenuViewController(nibName: "MenuViewController", bundle: nil) 
     self.rootViewController.presenter = MenuPresenter(interactor: MenuInteractor()) 
    } 
} 
+0

Привет, zellb, это работает!Но я не совсем уверен, почему это происходит. Вы можете объяснить это мне, пожалуйста? – bennythemink

+1

Типичные псевдонимы определяют альтернативное имя для существующего типа, поэтому в этом случае я объявил новое имя для всех типов, наследуемых от UIViewController (в строке 'typealias RootViewController: UIViewController'). После этого я устанавливаю тип rootViewController для нашего нового типа, поэтому rootViewController var может содержать любое значение, созданное из классов, унаследованных от UIViewController, поэтому теперь вы можете установить его непосредственно как MenuViewController без каких-либо требований к кастомизации. Надеюсь, я был чист. –

+0

Отлично, спасибо Zellb. Это имеет смысл для меня сейчас :) – bennythemink

1

ли вы попробовать это:

protocol WireframeProtocol: UIViewController { 
    var rootViewController: UIViewController { get } 
} 

class MenuWireframe : WireframeProtocol 
{ 
    let rootViewController: WireframeProtocol 

    init() 
    { 
     //... 
    } 
} 
+0

Привет, я получаю «неклассический тип WireframeProtocol не может наследовать от класса UIViewController»:/Не будет работать так, как я боюсь. Спасибо за ваше предложение – bennythemink

+0

Да, я указал на отсутствие в начале Swift в проекте. В Objective-C мы могли бы сделать что-то вроде 'UIViewController * rootViewController;' ... –

2

Если вы можете изменить объявление протокола, ответ использовать @ zelb в. Если вы не можете, вы могли бы сделать что-то вроде:

class MenuWireframe : WireframeProtocol 
{ 
    var rootViewController: UIViewController { 
     return menuViewController 
    } 

    let menuViewController: MenuViewController! 

    init() 
    { 
     menuViewController = MenuViewController(...) 
     //... 
    } 
} 
+0

Привет, спасибо за ваше предложение. Я просто тестировал его, и это не работает, я боюсь. Во-первых, я не могу использовать «let» с этим подходом, а во-вторых, мне все равно придется бросать rootViewController для ввода MenuViewController, если я хочу получить доступ к его свойствам :(но спасибо за ваше предложение. – bennythemink

+0

@bennythemink Почему вы не могли использовать «let»? идея заключается в доступе к 'menuViewController' вместо' rootViewController', где вы знаете, что данный объект на самом деле 'MenuWireFrame' не произвольный' WireFrameProtocol' –

+0

Привет, я не могу использовать «let», поскольку rootViewController теперь является вычисленным свойством в вашем предложении. может быть педантичным, но теперь это также означает, что у меня есть два свойства вместо одного в классе. Но еще раз спасибо за подсказку. – bennythemink

Смежные вопросы