В процессе разработки компонента выбора цвета пришлось столкнуться с парой неприятных моментов, касающихся работы с HSB-составляющими на нулевых значениях. Первым открытием был сброс оттенка при нулевой насыщенности, а вторым — обнуление и оттенка, и насыщенности при нулевой яркости.
import UIKit
var color: UIColor
var hue = CGFloat()
var saturation = CGFloat()
var brightness = CGFloat()
color = UIColor(hue: 1, saturation: 1, brightness: 1, alpha: 1)
color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: nil)
// Output: 1.0 1.0 1.0
// Saturation = 0 resets hue to 0
color = UIColor(hue: 1, saturation: 0, brightness: 1, alpha: 1)
color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: nil)
// Output: 0.0 0.0 1.0
// Brightness = 0 resets hue and saturation to 0
color = UIColor(hue: 1, saturation: 1, brightness: 0, alpha: 1)
color.getHue(&hue, saturation: &saturation, brightness: &brightness, alpha: nil)
// Output: 0.0 0.0 0.0
До выхода iOS 9 программное создание ограничений происходило через инициализацию объектов NSLayoutConstraint, включавшую длинный список передаваемых аргументов или код на Visual Format Language, однако с появлением нового класса NSLayoutAnchor процесс можно заметно упростить.
По сути, теперь ограничиваемые атрибуты добавлены в UIView как свойства с типом одного из подклассов NSLayoutAnchor: NSLayoutXAxisAnchor (для горизонтальных ограничений), NSLayoutYAxisAnchor (вертикальных) или NSLayoutDimension (высоты и ширины). И установка ограничений с нужными взаимосвязями доступна через их методы.
if #available(iOS 9.0, *) {
view.widthAnchor.constraintEqualToAnchor(view.heightAnchor, multiplier: 0.5).active = true
view.centerXAnchor.constraintEqualToAnchor(self.centerXAnchor, constant: 10).active = true
view.centerYAnchor.constraintEqualToAnchor(self.centerYAnchor, constant: 10).active = true
view.widthAnchor.constraintLessThanOrEqualToAnchor(self.widthAnchor).active = true
view.heightAnchor.constraintLessThanOrEqualToAnchor(self.heightAnchor).active = true
} else {
addConstraints([
NSLayoutConstraint(item: view,
attribute: .Width,
relatedBy: .Equal,
toItem: view,
attribute: .Height,
multiplier: 0.5,
constant: 0),
NSLayoutConstraint(item: view,
attribute: .CenterX,
relatedBy: .Equal,
toItem: self,
attribute: .CenterX,
multiplier: 1,
constant: 10),
NSLayoutConstraint(item: view,
attribute: .CenterY,
relatedBy: .Equal,
toItem: self,
attribute: .CenterY,
multiplier: 1,
constant: 10),
NSLayoutConstraint(item: view,
attribute: .Width,
relatedBy: .LessThanOrEqual,
toItem: self,
attribute: .Width,
multiplier: 1,
constant: 0),
NSLayoutConstraint(item: view,
attribute: .Height,
relatedBy: .LessThanOrEqual,
toItem: self,
attribute: .Height,
multiplier: 1,
constant: 0)
])
}
Во второй версия языка операторам if и for-in добавили способности, позволяющие писать еще более компактный и читаемый код.
Теперь в условном операторе можно сравнивать с диапазоном значений:
import UIKit
let number = arc4random_uniform(50)
if case 0...25 = number {
print("Number is between 0 and 25")
} else {
print("Number is over 25")
}
И фильтровать прямо в конструкции for-in:
let numbers = [0, 1, 2, 3, -7, 12, 13, -8, -11]
for number in numbers where number >= 0 {
print("Positive number: \(number)")
}
В Xcode есть возможность добавлять в код специальные маркеры:
Первым чаще всего обозначают группы элементов, а двумя остальными — требующие доработки места.
import Foundation
class Cat {
// MARK: - Properties
// MARK: required
let breed: String!
var age: UInt!
// MARK: optional
let sex: String?
// MARK: - Initialization
init() {
breed = "siamese"
age = 1
// FIXME: Sex setting
sex = nil
}
// MARK: - Main
func walk() {
print("Walk")
}
// TODO: Write a logic
func meow() {
print("Meow...")
}
}
В панели иерархии это выглядит так: 
Кроме разметки, редактор также позволяет документировать код Markup-языком. Возможности его достаточно обширны и включают наряду с базовым описанием объектов, параметров и возвращаемых значений, различные заголовки, списки, ссылки, вставки кода, изображений и многое другое.
Для наглядности, пример с использованием основных команд:
import Foundation
/**
The `Utility` class provides various useful functions and values.
*/
class Utility {
/**
Fixes the string representation of number.
```
1.0 -> 1 (not 1.0)
0.00003 -> 0.00003 (not 3e-05)
```
- parameters:
- doubleValue: The number to be represented as the string.
- returns: The string representation of number.
*/
class func doubleToString(doubleValue: Double) -> String {
var stringValue: String
if trunc(doubleValue) == doubleValue {
stringValue = "\(Int(doubleValue))"
} else if abs(doubleValue) < 0.0001 {
stringValue = "\(doubleValue + (doubleValue.isSignMinus ? -1 : 1))"
stringValue = stringValue.stringByReplacingOccurrencesOfString("1.", withString: "0.")
} else {
stringValue = "\(doubleValue)"
}
return stringValue
}
}
Теперь эта информация будет отображаться во всплывающей подсказке и панели помощи: 
Иногда бывает необходимо выполнить дополнительные операции при изменении значений свойств. Чтобы отловить события, используются наблюдатели willSet/didSet, в работе с которыми есть нюансы.
Рассмотрим пример:
import UIKit
class Object {
var color = UIColor.greenColor() {
didSet {
color.getRed(&red, green: &green, blue: &blue, alpha: &alpha)
}
}
private(set) var red = CGFloat()
private(set) var green = CGFloat()
private(set) var blue = CGFloat()
private(set) var alpha = CGFloat()
var point = CGPoint() {
didSet {
print("Point changed to \(point)")
}
}
var name = NSMutableString() {
didSet {
print("Name changed to \(name)")
}
}
init() {
color = UIColor.redColor()
}
}
Первое — наблюдатели не вызываются при задании значений по умолчанию, а также в инициализаторе:
let object = Object()
print("Red: \(object.red), green: \(object.green), blue: \(object.blue), alpha \(object.alpha)")
// Output: Red: 0.0, green: 0.0, blue: 0.0, alpha 0.0
И второе — изменение (мутация) свойств значений не ссылочных типов (структур и перечислений) реализуется через перезапись экземпляра на новый, содержащий обновления, поэтому мутация провоцирует вызов наблюдателей. Для ссылочных типов (объектных классов) такого не происходит:
object.point = CGPoint(x: 10, y: 10)
object.point.x = 20
// Output: Point changed to (10.0, 10.0)
// Point changed to (20.0, 10.0)
object.name = NSMutableString(string: "'The new name'")
object.name.setString("Changed name")
// Output: Name changed to 'The new name'