Отличие ленивых свойств от обычных в моменте установки их начальных значений. У ленивых это происходит во время первого обращения к ним, а не при инициализации экземпляра. Эта особенность позволяет сдвинуть исходное задание тяжело вычисляемых свойств на потом, до их фактической надобности.
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, впервые появившаяся в 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
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))
}
}
В мире языков программирования существует парадигма обобщенной разработки. Она заключается в возможности создавать алгоритмы, одинаково работающие с разными, заранее неизвестными типами входных данных.
Для ее реализации 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...
}
Разработчики iOS SDK не так уж часто добавляют новые компоненты пользовательского интерфейса, но в 9-й версии это случилось, был представлен UIStackView.
В прямом смысле, UIStackView не является графическим элементом и не обладает визуальным представлением, поэтому изменение таких его свойств, как backgroundColor, не имеет эффекта. Единственная задача UIStackView — организация расположения объектов. По сути, он лишь выступает контейнером для других UIView (в том числе и UIStackView, что бывает полезно), которые размещает по определенным правилам.
Основные настройки призводятся свойствами:
- axis — ось (направление) расположения элементов, значение UILayoutConstraintAxis. По умолчанию — Horizontal.
- alignment — выравнивание по оси, перпендикулярной axis, значение UIStackViewAlignment. По умолчанию — Fill.
- distribution — распределение объектов вдоль оси axis, значение UIStackViewDistribution. По умолчанию — Fill.
- spacing — расстояние (для некоторых distribution минимальное) между объектами. По умолчанию — 0.
Любое из этих свойств можно изменять динамически, при этом объекты передвинутся автоматически.
Также, разработчики постарались, добавив в Interface Builder практически все настройки UIStackView, поэтому работать там с ним очень удобно, особенно, если необходимо привязывать значения к сайзклассам.