четверг, 26 марта 2015 г.

Разница между opaque, hidden и alpha

Разница между opaque (непрозрачность), hidden(скрыто) и alpha  свойствами для UIView

Согласно UIView class reference:


  • opaque указывает системе, то view не имеет прозрачности, а значит рендеринг будет быстрее, потому что расчеты смешивания слоев(blending) будут опущены. 
  • hidden логическое свойство, которое изменяет только видимость конкретного view и прячет его от ui событий. 
  • alpha  анимируемое свойство. 
Выставление alpha = 0.0f or hidden = YES будет иметь тот же визуальный эффект. Стоит использовать hidden , чтобы реально спрятать uiview не только в графическом смысле, но и от ui event'ов будет лучше, особенно если у вас много вложенных view.
Однако, UIKit работает примерно так же для очень низких значений alpha, так как с hidden (если выставить alpha = 0.0f, то ui event'ы тоже будут игнорироваться). 

среда, 11 марта 2015 г.

Как спрятать tab bar / status bar / navigation bar

Для tab bar используйте hidesBottomBarWhenPushed. Например:
UIViewController *myController = [UIViewController new]; 
myController.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:myController animated:YES];
Чтобы спрятать status bar используйте:
[[UIApplication sharedApplication] setStatusBarHidden:YES];
Чтобы спрятать  nav bar:
self.navigationController.navigationBarHidden = YES;

понедельник, 12 января 2015 г.

Swift


Самым неожиданным продуктом, представленным на конференции WWDC 2014, безусловно, стал новый язык программирования Swift. О его разработке не было никаких слухов, и столь внезапный анонс стал настоящим сюрпризом для разработчиков.
Разработка языка велась в течение четырех лет, и наиболее активная работа над ним шла с июля 2013 года.

Крис Латтнер (директор отдела Developer Tools компании Apple)
 отмечает, что Swift был создан благодаря работе команды, которая сложила весь имеющийся опыт работы в таких языковых средах, как Objective-C, Rust, Haskell, Ruby, Python, C#, CLU и многих других, чтобы прийти к Swift в том виде, каким он предстал на конференции 2 июня.

Зачем? (Oh, god, why ? )

Как было сказано на презентации, в ряде случаев Swift работает значительно быстрее по сравнению с другими подобными языками. Например, сортировка комплексных объектов выполняется в 3,9 раза быстрее, чем в Python, и почти в 1,5 раза быстрее, чем в Objective-C, а RC4-шифрование в 220 раз быстрее, чем в Python и в 1,73 раза быстрее, чем в Objective-C.

Swift перенимает читаемость именованных параметров из Objective-C и силу его динамической объектной модели. Он предоставляет простой доступ к существующим фреймворкам Cocoa и возможность смешивать код с Objective-C кодом.


Компилятор оптимизирован для производительности и язык оптимизирован для разработки - без компромиссов с той или другой стороны. Он разработан для приложений от "Hello, world" до масштабов целой операционной системы. Все это делает Swift солидным вкладом для разработчиков и для самой Apple.


Крейг Федериги представил нам Swift в четырех понятиях :
  • Fast
  • Modern
  • Safe
  • Interactive
Fast - потому что не только выполняет важные задачи быстрее, чем Objective-C и Python, но и позволяет писать программы куда быстрее, чем обычно. Пример из презентации:

if (myDelegate != nil){
   if ([myDelegate respondsToSelector:
     @selector(scrollViewDidScroll:)]){
        [myDelegate scrollViewDidScroll:myScrollView];
   }
}
на Swift превращается в :

myDelegate?.scrollViewDidScroll?(myScrollView)

К слову сказать, 
Swift оказался настолько простым в освоении, что менее чем за 24 часа с момента его премьеры разработчик Нейт Мюррей переписал популярную игру Flappy Bird, используя исключительно возможности Swift.

Modern - потому что, как уже было сказано, впитывает в себя самое новое и лучшее из других языков.
Closures, Generics,Type inference,Namespace, Multiple return types,etc. 

Safe - огромные классы ошибок попросту невозможны:
goto
pointers
buffer overflows
uninitialized variables
unsafe string formatting
unclear copy/reference rules

Interactive - Это и playground и возможно, изменяемость кода на ходу, без перекомпилирования. 

Поскольку, Swift native для Cocoa and Cocoa Touch, билдится используя всё тот же LLVM компилятор, использует тот же Optimizer и Autovectorizer, имеет точно такую же ARC-модель, и тот же runtime, 
Вы можете поместить ваш код на Swift в одно приложение с вашим кодом на Objective-C и С.

Общие понятия

Итак, 
let и var используются для создания константы и переменной.
Компилятор сам определяет тип переменной при объявлении. Однако, переменная всегда должна иметь тип, который вы ей передаете. Если же вы хотите сделать что-то вроде:


NSInteger requestsCount = 10.5;

,то стоит помнить,что значения никогда не конвертируются в другой тип неявно. Если необходимо сконвертировать значение в другой тип, вы должны явно это показать:


let label = "The width is "
let width = 94
let widthLabel = label + String(width)                                                             
Хотя конечно, теперь строку widthlabel можно создать, используя \() 

let width = 94
let widthLabel = "The label is \(width)"
Теперь, можно создать массив или словарь, используя []


var ourProjects = ["Quixnap", "Woddl", "Ansa", "Round Table"]

var occupations = [
"CEO" : "Evgeniy",
"TeamLead": "Oleg"
]

А также создать пустой массив или словарь:

let emptyArray = String[]()
let emptyDictionary = Dictionary<String, Float>()

Следующее важное понятие это опциональное значение. Оно может содержать значение, или nil для обозначения того, что значение отсутствует. Для создания "опционального значения" используется знак вопроса:

var optionalString: String? = "Hello" 

Теперь для if и switch скобки вокруг условий опциональны, а фигурные вокруг тела - обязательны.if выражение должно возвращать Boolean, поэтому код типа if score { … } - это ошибка, никакого неявного сравнения с нулем не будет.

Больше не требуется break в switch, поскольку, когда совпал case - выполняется код и выходит из switch. Обязателен default


Функции и замыкания 

Функции вызываются: 

func greet(name: String, day: String) -> String 
    return "Hello \(name), today is \(day)." 
greet("Bob", "Tuesday")

Т.е.

fund functionName( parameter1: type1, parameter2: type2) ->  returningType

Можно использовать tuple для возращаемых значений и разное число аргументов, собираемых в массив:

func topMidBot(numbers: Int... )-> (Double, Double, Double)

Можно принимать функцию как аргумент и возвращать функцию из функции

Функции - это на самом деле специальный случай замыканий. Вы можете написать замыкание без имени, окружив код фигурными скобками. Используйте in для разделения аргументов и типа возвращаемого значения от тела замыкания:

numbers.map({ 
(number: Int) -> Int in 
 let result = 3 * number 
 return result 
})

У вас есть несколько опций для написания замыканий более кратко. Когда тип замыкания уже известен, например обратный вызов делегата (callback), вы можете пропустить тип его параметров, тип возвращаемого значения или и то и другое. Однострочное замыкание в примере ниже возвращает значение своего единственного выражения:

numbers.map({ number in 3 * number })

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

Замыкание, переданное как последний аргумент для функции, может появляться сразу после скобок:
sort([1, 5, 3, 12, 2]) { $0 > $1 }

Объекты и классы

Объявление свойства класса делается так же, как объявление обычной переменной или константы - с тем лишь исключением, что оно теперь находится в контексте класса. Аналогично, методы и функции задаются внутри класса:
class Shape { 
var numberOfSides = 0
init(name: String) 
    self.name = name 
 }
func simpleDescription() -> String 
{
    return "A shape with \(numberOfSides) sides."
 }
 }
Создается объект из класса, используя скобки после имени класса. Используйте синтаксис с точкой для доступа к свойствам и методам объекта:
var shape = Shape()
shape.numberOfSides = 7
var shapeDescription = shape.simpleDescription()
Используйте метод deinit для создания деинициализатора, если нужно перед уничтожением объекта выполнить какую-то очистку.
Классы могут наследоваться. Наследующие классы включают имя суперкласса (их родителя) после своего имени. При этом, классу не обязательно наследоваться от какого-то другого класса (в отличие от Objective-C, где нужно было наследоваться от NSObject - примечание переводчика), в этих случаях имя родителя можно пропустить.
Класс-наследник может определять методы своего родителя, используя слово override - в противном случае, компилятор сообщит об ошибке. Компилятор также определяет методы, которые помечены как override, но на самом деле ничего не переопределяют.
Проиллюстрируем все это с помощью кода:
class Square: NamedShape {
    var sideLength: Double
    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 4
    }
    func area() -> Double {
        return sideLength * sideLength
    }
    override func simpleDescription() -> String {
        return "A square with sides of length \(sidesLength)."
    }
}
let test = Square(sideLength: 5.2, name: "my test square")
test.area()
test.simpleDescription()
В дополнение к простым хранимым свойствам, свойства могут также иметь getter и setter методы, т.е. методы, используемые для получения и установки их значения.
Например:
class EquilateralTriangle: NamedShape {
    var sideLength: Double = 0.0
    init(sideLength: Double, name: String) {
        self.sideLength = sideLength
        super.init(name: name)
        numberOfSides = 3
    }
    var perimeter: Double {
        get {
  return 3.0 * sideLength
        }
        set {
            sideLength = newValue / 3.0
        }
    }
    override func simpleDescription() -> String {
        return "An equilateral triangle with sides of length \(sideLength)."
    }
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength
В сеттере для свойства perimeter, newValue - это псевдоним для нового значения, которое передается. Можно предоставить другой псевдоним, указав его в скобках после set.
Обратите внимание, что инициализатор для EqualiateralTriangle имеет три разных шага:
  1. Устанавливает значение свойств, объявляемых подклассом
  2. Вызывает инициализатор класса-предка
  3. Изменяет значение свойств, объявленных предком.
Любые дополнитеьлные действия так же можно сделать на последнем шаге.
Если вам не нужно вычислять свойство, но по прежнему нужно предоставить код, который будет запущен до и после получения нового значения, используйте willSet и didSet. Например, класс ниже проверяет, что длина стороны треугольника всегда такая же, как длина стороны квадрата:
class TriangleAndSquare {
    var triangle: EquilateralTriangle {
        willSet {
            square.sideLength = newValue.sideLength
        }
    }
    var square: Square {
        willSet {
            triangle.sideLength = newValue.sideLength
        }
    }
    init(size: Double, name: String) {
        square = Square(sideLength: size, name: name)
        triangle = EquilateralTriangle(sideLength: size, name: name)
    }
}
var triangleAndSquare = TriangleAndSquare(size: 10, name: "another test shape")
triangleAndSquare.square.sideLength
triangleAndSquare.triangle.sideLength
triangleAndSquare.square = Square(sideLength: 50,
name: "larger square")
triangleAndSquare.triangle.sideLength
Методы в классах имеют одно важное отличие от функций. Имена параметров в функциях используются только внутри функции, но имена параметров в методах используются так же при вызове метода (кроме первого параметра). По умолчанию, метод имеет одно и то же имя параметра при вызове и внутри самого метода. Но можно указать второе имя, используемое в самом методе:
class Counter {
    var count : Int = 0
    func incrementBy(amount: Int, numberOfTimes
        times: Int) {
        count += amount * times
    }
}
var counter = Counter()
counter.incrementBy(2, numberOfTimes: 7)
Работая с опциональными значениями, вы можете написать ? перед операциями типа методов, свойств и обращений к элементам массива или словаря. Если значение перед ? - nil, то все после ? игнорируется и значение всего выражения - nil. Иначе, опциональное значение используется для вычисления выражения. В обоих случаях, значение всего выражение также является опциональным значением:
let optionalSquare: Square?= Square(sideLength: 2.5, name: "optional square")
let sideLength = optionalSquare?.sideLength


Перечисления (enumerations) и структуры

enum используется для создания перечисления. Как классы и другие именованные типы, перечисления могут иметь ассоциированные с ними методы:
enum Rank: Int {
    case Ace = 1
    case Two, Three, Four, Five, Six, Seven, Eigth, Nine, Ten
    case Jack, Queen, King
    func simpleDescription() -> String {
        switch self {
            case .Ace :
                return "ace"
            case .Jack:
                return "jack"
            case .Queen:
                return "queen"
            case .King:
                return "king"
            default:
                return String(self.toRaw())
        }
    }
}
let ace = Rank.Ace
let aceRawValue = ace.toRaw()
В примере выше, исходное значение перечисления имеет тип Int, поэтому мы указали только первое - Ace равное 1. Остальные были добавлены по очереди (2, 3, 4 и т.д.). Можно также использовать строки или дробные числа в качестве исходных значений перечисления.
Используйте toRaw и fromRaw для перехода от исходного значения к значению перечисления и обратно.
if let convertedRank = Rank.fromRaw(3) {
let threeDescription =
convertedRank.simpleDescription()
}
Значения элементов перечисления - это настоящие значения, а не просто другой способ записи исходных значений. По сути, в случаях, где нет разумного исходного значения, его не обязательно подставлять:
enum Suit {
    case Spades, Hearts, Diamonds, Clubs
    func simpleDescription() -> String {
        switch self {
            case .Spades:
                return "spades"
            case .Hearts:
                return "hears"
             case .Diamonds:
                 return "diamonds"
             case .Clubs:
                 return "clubs"
         }
     }
}
let hearts = Suit.Hearts
let heartsDescription = hearts.simpleDescription()
Обратите внимание на то, как мы используем Hearts в двух разных случаях: когда присваиваем значение константе hearts, мы используем полное имя Suit.Hearts, т.к. константа не имеет определенного типа. Внутри switch'a, мы используем .Hearts, т.к. находимся внутри self. Можно использовать эту сокращенную форму всегда, когда тип значения уже известен.
Используйте struct, чтобы создать структуру. Структуры поддерживают многое из поведения классов, включая методы и инициализаторы. Одно из самых важных отличий между структурами и классами заключается в том, что структуры всегда копируются, когда передаются внутри кода, а классы - всегда передаются по ссылке.
struct Card {
    var rank: Rank
    var suit: Suit
    func simpleDescription() -> String {
        return "The \(rank.simpleDescription()) of \(suit.simpleDescription())"
    }
}
let threeOfSpades = Card(rank: .Three, suit: .Spades)
let threeOfSpadesDescription = threeOfSpades.simpleDescription()
Объект перечисления может иметь значения, ассоциирующиеся с объектом. Объекты одного и того же члена перечисления могут иметь разные значения, ассоциированные с ними. Вы предоставляете ассоциированные значения, когда создаете объект. Ассоциированные значения и исходные значения различны: исходное значение члена перечисления одинаковы для всех его объектов, вы задаете его при определении перечисления. Например, рассмотрим случай запроса времени заката и рассвета с сервера. Сервер отвечает или информацией, или ошибкой.
enum ServerResponse {
    case Result(String, String)
    case Error(String)
}
let success = ServerResponse.Result("6:00 am", "8:09 pm")
let failure = ServerResponse.Error("Out of cheese.")
switch success {
    case let .Result(sunrise, sunset) :
        let serverResponse = "Sunrise is at \(sunrise) and sunset is at \(sunset)."
    case let .Error(error):
        let serverResponse = "Failure… \(error)"
}
Обратите внимание, как время заката и рассвета достаются из ServerResponse как пара значений, соответствующих случаям case.

Протоколы и расширения

Используйте слово protocol для объявления протокола.
protocol ExampleProtocol {
    var simpleDescription: String { get }
    mutating fund adjust()
}
Классы, перечисления и структуры могут соответствовать протоколам:
class SimpleClass: ExampleProtocol {
    var simpleDescription: String = "A very simple class."
    var anotherProperty: Int = 66923
    fund adjust() {
        simpleDescription += " Now 100% adjusted."
    }
}
var a = SimpleClass()
a.adjust()
let aDescription = a.simpleDescription
struct SimpleStructure: ExampleProtocol {
    var simpleDescription: String = "A simple structure"
    mutating fund adjust() {
        simpleDescription += " (adjusted)"
    }
}
var b = SimpleStructure()
b.adjust()
let bDescription = b.simpleDescription
Обратите внимание на ключевое слово mutating, которое обозначает метод, модифицирующий структуру. Объявление класса не требует добавления слова mutating, т.к. методы класса всегда могут модифицировать класс.
Используйте слово extension (расширение) для добавления функциональности существующему типу, например новых методов или вычисленных свойств. Вы можете использовать расширение для добавления совместимости с протоколом типу, который объявлен в другом месте, или даже типу, который вы импортировали из библиотеки или фреймворка:
extension Int: ExampleProtocol {
    var simpleDescription: String {
        return "The number \(self)"
    }
    mutating func adjust() {
        self += 42
    }
}
simpleDescription
Вы можете использовать имя протокола, как любой другой именованный тип - например, создать коллекцию объектов, которые имеют разные типы, но все соответствуют одному протоколу. Когда вы работаете со значениями, тип которых - протокол, методы вне объявления протокола недоступны.
let protocolValue: ExampleProtocol = a
protocolValue.simpleDescription
// protocolValue.anotherProperty 
Хотя переменная protocolValue будет иметь тип SimpleClass во время исполнения, компилятор работает с ней как с переменной типа ExampleProtocol - это значит, что вы не сможете случайно обратиться к методам или свойствам, которые класс реализует в дополнение к протоколу.

Общие функции и типы

Напишите имя внутри <>, чтобы создать общую функцию или тип:
func repeat<ItemType>(item : ItemType, times: Int) ->
ItemType[] {
    var result = ItemType[]()
    for i in 0..times {
        result += item
    }
    return result
}
repeat("knock", 4)
Вы можете создать общие формы функций и методов, так же как и классов, перечислений и структур.
// Переопределяем опциональный тип из стандартной библиотеки Swift:
enum OptionalValue<T> {
    case None
    case Some(T)
}
var possibleInteger: OptionalValue<Int> = .None
possibleInteger = .Some(100)
Используйте where после имени типа, чтобы указать список требований - например, потребовать, чтобы тип реализовывал протокол, потребовать чтобы два типа были одинаковы или потребовать, чтобы класс имел определенный суперкласс:
func anyCommonElements <T, U where T: Sequence, U: Sequence,
    T.GeneratorType.Element: Equatable, T.GeneratorType.Element == U.GeneratorType.Element > (lhs: t, rhs: U) -> Bool {
    for lhsItem in lhs {
        for rhsItem in rhs {
            if lhsItem == rhsItem {
                return true
            }
        }
    }
    return false
}
anyCommonElements([1, 2, 3], [3])
В простых случаях, where можно пропустить и просто написать имя класса или протокола после двоеточия. Т.е. написать <T: Equatable> - это то же самое, что и <T where T: Equatable>.

Дополнительно


Facebook Parse будет использовать новый язык программирования Apple Swift

«Здесь, в Parse, мы очень рады появлению Swift, потому что язык приносит массу новых функций для разработчиков iOS и OS X,— отметил в официальном блоге программист компании Форко Маротто (Fosco Marotto). — Интерфейс классов Swift позволит разработчиков сэкономить массу времени на создании кода. И в целом снизит число ошибок времени исполнения…».

Крупнейшая социальная сеть в мире Facebook поглотила Parse в апреле 2013 года с целью усилить свои позиции в мире мобильных приложений и платных служб «бизнес для бизнеса».
Стоит отметить, что Swift совместим с существующими библиотеками Objective-C, включая сторонние вроде Parse, так что интеграция языка не должна стать большой проблемой. Подробнее о том, как использовать каркас приложений Parse в проекте Swift, можно узнать в детальной инструкции Stackoverflow.

пятница, 27 июня 2014 г.

Как вывести список свойств и ivar ios Objective-c

Бывают случаи, когда нужно вывести список свойств и переменных класса, вот как это сделать:

        Class  downloadTaskClass = [downloadTask class];
        Class  taskClass = [downloadTaskClass superclass];
        Class  superTaskClass = [taskClass superclass];
        Class  superSuperTaskClass = [superTaskClass superclass];
        
        unsigned int count;
        Ivar * ivars = class_copyIvarList(downloadTaskClass, &count);
        for(unsigned int i = 0; i < count; ++i)
        {
            NSLog(@"%@::%s", downloadTaskClass, ivar_getName(ivars[i]));
        }
        NSLog(@"Properties: ");
        
        unsigned int outCount;
        objc_property_t * properties = class_copyPropertyList(downloadTaskClass, &outCount);
        for (unsigned int i = 0; i < outCount; i++)
        {
            objc_property_t property = properties[i];
            NSLog(@"%s %s\n", property_getName(property), property_getAttributes(property));
        }

четверг, 5 июня 2014 г.

Базовые операторы (Отрывок из незаконченного перевода книги Swift)

Оператор - это специальный символ или фраза, которые Вы используете для проверки, изменения или комбинирования значений. Например, оператор сложения (+) складывает два числа вместе ( как let i = 1 +1 ). Более сложные примеры включают логический оператор и && ( как в if enteredDoorCode && passedRetinScan ) и оператор инкремента ++i, который является упрощенным оператором (shortcut) увеличения значения  i на 1.

Swift поддерживает большинство стандартных операторов языка C и улучшает несколько возможностей для устранения частых ошибок при программировании. Оператор присваивания (=) не возвращает значение, что предотвращает его ошибочное использование вместо оператора равенста (==). Арифметические операторы ( +, -, *, /, % и т.д.) определяют и запрещают переполнение значений, чтобы избежать неожиданных результатов, когда работаешь с числами которые становятся больше или меньше того, что позволяет диапазон принимающей переменной. Вы можете изменять поведение переполнения значения, используя операторы переполнения, которые описаны в Операторы Переполнения

В отличии от C, Swift дает возможность выполнять оператор остатка от деления (%) для чисел с плавающей запятой. Swift также предоставляет два оператора диапазона ( a..b и a...b ), которых не было в C, как упрощенный оператор для выражения диапазона значений.

Эта глава описывает самые частые операторы Swift. Продвинутые Операторы охватывает продвинутые операторы Swift и описывает как определить Ваши собственные операторы и написать стандартные операторы для Ваших типов.

Терминология

Операторы бывают унарные, бинарные и тернарные:

  • Унарные оперируют одним значением (как например -a). Унарные префиксные операторы определяются сразу перед выражением ( как !b) и унарные постфиксные операторы сразу после (  i++ )
  • Бинарные оперируют двумя выражениями ( 2 + 3 ) и только
  • Тернарные операторы используют три выражения. Как и в C, в Swift есть только один тернанрный оператор, оператор состояния  ( a ? b : c )  
Значения, с которыми операторы взаимодействуют, называются операндами .
В выражении 1 + 2 ,  + это бинарный оператор, а 1 и 2 - это операнды.

Оператор Присваивания 

Оператор присваивания ( a = b ) инициализирует или обновляет значение a значением :

let b = 10
var a = 5
a = b

//а сейчас равно 10

Если правая сторона присваивания это tuple с множеством значений, то его значения сразу раскладываются и присваиваются каждой переменной или константе

let (x, y ) = (1, 2)
//x сейчас равен одному, а y равен 2

В отличии от оператора присваивания в C и Objective-C , оператор присваивания в Swift не возвращает значение. Следующие выражение не допустимо:

if x = y
{
    //это не допустимо поскольку x = y не возвращает значение
    
}

Это предотвращает использование оператора присваивания (=) как оператора сравнения равенства (==).  Не допуская if x = y, Swift помогает Вам избежать эти виды ошибок в Вашем коде.

Арифметические операторы

Swift поддерживает четыре стандартных арифметических оператора для всех числовых типов:
  • Сложение (+)
  • Вычитание (-)
  • Умножение (*)
  • Деление (/)

1 + 2 // равно 3
5 - 3 // равно 2
2 * 3 // равно 6
10.0 / 2.5 // равно 4.0 

В отличие от арифметических операторов в C и Objective-C, арифметические операторы в  Swift  не позволяют значениям переполняться по умолчанию.  Вы можете изменять поведение переполнения значения, используя операторы переполнения ( вроде a &+ b) , которые описаны в Операторы Переполнения

Оператор сложения также поддерживает конкатенацию строк :


"hello," + "world" //равно "hello,world"

Два символьных(character)  значения или одно символьное значение и одна строка(String) могут быть сложены вместе и создают новую строку :

let A: Character = "A"
let B: Character = "B"

let AB = A + B
//AB сейчас равно строке AB


Оператор Остатка 

Оператор Остатка ( a % b )  вычисляет сколько останется от деления a на b  и возвращает это значение

Заметьте:
Оператор остатка (%) еще известен как оператор модуля в других языках. Однако, в Swift это звучит как Оператор Остатка, поскольку он работает одинаково и с отрицательными числами .

Вот как этот оператор работает. Чтобы вычислить 9 % 4,  сначала посчитайте сколько 4ок поместится в 9ти:
         4          4 1
1 2 3 4 5 6 7 8 9

Вы можете поместить две 4ки внутри 9ки и у вас останется 1.

В Swift это может быть записано как:
9 % 4 //равно 1 
Чтобы определить ответ для a % b , оператор % считает следующее уравнение и возвращает остаток как значение 
a = (b x какой-то множитель ) + остаток 
Где "какой-то множитель" это самое большое количество множителей b, которое поместится в a.
Подставив 9 и 4 в это уравнение, получим:
9 = (4 x 2) +

Тот же метод применяется, когда рассчитывается остаток для отрицательного значения a:

-9 % 4 // равно - 1

Подставив -9 и в это уравнение, получим:
-9 = (4 x 2) + -
возвращаемый остаток = - 1

Знак b игнорируется для отрицательных значений b. Это значит, что a % b и a % -b всегда возвращают тот же ответ.

Остаток для чисел с плавающей запятой
В отличии от оператора остатка C и Objective-C, в Swift оператор остатка от деления также может работать с числами с плавающей запятой:

8 % 2.5 // равно 0.5

В этом примере, 8 разделенное на 2.5 равно 3 с остатком 0.5, т.е. оператор остатка возвращает Double значение 0.5

2.5  2.5  2.5 .5
1 2 3 4 5 6 7 8

Операторы Инкремента и Декремента

Как и в C, в Swift есть операторы инкремента ( ++ )  и декремента ( -- ) как упрощенный вариант ( shortcut ) для увеличения и уменьшения значения числовой переменной на 1. Вы можете использовать эти операторы с переменными целого типа и с плавающей запятой.

var i = 0
++i // i сейчас равно 1

Каждый раз когда Вы вызываете ++i , значение i увеличивается на 1. По существу, ++i это сокращенный способ сказать i = i + 1. Также, --i используется для сокращения i = i - 1.
Символы ++ и -- могут быть использованы как префикс и постфикс. ++i и i++  - оба выражения допустимые способы увеличить значение i на 1.  Точно как, --и i--  -допустимые способы уменьшить значение i на 1.

Заметьте что эти операторы изменяют i и также возвращают значение. Если вы хотите только уменьшить или увеличить значение, хранимое в i,  достаточно игнорировать возвращаемое значение.  И если вы используете возвращаемое значение, оно будет различным, в зависимости от того,  используете вы префиксную или постфиксную версию оператора, в соответствии со следующими правилами :
  • Если оператор написан перед переменной, он инкрементирует переменную перед тем как вернуть её значение.
  • Если оператор написан после переменной, он инкрементирует переменную после того как вернет значение.
var a = 0
let b = ++a
// a и b сейчас равны 1
let c = a++
// a рано 2 , с = 1

В примере выше, let b= ++a увеличивает a перед возвращением значения. Это почему a и b оба равны 1.
Также , let c = a++ увеличивает a после возвращения значения . Т.е. c получает старое значение 1, инкрементится a и становится равным 2.
За исключением, когда вам нужно специфичное поведение i++, рекомендуется использовать ++i и --i во всех случай, потому что у них типичное поведение изменения и возвращения значения. 

Унарный Оператор Минус

Знак численных значений может быть переключен, используя префикс -, известный как унарный оператор минус:
let three = 3  // равно 3

let minusThree = -three  // равно -3

let plusThree = -minusThree // равно 3

Унарный оператор минус (-) добавляется сразу перед значением, которым он оперирует, без пробелов.

Унарный Оператор Плюс

Унарный оператор плюс (+) возвращает значение перед которым стоит, ничего не изменяя:
let minusSix = -6  // равно 6

let alsoMinusSix = +minusSix // тоже равно 6

Хотя оператор плюс ничего по-существу не делает, Вы можете использовать его чтобы обеспечить симметрию в Вашем коде для положительных чисел, когда используете оператор минус для отрицательных чисел.

Составные операторы присваивания

Как C, Swift предоставляет составные операторы присваивания,  которые комбинируют операторы присваивания с другими операторами. К примеру,  присваивание с суммированием(+=):
var a = 1

a += 2 //a сейчас равно 3

Выражение a += 2 это упрощение для a = a + 2. Фактически, сложение и присваивание скомбинированы в один оператор, который выполняет обе задачи сразу.

Заметьте
Составное присваивание не возвращает значение . Вы не можете написать let b = a += 2 , например. Это поведение отличается от операторов инкремента и декремента.

Полный список составных операторов приваивания можно найти в Выражения .

Операторы сравнения 

Swift поддерживает все стандартные операторы сравнения C :
  • Равно ( a == b )
  • Не равно ( a !=b )
  • Больше чем ( a > b )
  • Меньше чем ( a < b )
  • Больше чем или равно ( a >= b )
  • Меньше чем или равно ( a <= b )
Заметьте
Swift также предоставляет два оператора равенства ( === и !== ), которые Вы используете для проверки являются ли два объекта-ссылки ссылающимися на тот же экземпляр объекта. Больше информации в Классах и Структурах . 

Каждый из операторов сравнения возвращает Булевое значение (Bool), которые показывает является ли выражение верным(true):
1 == 1  //true(верно) поскольку 1 равен 1
2 != 1  //true, поскольку 2 не равно 1
2 > 1   //true, поскольку 2 больше чем 1
1 < 2   //true, поскольку 1 меньше 2
1 >= 1  //true, поскольку 1 больше чем либо равно 1
2 <= 1  //false( не верно), поскольку 2 не меньше и не равно 1

Операторы сравнения часто используются в условных выражениях, таких как if :
let name = "world"

if name == "world"
{
    println("hello, world")
}
else
{
    println("Im sorry \(name),but I don't recognize you")
}

// Напечатается "hello, world", поскольку name == "world"
Для большего о if выражениях смотрите Control Flow .

Тернарный условный оператор

Тернарный условный оператор это специальный оператор с тремя частями, которые принимают форму question ? answer1 : answer2. Это упрощенный вариант для оценки одного из двух выражений, основанный на тот верно или нет выражение question . Если question верно (true), выполняется answer1 и возвращает значение; если не верно, то считается и возвращается  значение answer2. 
Тернарный условный оператор это упрощение для следующего кода:
if question
{
    answer1
}
else
{
    answer2
}

Здесь пример, который подсчитывает пиксели высоты для ячейки таблицы(table row).   Высота должна быть выше на 50 пикселей, чем высота контента, если у ячейки есть заголовок, и на 20 пикселей выше, если у ячейки нет заголовка:

let contentHeight = 40
let hasHeader = true
let rowHeight = contentHeight + (hasHeader ? 50 : 20)
//rowHeight равно 90 
//прим.переводчика: если Вы поставите ? сразу после hasHeader,будет ошибка

Предшествующий пример это сокращенный вариант кода :
let contentHeight = 40
let hasHeader = true
var rowHeight = contentHeight
if hasHeader
{
    rowHeight = rowHeight + 50
}
else
{
    rowHeight = rowHeight + 20
}

Первый пример использования тернарного условного оператора значит что rowHeight может установлен в нужное значение в единственной строке кода. Это более кратко, чем второй пример и позволяет rowHeight быть не переменной, а константой, поскольку её значение не будет изменено внутри if.
Тернарный условный оператор предоставляет эффективный способ решения какое из двух выражений принять. Используйте тернарный оператор с осторожностью. Его сжатость может привести к трудночитаемости кода. Избегайте комбинирование нескольких экземпляров тернарного оператора в одном сравнении. 

Операторы Диапазона 

Swift включает два оператора диапазона, которые упрощают обозначение диапазона значений

Оператор Закрытого Диапазона

Оператор закрытыго диапазона (a...b ) определяет диапазон который идет от a до b включая значения a и b

Оператор закрытого диапазона полезен когда итерации в диапазоне, в котором вы хотите использовать все значения, как for-in цикл:

for index in 1...5
{
    println("\(index) times 5 is \(index * 5)")
    index
}

// 1 times 5 is 5
// 2 times 5 is 10
// 3 times 5 is 15
// 4 times 5 is 20
// 5 times 5 is 25

Для большей информации о for-in циклов смотрите Control Flow

Оператор Полузакрытого Диапазона


Оператор полузакрытого диапазона (a..b) определяет диапазон который идет от a до b, не включая b. Называется так, поскольку включает первое значение, но не последнее.

Полузакрытый диапазаон особенно полезен когда Вы работаете со списками типа массив(Array), где счет начинается с 0, а значит полезно использовать значение длина-1:

let names = ["Anna","Alex","Brian","Jack"]
let count = names.count
for i in 0..count
{
    println("Person \(i+1) is called \(names[i])")
}

// Person 1 is called Anna
// Person 2 is called Alex
// Person 3 is called Brian
// Person 4 is called Jack 

 Заметьте, что массив содержит четыре значения, но 0..count считает только до 3(индекс последнего элемента в массиве), поскольку используется полузакрытый диапазон. 
Для большей информации о массивах, смотрите Массивы

Логические Операторы

Логические Операторы изменяют или комбинируют Булевскиие логические значения true и false. Swift поддерживает три стандартных логических оператора из C-основанных языков:
  • Логическое отрицание ( !a )
  • Логическое и ( a && b )
  • Логическое или ( a || b )

Логическое Отрицание 

Оператор логического отрицания ( !a ) инвертирует Булевское значение, т.е. true становится false, и false становится true.
Этот оператор является префиксным, и появляется сразу перед значение над которым он работает, без пробелов. Это можно прочесть как "не a". Например:
let allowedEntry = false
if !allowedEntry
{
    println("Access Denied")
}

// напечатается "Access Denied"

Фраза if !allowedEntry может звучать как "не allowedEntry". Следующая строка выполнится только, если "не allowedEntry" равен true; это так, поскольку allowedEntry = false.
Как и в этом примере внимательный выбор Булевской константы и имени переменной, могут помочь сохранить коду читаемость и краткость, пока избегается двойное отрицание или запутанные логические выражения.

Логический Оператор И

Логический оператор И ( a && b ) создает логические выражения, где оба выражения должны быть true, чтобы общее выражение тоже было true.
Если любое значение false, то общее выражение тоже будет false. По факту, если первое значение false, второе не будет даже вычиcляться, поскольку невозможно чтобы общее выражение стало true . Это известно как быстрая схема вычисления .

В этом примере сравниваются две Булевые переменные и доступ разрешен, только если оба значения true:

let enteredDoorCode = true
let passedRetinaScan = false
if enteredDoorCode && passedRetinaScan
{
    println("Welcome!")
}
else
{
    println("Access Denied")
}

//напечатается "Access Denied"

Логический оператор ИЛИ

Логический оператор или  ( a || b ) это оператор, который используется для создания выражений, в которых общее значение будет true, если хотя бы одно из значений true.
Как и логический оператор и, логический или использует быструю схему вычисления. 
Если левая сторона выражения true, правая не вычисляется, поскольку правая уже не может изменить общего значения.
В примере ниже, первая Булевая переменная (hasDoorkey) равна false, однако второе значение (knowsOverridePassword) равна true. Поскольку одно значение true, общее выражение также считается true, и доступ разрешен:
let hasDoorKey = false
let knowsOverridePassword = true
if hasDoorKey || knowsOverridePassword
{
    println("Welcome")
}
else
{
    println("Access Denied")
}


//напечатается "Welcome!"

Комбинирование Логических Операторов

Вы можете комбинировать несколько логических операторов, чтобы увеличить количество сравнений:

if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword
{
    println ("Welcome")
}
else
{
    println("Access Denied")
}

Этот пример использует несколько && и || операторов чтобы создать длинное смешанное сравнение. Однако, && и || всё еще работает с двумя операндами, т.е. это три маленьких выражения связанных вместе. Это можно прочесть как :
Если enteredDoorCode и passedRetinaScan; или если hasDoorKey ; или если knowsOverridePassword, то выполнить println("Welcome"), иначе  println("Access Denied").
Основываясь на enteredDoorCode, passedRetinaScan, and hasDoorKey, первые два выражения
false. Однако, knowsOverridePassword true, а значит и всё выражение true.

Явные скобки

Иногда полезно использовать скобки, когда они не необходимы, чтобы сделать общее выражение более читаемым. В верхнем выражении полезно добавить скобки в первую часть общего выражения, чтобы явно выделить выражение:

if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword
{
    println ("Welcome")
}
else
{
    println("Access Denied")
}

Скобки делают понятнее, что первые два значения являются частью общего разделенного выражения. Вывод объединного выражения не изменяется, однако общий замысел более понятен читающему. Читаемости всегда отдается предпочтение перед краткостью; используйте скобки там, где они помогают сделать идею более ясной.

(Отрывок из перевода книги о Swift, правда сам проект закрылся, так что только несколько глав переведено)