RW-Swift-5.1-Cheatsheet-1.0.pdf
3.21MB

Swift 5.1 관련하여 간단하게 개념만 집고가자!

 

  1. Declaring constants and variables
  2. Numeric type conversion
  3. String
  4. Tuple
  5. Optionals
  6. Collection Types: Array
  7. Collection Types: Dictionary
  8. Collection Types: Set

  9. Control Flow: Loops
  10. Control Flow: Conditionals
  11. Functions
  12. Closures
  13. Enumerations 
  14. Structs
  15. Classes
  16. Inheritance
  17. designated & Convenience Initializers

  18. Extensions
  19. Error Handling
  20. Coding Protocols
  21. Access Control
  22. 스위프트에서의 물음표와 느낌표

 

1. Declaring constants and variables

let double: Double = 2.0 
let inferredDouble = 2.0 

var mutableInt: Int = 1 


2. Numeric type conversion

let integerValue = 8 
let doubleValue = 8.0 

// error: type mismatch 
//let sum = integerValue + doubleValue 
let sum = Double(integerValue) + doubleValue 


3. String - TODO: string 비교

let helloWorld = "Hello, world" 

let helloWorldProgram = """ 
dfdf 
dfdf 
""" 

// emptyString 
let emptyString = ""        // Using string literal 
let anotherEmptyString = String() 

var mutableString = "Swift" 
mutableString += " is awesome!" 

print("This is my opinion: \(mutableString)") 


4. Tuple

- 여러 값을 group화 할 수 있는 자료형 => Tuples are useful for simple groups of related values

- decompose - let (code, reason) = httpError

- underscore (_) : ignoring parts of the tuple

- 인덱스 숫자로 접근하여 값을 가져올 수 있음

- element에 이름 추가 가능

// Group multiple values into a single compound value
// : a number and a human-readable description.
let httpError = (503, "Server Error") 

// decompose 
let (code, reason) = httpError 
let codeByIndex = httpError.0 
let reasonByIndex = httpError.1 

// _ : ignoring parts of the tuple 
let (_, justTheReason) = httpError 

// access using index numbers
print("The status code is \(http404Error.0)")

/-----------------------------------
// element 이름 추가 가능
let http200Status = (statusCode: 200, description: "OK")
print("The status code is \(http200Status.statusCode)")


5. Optionals

- 해당 자료형 값 또는 nil 값을 갖는 변수

var catchphrase: String?                     // optional String

let count3: Int?  = catchphrase?.count   // optional Int (catchphrase가 nil일 수도 있으니까요)

- ! (forced unwrapping opration) : nil이 아니면 unwrapped optional, nil이면 crash

- optional binding: if let, guard let

- ?? : coalescing operator

- ? : chaing operator

- implicitly unwarpped optionals : 강제적으로 optional unwrap

// optional: String or nil 값을 갖는 변수 
var catchphrase: String?    // called optional String 
catchphrase = "Hey, everybody?" 

// Forced uwrapping operation(!) 
// catchphrase이 nil이 아닐 경우 count 값을 가짐, nil이면 crash  
let count1: Int = catchphrase!.count 

// Optional binding 
// catchphrase?count : optional Int 
// optional Int에 값이 포함되어 있으면 count라는 constant 생성  
if let count = catchphrase?.count { 
    print(count) 
} 

// Coalescing operator (??) - coalesce: 합치다 
//catchphrase가 nil이 아니면 count2는 cathphrase의 count을 넣음; nil이면 0 
let count2: Int = catchphrase?.count ?? 0 

// Chaining operator (?) 
// Optional Int: catchphrase의 count or nil 
let count3: Int? = catchphrase?.count 

// Implicitly unwrapped optionals (implicit: 절대적인) 
let forcedCatchphrase: String! = "Hey, everybody?" 
let implicitCatchphrase = forcedCatchphrase // 값을 넣을 때 ! mark 필요 없음 


6. Collection Types: Array

- contains

- append, insert

- remove

- arr[0]

// let collection : reassign과 element 바꾸는 것 안됨 
let immutableArray: [String] = ["Alice", "Bob"] 

// 타입 추론: mutableArray [String] 
var muttableArray = ["Eve", "Frank"] 
let isEveThere = immutableArray.contains("Eve") 
let name: String = immutableArray[0] 

// index가 out of range이면 crash 
mutableArray[1] = "Bart" 

// immutableArray[1] = "Bart" // Error: 바꿀 수 없음 
mutableArray.append("Ellen") 
mutableArray.insert("Gemma", at: 1) 
let removedPerson = mutableArray.remove(at: 1) 

mutableArray = ["Ilary", "David"] 
mutableArray[0] = "John" 


7. Collection Types: Dictionary

- key가 존재하지 않으면 nil return : optional 값 리턴

- dic["name], removeValue(forKey: )

let immutableDict: [String: String] = ["name", "Kirk", "rank": "captain"] 
var mutableDict = ["name": "Picard", "rank": "captain"] 

// key가 존재하지 않으면 nil return (String? - optional String) 
let name2: String? = immutableDic["name"] 

// update value for key 
mutableDic["name"] = "Janeway" 

// add new key and value 
mutableDic["ship"] = "Voyager" 

// delete by key, 해당 key가 nil이 아니면 
let rankWasRemoved: String? = mutableDic.removeValue(forKey: "rank") 


8. Collection Types: Set

- list와 비슷하지만 중복된 item은 ignore

- contains, insert, remove

// Set: 중복된 item은 ignore 
let immutableSet: Set = ["chocolate", "vanilla", "chocolate"] 
var mutableSet: Set = ["butterscotch", "strawberry"] 

immutableSet.contains("chocolate") 
mutableSet.insert("green tea") 

// 해당 item을 찾지 못하면 nil return  
let flavorWasRemoved: String? = mutableSet.remove("strawBerry") 

9. Control Flow: Loops

// Iterator list or set 
for item in listOrSet { 
    print(item) 
} 
// Iterator over dictionary 
for (key, value) in dictionary { 
    print("\(key) = \(value)") 
} 

for i in 0...10 { 
    print(i)    // 0 to 10 
} 

for i in 0..<10 { 
    print(i)    // 0 to 9 
} 

var x = 0 
while x < 10 { 
    x += 1 
    print(x) 
} 

repeat { 
    x -= 1 
    print(x) 
} while(x > 0) 


10. Control Flow: Conditionals

let number = 88 

if (number <= 10) { 

} else if (number > 10 && number < 100) { 

} else { 

} 

// Ternary operator (ternary: 3으로 이루어진) 
let height = 100 
let isTall = height > 200 ? true : false 

// guard: program의 제어를 변형하기 위해 
for n in 1...30 { 
    guard n % 2 == 0 else { 
        continue 
    } 
    print("\(n) is even") 
} 

let year = 2012 
switch year { 
case 2003, 2004: 
    print("Panther or Tiger") 
case 2010: 
    print("Lion") 
case 2012...2015: 
    print("Mountain Lion through El Captain") 
default: 
    fatalError("Not already classified") 
} 


11. Functions

_: argument label 제외

// void function 
func sayHello() { 
    print("Hello") 
} 
// function with parameters 
func sayHello(name: String) { 
    print("Hello \(name)!") 
} 
// function with default parameters 
func sayHello(name: String = "Lorenzo") { 
    print("Hello \(name)!") 
} 

func sayHello(name: STring = "Lozenzo", age: Int) { 
    print("\(name) is \(age) years old!") 
} 

// using just the non default value 
sayHello(age: 35) 

// function with parameters and return value 
func add(x: Int, y: Int) -> Int { 
    return x + y 
} 
let value = add(x: 8, y:10) 

// single expression만 포함할 경우 return 키워드 제거 가능 
func multiply(x: Int, y: Int) -> Int { 
    x + y 
} 

// arguments label 명시 
func add(x xVal: Int, y yVal: Int) -> Int { 
    return xVal + yVal 
} 

// TODO: argement label 제외  
func add(_ x: Int, y: Int) -> Int { 
    return x + y 
} 
let value = add(8, y: 10) 

// parameter로 다른 함수 접근 
func doMath(operation: (Int, Int) -> Int, a: Int, b: Int) -> Int { 
    return operation(a, b) 
} 


12. Closures:  TODO: 실행하기

// TODO: 
let adder: (Int, Int) -> Int = {(x, y) in x + y} 
// argument의 약어 사용  
let square: (Int) -> Int = {$0 * $0} 
// 함수에 closure 전달  
let addWithClosure = doMath(operation: adder, a: 2, b: 3) 

13. Enumerations 

- allCases : CaseIterable protocol을 채택하면 사용 가능

- rawValue

- associated value(연관값): enum case문에 추가 정보를 덧붙일 수 있음 

  case text(String)

- switch문으로 associated value를 캐치할 수 있다.

  case .text(let value):

enum Taste { 
    case sweet, sour, salty, bitter, umami 
} 
let vinegarTaste = Taste.sour 

// Iterating through an enum class 
enum Food: CaseIterable { 
    case pasta, pizza, hamburger 
} 
for food in Food.allCases { 
    print(food) 
} 

// enum with String raw values 
enum Currency: String { 
    case euro = "EUR" 
    case dollar = "USD" 
    case pound = "GBP" 
} 
let euroSymbol = Currency.euro.rawValue 
print("The currency symbol for Euro is \(euroSymbol)") 

// enum with associated values 
// associated value(연관값):  
// 열거형의 케이스(case)에 추가적인 정보를 덧 붙일 수 있는 독특한 방법 
enum Content { 
    case empty 
    case text(String) 
    case number(Int) 
} 
// matching enumeration values with a switch statement 
let content = Content.text("Hello") 
switch content { 
case .empty: 
    print("Value is empty") 
case .text(let value):  // String value 추출 
    print("Value is \(value)") 
case .number(_):        // Int value ignore 
    print("Value is a number") 
} 


14. Structs

- member initializer 자동 생성됨

struct User { 
    var name: String 
    var age: Int = 40 
} 
// member initilizer는 자동적으로 생성됨. 
let john = User(name: "John", age: 35) 
// member initilizer는 기본 파라미터 값을 사용.  
// TODO: User()이렇게 해도 돼? 
let dave = User(name: "Dave") 

print("\(john.name) is \(john.age) years old") 


15. Classes

- 반드시 하나의 designated initializer를 가져야 함

- computed property

- deinit: object의 리소스가 해제될 때 수행

class Person { 
    let name: String 
    // class initializer(designated initializer) 
    init(name: String) { 
        self.name = name 
    } 
    // using deinit to perform object's resources cleanup 
    deinit { 
        print("Perfom the deinitialization") 
    } 

    var numberOfLaughts: Int = 0 
    func laugh() { 
        numberOfLaughts += 1 
    } 
    // define a computed property 
    var isHappy: Bool { 
        return numberOfLaughs > 0 
    } 
} 

let david = Person(name: "David") 
david.laugh() 
let happy = david.isHappy 


16. Inheritance

- override computed property

- final: subclass를 방지하기 위해 사용

class Student: Person { 
    var numberOfExams: Int = 0 

    // override isHappy computed property providing additional logic 
    override var isHappy: Bool { 
        numberOfLaughs > 0 && numberOfExams > 2 
    } 
} 

let ray = Student(name: "Ray") 
ray.numberOfExams = 4 
ray.laugh() 
let happy = ray.isHappy 
// final: subclass를 방지하기 위해 사용 
final class Child: Person { } 


17. designated & Convenience Initializers

- designated initializer: class는 반드시 하나 가져야 함

- convenience initializer: 옵션

// class는 반드시 최소한의 하나의 designated initilizer를 가져야 함 
// convenience initilizer는 옵션 
// TODO:  designated initilizer 정의 
class ModeOfTransportation { 
    let name: String 
    // designated initilizer 정의 
    init(name: String) { 
        self.name = name 
    } 
    // convenience initilizer 정의 
    convenience init() { 
        // 내부 designated initilizer에게 위임 
        self.init(name: "Not classified") 
    } 
} 

class Vehicle: ModeOfTransportation { 
    let wheels: Int 
     
    init(name: String, wheels: Int) { 
        self.wheels = wheels 
        // superclass의 designated initilizer로 위임 
        super.init(name: name) 
    } 
    // override superclass convenience initilizer 
    override convenience init(name: String) { 
       // 내부 designated initilizer에게 위임 
        self.init(name: name, wheels: 4) 
    } 
} 

18. Extensions

- 존재하는 class, structure, enumeration, protocol 타입에 새로운 기능 추가

- TODO: Category와 extension의 차이점은?

 extension String { 
    // String type 확장 - String instance가 truthy or falsy인지 판단 
    var boolValue: Bool { 
        if self == "1" { 
            return true 
        }  
        return false 
    } 
} 

let isTrue = "0".boolValue 


19. Error Handling

- Error protocol 채택하여 enum으로 정의

- do catch 문으로 에러 캐치

- try? : 해당 값에 error가 던져지면 nil로 반환 (optional 반환)

  try! : 해당 값에 error가 던져지면 런타임 에러(앱이 죽는다는 얘기... 절대로 에러가 발생하지 않을 경우만 사용)

// error 상속받아 enum으로 기술 
enum BeverageMatchineError: Error { 
    case invalidSelection 
    case insufficientFunds 
    case outOfStock 
} 

func selectBeverage(_ selection: Int) throws -> String { 
    return "Waiting for beverage" 
} 

// do clause의 code에 의해서 error가 던져지면 처리  
let message: String 
do { 
    message = try selectBeverage(20) 
} catch BeverageMatchineError.invalidSelection { 
    print("Invalid selection") 
} catch BeverageMatchineError.insufficientFunds { 
    print("Insufficient funds") 
} catch BeverageMatchineError.outOfStock { 
    print("Out of stock") 
} catch { 
    print("Generic error") 
} 

// try? error가 던져지면, 그 expression의 값은 nil로 처리 
let nillableMessage = try? selectBeverage(10) 

// try! : 런타임에 error를 받으면 error를 받음. 
let throwableMessage = try! selectBeverage(10) 


20. Coding Protocols

- Codable: Decodable + Encodable protocol

- JSONDecoder: JSON String -> Data

- JSONEncoder: Data -> JSON String

import Foundatation 

// Codable: Decodable, Encodable protocol 
struct UserInfo: Codable { 
    let username: String 
    let loginCount: Int 
} 

// CustomStringConvertible 채택 
extension UserInfo: CustomStringConvertible { 
    var description: String { 
        return "\(username) has tried to login \(loginCount) time(s)" 
    } 
} 

// string literal 
let json = """ 
    {"username" : "David", "loginCount" : 2} 
""" 

// JSONDecoder를 사용하여 JSON serialize : JSON string -> Data 
let decoder = JSONDecoder() 

// String을 data(struct)로 표현  
let data = json.data(using: .utf8)! 
let userInfo = try! decoder.decode(UserInfo.self, from: data) 
print(userInfo) 

// JSONEncoder 사용하여 struct serialize :  
let encoder = JSONEncoder() 
let userInfoData = try! encoder.encode(userInfo) 
// Data -> JSON String으로 표현 
let jsonString = String(data: userInfoData, encoding: .utf8)! 
print(jsonString) 


21. Access Control

- public

- fileprivate

- private

- access관련이 없을 경우

// module(framework or application): 코드가 배포의 single unit 
// public: 다른 모듈에서 접근 가능 
public class AccessLevelsShowcase { 
    public var somePublicProperty = 0 
    // ? 
    var someInternalProperty = 0 

    // 소스 파일을 정의한 것으로부터 접근 가능  
    fileprivate func someFilePrivateMethod() { } 
    //  
    private func somePrivateMethod() { } 
}


22. 스위프트에서의 물음표와 느낌표

스위프트에서 이 두 가지 구두 문자 (? 와 !)는 사용된 모든 용법에서 공통된 의미를 가지고 있음

물음표 : 무언가 확실하지 않다는 뜻

느낌표 : 경고 표지판 같은 용도, 잠재적으로 위험 동작을 수행한다.

 

옵셔널의 언랩핑과 마찬가지로 몇 라인 코드를 더 작성해야한다 할지라도 try!대신에 try try?를 사용할 것을 권장합니다. 물론 try!와 옵셔널 강제 언랩핑이 필요한 경우가 분명 존재합니다.

 

 

 

Ref. 

Ray Wenderlich website

https://outofbedlam.github.io/swift/2016/03/22/try/

+ Recent posts