Подтвердить что ты не робот

Почему главное окно типа double optional?

При доступе к главному окну UIapplication's он возвращается как UIWindow??

let view = UIApplication.sharedApplication().delegate?.window // view:UIWindow??

Почему он возвращается как двойной необязательный и что это значит, и если он помещается в if let, я должен добавить один ! после него?

if let view = UIApplication.sharedApplication().delegate?.window!

В первую очередь я решил заменить ? на ! после делегирования, но это не было решением.

4b9b3361

Ответ 1

@matt имеет детали, но есть (несколько ужасное, несколько потрясающее) обходное решение. (См. Ниже, ниже)

let window = app.delegate?.window??.`self`()

Я оставлю понимание этой строки кода в качестве упражнения для читателя.

Хорошо, я лежу, давайте сломаем его.

app.delegate?.window

Хорошо, пока все хорошо. На данный момент мы имеем UIWindow??, который дает нам головную боль (и я считаю, что ошибка в Swift отключается между Swift и Cocoa). Мы хотим развалить его дважды. Мы можем сделать это с опциональной цепочкой (?.), но это разворачивается и перезаписывается, поэтому мы вернулись туда, откуда мы начали. Вы можете удвоить-необязательно-цепочку, однако, с ??., которая причудлива, но работает.

Это здорово, но ?? не является юридическим суффиксом. Вы должны на самом деле цепочки к чему-то. Ну, мы хотим привязать себя к себе (т.е. "Идентичность" ). Протокол NSObject дает нам метод идентификации: self.

self - это метод на NSObject, но он также является зарезервированным словом в Swift, поэтому для него синтаксис `self`()

Итак, мы получаем наше безумие выше. Делайте с ним, как хотите.

Обратите внимание, что поскольку ??. работает, вам это не требуется. Вы можете просто принять, что view есть UIWindow?? и использовать ??. на нем, как view??.frame. Это немного шумно, но, вероятно, не создает никаких реальных проблем для немногих мест, в которых это необходимо.

(*) Раньше я думал об этом как об ошибке в Swift, но не фиксировался напрямую при помощи дополнительной цепочки. Проблема в том, что опционально цепочка window отсутствует. Поэтому я не уверен, где это место для исправления. Swift может позволить postfix-? означать "сгладить", не требуя цепочки, но это кажется странным. Я предполагаю, что правильный оператор будет interrobang delegate?.window‽: D Я уверен, что это не вызовет путаницы.

EDIT:

Джозеф Лорд указал на лучшее решение (которое очень похоже на методы, которые я использовал, чтобы избежать тривиального if-let, но не думал об этом путь раньше):

let window = app.delegate?.window ?? nil // UIWindow?

Я согласен с ним в том, что это правильный ответ.

Ответ 2

Это потому, что свойство window само по себе сомневается (оно необязательно). Таким образом, вам нужен один знак вопроса, потому что может быть или не быть свойство окна, и еще один знак вопроса, поскольку возвращаемое значение этого свойства окна само по себе является необязательным. Таким образом, мы получаем опцию с двойным оберткой (как я объясняю в своем учебнике: прокрутите вниз до поля Tip, где я говорю о том, что происходит, когда необязательный свойство имеет необязательное значение).

Таким образом, один из способов выразить это будет состоять из двух этапов: один для создания (и разворачивания этого необязательного), а другой - для выбора окна (и разворачивания этого необязательного):

if let del = UIApplication.sharedApplication().delegate as? AppDelegate {
    if let view = del.window {

Теперь view является UIWindow.

Конечно, если вы уверены в своей земле (что вы, вероятно, есть), вы можете заставить бросок в первой строке и разворачиваться во второй строке. Итак, в Swift 1.2:

let del = UIApplication.sharedApplication().delegate as! AppDelegate
let view = del.window!

Ответ 3

О, двойной вариант! Иногда вы можете использовать double-bang (два восклицательных знака), но вы не можете использовать этот способ с необязательным привязкой. Итак... мой ремикс на весь другой код вызывает у вас объект UIWindow с именем window не факультативного типа:

guard let w = UIApplication.shared.delegate?.window, let window = w else { return }

Но не тратьте время и просто используйте

let window = UIApplication.shared.delegate!.window!!

и сделаем.

Ответ 4

С появлением Swift2 для меня обычным обходным путем в таких случаях является

if let _window = UIApplication.sharedApplication().delegate?.window, window = _window {
    // Some code... i.e.
    let frame = window.frame
}