Ilya Loshkarev loshkarev.i@gmail.com
SFEDU 2016
struct Point {
var x = 0.0, y = 0.0
}
struct Size {
var width = 0.0, height = 0.0
}
let p = Point(x: 1.0, y: 1.0)
Structures have default memberwise initializers
class Rect {
var origin = Point()
var size = Size()
init() {}
init(origin: Point, size: Size) {
self.origin = origin
self.size = size
}
}
Classes don't have default memberwise initialisers
init(origin: Point, size: Size) { // designated init
self.origin = origin
self.size = size
}
Designated initializer fully initializes all proprties of the class
convenience init(center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(origin: Point(x: originX, y: originY), size: size)
}
Convenience initializer covers specific use case
of initialization parameters
class TextBox: Rect {
var text: String = ""
init(text: String, origin: Point, size: Size) { //designated init
super.init(origin: origin, size: size)
self.text = text;
}
convenience init(text: String, center: Point, size: Size) {
let originX = center.x - (size.width / 2)
let originY = center.y - (size.height / 2)
self.init(text: text, origin: Point(x: originX, y: originY),
size: size)
}
}
↑ designated delegate up ↑
← convenience delegate across →
class TextBox: Rect {
var text: String = ""
convenience init(text: String, origin: Point, size: Size) {
self.init(origin: origin, size: size)
self.text = text
}
}
var t = TextBox()
If no designated initializers declared in subclass
it inherits designated initializers of its superclass
class Rect {
required init(){}
}
class TextBox {
required init(){
super.init()
}
}
Required initializers must be implemented as
required
or final
class TextBox: Rect {
init? (text: String){
if text.characters.count == 0 { return nil }
super.init()
}
}
Failiable initializers return an optional
protocol IntContainer {
var count: UInt { get }
subscript(index: Int) -> Int { get }
mutating func append(item: Int)
}
Protocol lists methods and properties
required for implementation
class IntStackClass: IntContainer {
let elements: [Int]
var count {
return elements.count
}
subscript(index: Int) -> Int {
return elements[index]
}
func append(item: Int) {
elements.append(item)
}
}
Structures and classes that adopt a protocol
must implement all of the required members
if someObject is IntContainer {
print((someObject as! IntContainer).count)
}
// binding is always a better solution
if let container = someObject as? IntContainer {
print(container.count)
}
is
and as
can be used with protocols
func createContainer(ofSize size: UInt,
fillWith value: Int) -> IntContainer
{
// create some value conforming to IntContainer
}
let container = createContainer(ofSize: 10, fillwith:0)
let conatiners: [IntContainer]
Any value of a type that adopts required protocol
can be assigned to the variable of protocol type
You can requre multiple protocol conformance by using protocol<someProtocol, anotherProtocol>
extension Double {
var km: Double { return self * 1_000.0 }
var m: Double { return self }
var cm: Double { return self / 100.0 }
var mm: Double { return self / 1_000.0 }
var ft: Double { return self / 3.28084 }
}
let oneInch = 25.4.mm
Extensions can add new functionality to a type
but they cannot override existing functionality
Extensions cannot add stored properties
extension Int {
func times(do: () -> Void) {
for _ in 0..<self {
task()
}
}
}
3.times(do: { print("Hello! ") })
The new functionality will be availiable
on all existing instaces of a type
protocol TextRepresentable {
var description: String { get }
}
extension Int: TextRepresentable {
var description: String {
return "Integer: \(self)"
}
}
var i: TextRepresentable
i = 1
All existing instances of a type automatically adopt and conform to a protocol
extension TextRepresentable {
var description: String { // default implementation
return "I am \(self)!"
}
func printMe() {
print(self.description)
}
}
extention Double: TextRepresentable {}
Type should explicitly adopt a protocol
3.14.printMe() // "I am 3.14!"
If no implementation declared in a conforming type
default one is used
extension CollectionType where Generator.Element: TextRepresentable {
var description: String {
let itemsAsText = self.map { $0.description }
return "[" + itemsAsText.joinWithSeparator(", ") + "]"
}
}
var numbers = [3.14, 2.71, 1.8]
print(numbers.description)
enum Compass: Character {
case South = "S"
case North = "N"
case East = "E"
case West = "W"
}
Raw value of enumeration can be integer,
floating point number, string or character
print(Compass.South.rawValue)
var south = Compass(rawValue: "S")
Raw value initalizer returns an optional
enum Barcode {
case UPCA(Int, Int, Int, Int)
case QRCode(String)
}
Enumerations can store associated values of any given type
var productBarcode = Barcode.UPCA(8, 85909, 51226, 3)»
switch productBarcode {
case let .UPCA(numberSystem, manufacturer, product, check):
print("UPC-A: \(numberSystem), \(manufacturer), \(product), \(check).")
case let .QRCode(productCode):
print("QR code: \(productCode).")
}
enum Compass {
var opposite: Compass {
// return opposite direction
}
}
Enumerations can store properties and methods
Enumerations are value types
indirect enum ArithmeticExpression {
case Number(Int)
case Addition(ArithmeticExpression, ArithmeticExpression)
}
Enumeration can refer itself in its declaration
with indirect
let five = ArithmeticExpression.Number(5)
let four = ArithmeticExpression.Number(4)
let sum = ArithmeticExpression.Addition(five, four)
Global functions and interfaces from NSFoundation
are availiable in Swift
let flag = "🇷🇺"
print(flag.characters.count) // Charcter View
// Prints "1"
print(flag.unicodeScalars.count) // Unicode View
// Prints "2"
print(flag.utf16.count) // UTF-16 View
// Prints "4"
print(flag.utf8.count) // UTF-8 View
// Prints "8"
Each view has its own indices
let start = str.startIndex
let end = str.endIndex
let range = start.successor()..<end.advancedBy(-2)
str.replaceRange(range, with: " swift ")
var doubles: [Double] = []
var emptyFloats: Array = Array()
doubles.append(contentsOf: [3.0, 2.0, 1.0])
doubles += [0.0, -1.0]
var index = doubles.index(of: 2.0)
for number in doubles {
print("\(number)")
}