Ленивые свойства

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

import Foundation

class Message {
    private(set) var lastText: String?
    
    lazy var text: String = {
        // Very long calculations...
   
        let value = "I'm lazy"

        self.lastText = value
        return value
    }()
}

let message = Message()

print(message.lastText)
// nil

print(message.text)
// I'm lazy

print(message.lastText)
// I'm lazy

Анимация в Playground

Среда Playground, впервые появившаяся в Xcode 6, незаменима для быстрого прототипирования, разработки и тестирования алгоритмов. Однако, по умолчанию в ней не отображается анимация графических объектов. Чтобы это исправить, необходимо импортировать модуль XCPlayground и задать у текущей страницы свойство liveView. После этого Assistant Editor (включается в меню View → Assistant Editor → Show Assistant Editor) станет показывать динамические изменения.

import UIKit
import XCPlayground

let view = UIView(frame: CGRect(x: 0, y: 0, width: 500, height: 500))
view.backgroundColor = UIColor(white: 0.9, alpha: 1)

let animator = UIDynamicAnimator(referenceView: view)

let gravity = UIGravityBehavior()
let collision = UICollisionBehavior()
collision.translatesReferenceBoundsIntoBoundary = true

for i in 1...50 {
    let item = UIView(frame: CGRect(x: Int(arc4random_uniform(480)),
                                    y: Int(arc4random_uniform(100)),
                                    width: 20,
                                    height: 20))

    item.backgroundColor = UIColor(red: CGFloat(drand48()),
                                   green: CGFloat(drand48()),
                                   blue: CGFloat(drand48()),
                                   alpha: 1)
    
    gravity.addItem(item)
    collision.addItem(item)
    
    view.addSubview(item)
}

animator.addBehavior(gravity)
animator.addBehavior(collision)

XCPlaygroundPage.currentPage.liveView = view
Playground live animation

Атрибуты IBInspectable и IBDesignable

Xcode 6 обзавелся новыми атрибутами, позволяющими вживую отображать ваши подклассы UIView через Interface Builder, и там же определять значения свойств. Все, что для этого нужно — пометить класс как @IBDesignable, а свойства как @IBInspectable, поддерживаемые типы: Int, CGFloat, Double, String, Bool, CGPoint, CGSize, CGRect, UIColor, UIImage.

import UIKit

@IBDesignable
class FlagView: UIView {
    @IBInspectable var firstColor: UIColor = UIColor.clearColor() {
        didSet {
           setNeedsDisplay()
        }
    }

    @IBInspectable var secondColor: UIColor = UIColor.clearColor() {
        didSet {
            setNeedsDisplay()
        }
    }

    @IBInspectable var thirdColor: UIColor = UIColor.clearColor() {
        didSet {
            setNeedsDisplay()
        }
    }

    override func drawRect(rect: CGRect) {
        let context = UIGraphicsGetCurrentContext()
        let width = bounds.width
        let height = bounds.height / 3
  
        firstColor.setFill()
        CGContextFillRect(context, CGRect(x: 0, y: 0, width: width, height: height))

        secondColor.setFill()
        CGContextFillRect(context, CGRect(x: 0, y: height, width: width, height: height))

        thirdColor.setFill()
        CGContextFillRect(context, CGRect(x: 0, y: 2 * height, width: width, height: height))
    }
}
Set FlagView class Set custom attributes

Дженерики

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

Для ее реализации Swift обладает дженериками, которые уже в полной мере задействованы в стандартной библиотеке. Например, массивы и словари, где тип элементов неизвестен вплоть до инициализации, построены с ними.

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

import UIKit

// Generic struct
struct SuperSet<T> {
    let array = [T]()
}

// Generic function
func swapTwoValues<T>(inout a: T, inout _ b: T) {
    let temporaryA = a
    a = b
    b = temporaryA
}

let superset = SuperSet<Int>()

var a: Int = 1
var b: Int = 2

swapTwoValues(&a, &b)

var c: CGFloat = 3.0
var d: CGFloat = 4.0

swapTwoValues(&c, &d)

В дополнение, параметры дженериков допускают ограничение по наследованию от определенных классов и соответствию протоколам. Для этого предназначена конструкция where.

import UIKit

protocol Swiftable {
    func swift()
}

func addSwiftableView<T where T: UIView, T: Swiftable>(swiftableView: T) {
    // Some code...
}

Основы UIStackView

Разработчики iOS SDK не так уж часто добавляют новые компоненты пользовательского интерфейса, но в 9-й версии это случилось, был представлен UIStackView.

В прямом смысле, UIStackView не является графическим элементом и не обладает визуальным представлением, поэтому изменение таких его свойств, как backgroundColor, не имеет эффекта. Единственная задача UIStackView — организация расположения объектов. По сути, он лишь выступает контейнером для других UIView (в том числе и UIStackView, что бывает полезно), которые размещает по определенным правилам.

Основные настройки призводятся свойствами:

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

Также, разработчики постарались, добавив в Interface Builder практически все настройки UIStackView, поэтому работать там с ним очень удобно, особенно, если необходимо привязывать значения к сайзклассам.