2015-04-28 6 views
3

Для моего проекта я должен создать прокси AppDelegate, который переадресует вызовы другому AppDelegate.Swift Необязательный необязательный

UIApplicationDelegate havs a var window: UIWindow?. Мой вопрос, почему я не могу это сделать:

private lazy var realAppDelegate: UIApplicationDelegate = { 
    return AppDelegate() 
}() 

var window: UIWindow? { 
    get { 
     return realAppDelegate.window 
    } 
    set { 
     realAppDelegate.window = newValue 
    } 
} 

Проблема с этим кодом является то, что realAppDelegate.window является UIWindow??.

Кто-нибудь знает почему?

+0

Некоторые больше информации о вложенных дополнительных опциях: [Swift в блоге] (https://developer.apple.com/swift/blog/?id=12) и [связанный вопрос] (http://stackoverflow.com/questions/27225232/two-or-more-optionals-in-swift/27226589 # 27226589) – vrwim

+0

Связанный: http://stackoverflow.com/questions/25175544/uiwindow-does-not-have-member-named-bounds, http://stackoverflow.com/questions/28901893/why-is- главное окно-оф-типа двойного необязательный. –

ответ

7

Свойство window из UIApplicationDelegate протокола объявляется следующим образом:

optional var window: UIWindow? { get set } 

Это означает, что это необязательное свойство (в том смысле, что «класс, реализующий UIApplicationDelegate протокол не предлагается реализовать/иметь это свойство ", как если у вас есть @optional в Objective-C), и это свойство имеет дополнительный типOptional<UIWindow> (или UIWindow?).

Именно поэтому у вас есть двойной необязательный тип, в конце концов, потому что window свойство может или не может быть реализован в realDelegate, и если да, то это будет сам тип Optional<UIWindow>/UIWindow?.


Поэтому в основном то, что вы хотите, чтобы вернуть window свойство вашего realAppDelegate ... только если realAppDelegate решил объявить, что собственность сама (что она не требует, чтобы сделать, так как это optional var).

  • Если realAppDelegate не реализовывали window себя, вы, вероятно, намерены вернуть nilUIWindow? в результате.
  • Если ваш realAppDelegate действительно реализовал свойство window, тогда вам необходимо вернуть его как есть (пусть эта реализация возвращает фактический UIWindow или nil).

Самый простой способ сделать это - использовать оператор ниль-коалесценции ?? в Swift. a ?? b означает, что «если a не является ником, то возвращает a, но если a равно nil, верните b» (где, если a имеет тип T?, тогда ожидается, что все выражение вернет объект типа T, где в вашем случай T - это тип UIWindow?).

var window: UIWindow? { 
    get { 
     // If realAppDelegate.window (of type UIWindow??) is not implemented 
     // then return nil. Otherwise, return its value (of type UIWindow?) 
     return realAppDelegate.window ?? nil 
     // That code is equivalent (but more concise) to this kind of code: 
     // if let w = realAppDelegate.window { return w } else return nil 
    } 
    ... 
} 

Для реализации сеттер, это еще одна проблема. Согласно this SO answer, прямой доступ к установщику необязательного свойства протокола не представляется возможным. Но вы можете себе представить, хак, чтобы обойти это, объявив другой протокол, который делает это требование window свойства является обязательным, а затем попытаться бросить ему в инкубаторе:

@objc protocol UIApplicationDelegateWithWindow : UIApplicationDelegate { 
    var window: UIWindow? { get set } 
} 

class AppDelegateWrapper : UIApplicationDelegate { 
    ... 
    var window: UIWindow? { 
     get { 
      return realAppDelegate.window ?? nil 
     } 
     set { 
      if let realAppDelWithWindow = realAppDelegate as? UIApplicationDelegateWithWindow 
      { 
       // Cast succeeded, so the 'window' property exists and is now accessible 
       realAppDelWithWindow.window = newValue 
      } 
     } 
    } 
... 
} 
+0

Очень ясно, спасибо! – delannoyk

+1

Можете ли вы расширить свой ответ, чтобы показать, как вы будете реализовывать 'set {...}'? –

+0

Это на самом деле очень хороший вопрос ... и я боюсь, что это невозможно в Swift (пока?) В соответствии с http://stackoverflow.com/questions/26083377/swift-setting-an-optional-property-of-a- протокол: -/ – AliSoftware

1

Декларация собственности

optional var window: UIWindow? { get set } 

optional в начале означает, что свойство не должно быть там вообще, это второй ?.

UIApplicationDelegate - это протокол, класс, который его реализует, не должен реализовывать все.

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