2014-09-01 5 views
3

Если функция возвращает неявно развернутую опцию, вы бы присвоили ее явным необязательным?Назначение неявно развернутого необязательного для явного необязательного

Например, в blog post Криса Адамсона он сначала перечисляет функцию, возвращающую неявно развернутую, а затем он присваивает возвращаемое значение функции явным необязательным.

class func JSONObjectWithData(_ data: NSData!, 
         options opt: NSJSONReadingOptions, 
         error error: NSErrorPointer) -> AnyObject! 

let jsonResponse : AnyObject? = 
NSJSONSerialization.JSONObjectWithData(evilData, 
    options: NSJSONReadingOptions(0), 
    error: &parseError); 

Если функция вернет то, что не может быть нулевым, зачем назначать его необязательно?

+0

В текущем (бета-6) SDK, JSONObjectWithData() возвращает 'AnyObject?'. –

+0

Спасибо Martin R, я знаю об этом - хотел использовать пример Криса, чтобы выяснить, почему он назначил неявное явное. – Boon

+1

Раздел в примечаниях к выпуску бета-версии, начиная с * «Большое количество API-интерфейсов Foundation проверено для дополнительного соответствия ...» * также интересно в этом контексте. –

ответ

3

В этом конкретном случае возврат AnyObject! является ошибкой в ​​SDK (технически это просто место, где они использовали авто-Swiftifier и еще не зафиксировали его вручную). JSONObjectWithData совершенно можно вернуть nil. Из документов:

Возвращаемое значение: объект фундаментной из данных JSON в данных, или нулевыми, если произошла ошибка.

Крис спасает это значение от возможного сбоя, переместив его на явный необязательный, а не на неявный, который фактически может быть ni.

+0

Спасибо, Роб. Итак, в нормальном состоянии, если функция объявлена ​​правильно, вам никогда не придется назначать неявно развернутую опциональную для явного, правильного? – Boon

+2

Rob, «возврат' AnyObject! 'Является ошибкой ... [потому что этот метод] абсолютно может возвращать' nil'. " Хотя это может быть лучший дизайн для возврата 'AnyObject? ', Я не уверен, что я бы охарактеризовал это как« ошибку ». «AnyObject!» - это неявно разворачиваемый необязательный параметр и, как таковой, может быть «nil» (на самом деле он имеет смысл только в том контексте, где возвращаемое значение _could_ будет «nil»). Поэтому тот факт, что возвращаемое значение может быть «nil», не является несовместимым с типом возвращаемого типа «AnyObject!». Возможно, я не понимаю вашу точку зрения ... – Rob

+2

@Rob Это технически ошибка, но вы можете думать об этом как о позиции по умолчанию, когда все существующие методы SDK получают некоторую Swififying любовь, как говорит Роб. Для * Swift *, правильный тип возврата здесь будет реальным. Необязательно, поэтому вызывающий получает подсказку, что то, что возвращается, вполне может быть нулевым. Вы действительно не можете сказать из неявно-развернутого необязательного возврата из метода SDK, может ли значение когда-либо быть нулевым или нет, поэтому в этом случае явная опция «Лучше» - это лучше «документация», если хотите. –

0

Вы должны всегда использовать этот подход, когда вы можете изменить Implicit Unwrapped Optional к Optional Type возвращенного API, как и Xcode релизы в будущем будет пытаться заменить их API, из Implicit Optionals type в explicit optional и в бета-версии 6 и 5 этот подход начал и многие интерфейсы API был изменен для использования типа explicit optional. Экспертная рекомендация - избегать Implicit Unwrapped Optional, когда это возможно, потому что вы получите аварийный сигнал, когда nil распакуется автоматически. Если вы используете optional(explicit), вам необходимо явно развернуть значение, чтобы сделать это, поставив условие if или если вы действительно уверены, что это будет не ноль, вы можете развернуть его без if (но вы всегда должны проверить наличие nil).

JSONObjectWithData может вернуться nil, как вы не знаете, что в evilData, и если он не в состоянии преобразовать в json вы получите значение nil и если вы пытаетесь использовать jsonResponse с implicit optional type в другом месте в коде, чем ваше приложение будет авария во время выполнения. Вот почему chris использовал explicit optional, чтобы позаботиться об этом случае и в другом месте, где использование jsonResponse не будет автоматически разворачиваться до нуля, что может привести к сбоям. Если вы разворачиваете код самостоятельно с if или optional binding, вы можете избежать краха и шоу какой-либо смысл полный сообщение.

+2

(Стилистическое примечание: обратные тики «' '» предназначены для «кода», а не для общего внимания.Пометка «каждая важная фраза» с «обратными тиками» не «улучшает» «удобочитаемость». Существуют и другие методы разметки, такие как * курсив * или ** жирный шрифт ** :) –

+0

спасибо @MartinR, я позабочусь об этом в будущем – codester

-1

Неявно развернутый необязательный параметр по-прежнему является необязательным, хотя гарантированно удерживает значение.

Назначение неявно развернутого дополнительного для обычного необязательного является законным.

Итак, если у вас есть линейная логика в приложении, где вы объявляете необязательную переменную, а затем инициализируете ее с неявным образом развернутым необязательным, было бы лучше использовать необязательный.

Но есть некоторые случаи, когда вы определяете необязательную переменную (скажем, в начале функции), а затем основываясь на условиях, потоке, и т. Д. Ему может быть присвоено значение из разных функций - если не менее один из них может вернуть нормальный факультативный, тогда вы должны объявить переменную как необязательную.

Но в этом случае, даже если все функции, используемые для назначения значения вашей необязательной/необязательной переменной, всегда возвращают либо необязательный, либо (по крайней мере один из них), неявно разворачиваемый необязательно, всегда лучше придерживаться с необязательным объявлением, потому что в будущем вы можете создать новую ветвь кода, которая возвращает нормальный вариант.

Последнее, очень интересно, это, кажется, работает хорошо:

let x: Int! = nil 

в то время как я должен признать я ожидал, что это исключение при выполнении. Зная это, я думаю, что с этого момента я всегда буду использовать опцию, когда функция заявляет, что возвращает неявно развернутую.

Больше испытаний:

func test() -> Int! { 
    return nil 
} 

let q1: Int? = test() // it works, q1 = nil (expected) 
let q2: Int! = test() // it works, q2 = nil (unexpected) 
let q3: Int = test() // runtime exception (expected) 

Update: Это то, что documentation говорит вместо этого:

Если вы пытаетесь получить доступ к неявным развернутый необязательным, если оно не содержит значения, то вызовет ошибку времени выполнения. Результат точно такой же, как если бы вы поместили восклицательный знак после обычного необязательного, который не содержит значения.

Что означает: назначение nil нормально, но как только она доступна (т.е. присваивается другой переменной, используется в выражении, и т.д.), то это вызовет ошибку

+3

Почему вы ожидали назначения nil неявно-развернутому необязательному значению для исключения исключения во время выполнения? Это каждый бит так же корректно, как назначение nil нормальному Необязательно. ! только означает, что вам не нужно разворачивать его вручную при доступе к нему; он все еще может иметь нулевое значение. –

+1

@MattGibson: Я просто не понимал, что он выдает ошибку только тогда, когда к ней обращаются (см. Обновленный ответ в нижней части моего ответа). Это имеет смысл, потому что под капотом это по-прежнему необязательно, поэтому присвоение nil является законным. – Antonio

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