В последнее время я играл с переменными и разобрался с некоторыми опциями, доступными для языка. На первый взгляд Swift кажется довольно простым и имеет сходство с другими языками, с которыми я работал. Однако, если копнуть глубже, у него есть несколько довольно уникальных характеристик, которые делают его интересным для программирования.
"Обычные" переменные, также известные как примитивы
Фундаментальные строительные блоки практически любого приложения включают в себя базовые первичные типы переменных. Swift начинает вас здесь и дает вам доступ к:
/* String = Allows us to work with text. ex: "It is beautiful outside" Int = Data type for working with whole numbers. Ex: 0, 5, 100 Float = Data type for working with decimal type numbers ex: 1.5, 2.25 Double = Similar to Float but used for larger decimal values Bool = Data type for working with True or False statements. */
Теперь, с учетом сказанного, есть несколько способов их создания. Некоторые важные вещи, на которые следует обратить внимание в приведенном ниже примере.
- Разница между let и var
- Строго типизированные экземпляры с использованием :
// let = a keyword we use when we expect this value to be constant and not change. let myVariable: String = "This string is constant" // var = a keyword indicating that the value is variable and is expected to / can change. var myVariable: String = "Hello Joseph!" // Can declare multiples of the same type in a row var hasWater, hasPicnicTables, hasShade : Bool // Can even define starting values for multiples let firstPeriod = 1, secondPeriod = 2, thirdPeriod = 3
Примечание. Возможно, вы заметили, что в последнем примере переменной не было идентификатора типа. Что ж, компилятор Swift автоматически определит тип для вас, если он не определен.
Swift включает в себя очень классную функциональность с его примитивными типами!
//Strings can have different cases to them myStringVariable.uppercased() //"HELLO WORLD" myStringVariable.lowercased() //"hello world" myStringVariable.capitalized // "Hello World" //Strings can use the .isEmpty to determine if the string is empty or not if(myStringVariable.isEmpty){ ... } //Bools can use the .toggle() option to automatically switch it to the opposite value Button("Click me"){ isActive.toggle() } //.description is used to give you a representation of the current value Text(myVariable.description) //You can also see a value of a variable by using it in a string Text("This is the value of my variable: \(myVariable)")
Не совсем обычные типы переменных
Одной из величайших особенностей переменной является ее гибкость. Они могут быть буквально кем угодно! От цвета до пользовательского объекта. Хотя, я думаю, в какой-то момент большинство людей больше не считают их переменными, но все они имеют одно и то же базовое определение и по-прежнему сохраняются для последующего использования.
//Setting a constant background color variable let backgroundColor : Color = Color.red //A Tuple is a unique type that can store a group of values into one variable let runningBack = (20, "Barry Sanders") //Collections such as arrays var fruitAssortment : [String] = ["Apples", "Oranges", "Plums"] //Even entire views can be tucked away var myView : some View{ Text("Hi, this is part of myView") }
Необязательные переменные — вы ничего не сделаете!
Вышеприведенные примеры великолепны и все, но иногда переменные могут иметь или не иметь значение для них. Что тогда!? Давайте возьмем какое-то ожидаемое значение, например код безопасности кредитной карты, как часть процесса проверки. Мы можем использовать необязательный параметр как простой способ проверить, было ли сохранено это значение или нет.
//To define an optional put a question mark next to the type var securityCode : Int? = nil //Then later on we can check if it has a value or not. If it's not nil, continue! if(securityCode != nil){ ... }
Сравнения — использование операторов
Как и в приведенном выше примере, нам часто нужно сравнить значение переменной с чем-то для оценки. Для этого мы можем использовать несколько разных операторов!
// use the == symbol to compare if these objects are equal in value if( myValue1 == myValue2 ){ ... } // use the != symbol to compar if these objects are NOT equal in value if( myValue1 != myValue2 ){ ... } /* Mathmatical type operators > for greater than < for less than >= greater than or equal to <= less than or equal to */ if( myInt1 > myInt2){ ... }
Примечание. Метод проверки == и != иногда может вызвать некоторые проблемы, если вы не будете осторожны. Распространенной ловушкой, в которую попадают люди, является сравнение строковых значений. Иногда полезно быть таким явным, но часто вам нужно убедиться, что вы сравниваете правильные случаи для большей точности (совет: используйте .lowercased() или .uppercased() для каждого значения для этой цели).
Сравнения — проверка типов по ключевому слову is
Но что, если нам нужно выяснить, к какому типу относится что-то? Возможно, это происходит, когда мы перебираем набор значений. Для этого примера предположим, что у нас есть коллекция объектов Car. Теперь мы хотим посмотреть, какие из них являются электромобилями (Tesla).
struct CarExample: View { //create our collection of cars let cars : [Car] = [Tesla(), Ford(), Ford(), Tesla(), Tesla()] var body: some View { VStack(alignment: .leading, spacing: 10) { //Iterate through our collection ForEach(cars){ car in //** Use the is keyword to check the type of the object! if car is Tesla{ Text("This car is electric: \(car.isElectric.description)") } else{ Text("This car is not electric: \(car.isElectric.description)") } } } } } //Basic car classes used for our example above public class Car : Identifiable { var isElectric : Bool init(electric : Bool){ isElectric = electric } } public class Tesla : Car { init(){ super.init(electric: true) } } public class Ford : Car { init(){ super.init(electric: false) } }
Преобразование типов
Этот язык типобезопасен, что означает, что он не позволит вам наделать глупостей, назначив какие-либо другие типы значений чему-либо, если оно уже определено как нечто другое. Таким образом, вы не сможете случайно установить значение Int в Bool. Однако бывают случаи, когда вам нужно преобразовать значение из одного в другое.
Хотя мы немного ранее коснулись того, как получить строковые значения из ваших переменных, у каждого класса также есть способ создать новый объект из заданного значения. Ниже у нас есть пара примеров. Первый показывает, что мы можем взять значение Double и преобразовать его в Int, по существу отбросив десятичные значения. Во втором примере мы создаем новый Bool из строки.
/* In the example below we don't actually care about the decimal places so we can convert from double to Int */ let myDoubleValue : Double = 2.5 Text("Showing an Int value: \( Int(myDoubleValue) )") //2 Text("Showing as a String: \( myDoubleValue ) ") //2.500000 Text("Showing as a String: \( myDoubleValue.description ) ") //2.5 /* Creating a bool object from a string value */ let myStringValue : String = "true" Text("Showing text as a bool: \( Bool(myStringValue)!.description )")
ПРИМЕЧАНИЕ. В последнем примере вы заметите ! после нашего вызова Bool(). Это потому, что система не знает, может ли она создать логическое значение из данного значения, поэтому она возвращает необязательный (пару абзацев назад). ! просто распаковывает значение, так как мы знаем, что оно есть (не используйте !, если вы не уверены).
Оболочка @ State
Когда вашей переменной необходимо обновить состояние пользовательского интерфейса, вы можете использовать эту оболочку. По сути, он следит за любыми изменениями в переменной, а затем сигнализирует об обновлении пользовательского интерфейса при изменении. Обратите внимание, что это не работает с let, так как это константа, не ожидающая изменений!
//Since this displays in our UI, when the color is changed it will change the background @State var backgroundColor = Color.red var body: some View{ ZStack { backgroundColor .edgesIgnoringSafeArea(.all) VStack{ //When this button clicks it sets the value of our @State variable Button("Update Color"){ backgroundColor = Color.purple } } } }
Оболочка @ Binding
В большинстве языков программирования, с которыми я работал, всегда был какой-то способ передачи значений в том, что они называют способом по значению или по ссылке.
По значению = передается только значение, и любые его изменения НЕ влияют на исходный объект.
По ссылке = передается ссылка на исходный объект, и любые внесенные изменения повлияют на исходный объект.
По сути, оболочка привязки позволяет нам передавать переменную по ссылке!
Здесь мы берем предыдущий пример и перемещаем основные компоненты в новое дополнительное представление. Однако подвиду нужна ссылка на объект цвета, который он использует, чтобы кнопка могла обновить цвет фона.
- В нашем подчиненном представлении мы объявляем переменную, с которой нам нужно работать, используя оболочку @ Binding.
- При передаче переменной в инициализатор подпредставления с использованием $ для привязки переменной
struct ColorExample: View{ @State var mainColor : Color = Color.red var body: some View{ //Use the $ sign to bind this variable in the init of the sub view SubViewWithBackground(backgroundColor: $mainColor) } } struct SubViewWithBackground : View { @Binding var backgroundColor : Color var body: some View{ ZStack { backgroundColor .edgesIgnoringSafeArea(.all) VStack{ /* When this button clicks it sets the value of our @State variable. Which is just a reference to our mainColor */ Button("Update Color"){ backgroundColor = Color.purple } } } } }
Ну, это было совсем немного, чтобы покрыть! Сумасшедшая часть заключается в том, что это даже близко не все, что вы можете узнать по этой теме. Тем не менее, это чертовски хорошее начало. Это просто заметки и странные примеры мячей, которые я пытался придумать. Поиграйте с ним немного и привыкните к работе с ними. Это на самом деле довольно круто и очень гибко!
До следующего раза сохраняйте спокойствие и продолжайте кодить!