Я новичок в кодировании Swift и iOS и работаю над написанием своего первого приложения. В то время как мой фон программирования довольно значителен, я исхожу из фона Python и C#, где почти все может быть None
или null
, и это зависит от пользователя, чтобы проверить его во время выполнения для null. Я нахожу всю эту концепцию «nullable vs. non-nullable types» или «необязательные типы» в Swift, чтобы запутать.Swift: путают о нулевых/необязательных типах
Я понимаю, что основная концепция заключается в том, что переменная, объявленная как тип myObject
, не может быть установлена в nil
. Однако, если я определяю его как тип myObject?
, тогда значение может быть установлено на nil
.
Проблема в том, что, когда я смотрю на свои проекты кода, кажется, что все должно быть «обнулено» в моем коде. Кажется, что это означает, что я не думаю правильно, как должен работать мой код, или что мне не хватает какого-то важного понимания.
Давайте рассмотрим простейший пример того, чем я смущен. Предположим, у меня есть два класса: один, который хранит и управляет некоторыми данными, а другой - обеспечивает доступ к этим данным. (Например, это может быть что-то вроде соединения с базой данных, или дескриптор файла или что-то подобное.) Назовем класс, содержащий данные myData
, и класс, который работает с этими данными myObject
.
myObject
потребуется ссылка на уровне класса на myData
, поскольку многие из его методов зависят от локальной ссылки на класс. Итак, первое, что делает конструктор, это создать соединение с данными, а затем сохранить его в локальной переменной dataConnection
. Переменная должна быть определена на уровне класса, чтобы другие методы могли получить к ней доступ, но она будет назначена в конструкторе. Неспособность получить соединение приведет к некоторому исключению, которое будет мешать самому созданию класса.
Я знаю, что Swift имеет два способа определения переменного: var
и let
, с let
быть аналогичны const
директивы некоторых Языков. Поскольку соединение данных будет сохраняться на протяжении всей жизни класса, let
кажется очевидным выбором. Однако я не знаю, как определить переменную уровня класса через let
, которая будет назначена во время выполнения. Поэтому я использую что-то вроде
var dataConnection: myData?
в классе вне любых функций.
Но теперь мне приходится иметь дело с типом данных с нулевым значением и делать явные разворачивающиеся каждый раз, когда Я использую его в любом месте. Нехорошо говорить и сбивать с толку.
func dealWithData() {
self.dataConnection.someFunctionToGetData() <- results in an unwrapping error.
self.dataConnection!.someFunctionToGetData() <- works.
let someOtherObjectUsingData: otherObject = self.getOtherObject() <- may result in error unless type includes ?
someOtherObjectUsingData.someMethod(self.dataConnection) <- unwrap error if type included ?
var myData = self.dataConnection!
someOtherObjectUsingData.someMethod(myData) <- works
}
func somethingNeedingDataObject(dataObject: myData?) {
// now have to explicitly unwrap
let myDataUnwrapped = myData!
...
}
Это, по-видимому, очень подробный способ решения проблемы. Если объект равен nil
, не может ли явное разворачивание само по себе вызвать ошибку времени выполнения (которую можно поймать и обработать)? Это, как правило, является кошмаром при навязывании вещей вместе. Я должен был сделать что-то вроде:
self.dataConnection!.somethingReturningAnObject!.thatObjectsVariable!.someMethod()
var myData? = self.dataConnection
var anotherObject? = myData!.somethingReturningAnObject
...
То, как я привык делать это, что вы просто определить переменную, и если он установлен в нуль, и вы пытаетесь сделать что-то с ним, исключение (которое вы можете поймать и обработать). Разве это просто не так, как все работает в Свифте?Это довольно смутило меня, что почти каждый раз, когда я пытаюсь скомпилировать приложение, я получаю массу ошибок об этом (и я просто позволяю Xcode исправлять их). Но это не может быть лучшим способом справиться с этим.
Должен ли я последовательно обрабатывать переменные обертывания и разворота - даже те, которые, как ожидается, никогда не будут нулевыми, но просто не могут быть назначены во время компиляции?
Я настоятельно предлагаю вам использовать типы заглавных букв, чтобы мы могли легко идентифицировать их, когда вы пишете о них. Также это соглашение в Swift;) – Fantattitude
Если вы хотите добавить свойство к классу, который не может быть установлен во время создания, но вы можете гарантировать, что: 1. Как только он будет установлен, он никогда не станет 'nil' и 2. You никогда не пытайтесь получить к нему доступ до того, как он будет установлен, безопасно использовать неявно отключенные опции: 'var dataConnection: MyData!' –