Skip to content

Latest commit

Β 

History

History

CHAPTER3

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
Β 
Β 

CHAPTER3

stride

stride λŠ” μ…€ 수 μžˆλŠ” λ²”μœ„λ₯Ό 지정해주 λŠ” λ©”μ†Œλ“œμ΄λ‹€.

이걸 μ΄μš©ν•˜λ©΄ μ†Œμˆ˜μ™€ 같은 λΆ€λ™μ†Œμˆ˜μ λ„ μ…€ μˆ˜κ°€ μžˆλ‹€.

for i in stride(from: 0.5, throught: 15.25, by: 0.3) {
  
}

Tuple

νŠœν”Œμ€ λ©”μ†Œλ“œλ‚˜ λ³€μˆ˜κ°€ μ—†λŠ” μ†Œν˜• ꡬ쑰체이닀.

κ°’λ§Œ μžˆλŠ” ν˜•νƒœμ˜ 맀우 κ°€λ²Όμš΄ ꡬ쑰체둜 μš”μ†Œμ˜ 이름을 μœ μ—°ν•˜κ²Œ μ„€μ •ν•  수 μžˆλ‹€.

let x: (String, Int, Double) = ("hello", 5, 0.85)
let (word, number, value) = x
print(word)		// print "hello"
print(number)	// print 5
print(value)	// print 0.85

let x: (w: String, i: Int, v: Double) = ("hello", 5, 0.85)
print(x.w) 	// print "hello"
print(x.i)	// print 5
print(x.v)	// print 0.85
let (wrd, num, val) = x

Computed Property

값을 어디에 μ €μž₯ν•˜μ§€ μ•Šκ³  κ³„μ‚°λœ ν˜•νƒœλ‘œ μ‚¬μš©ν•  수 μžˆλ‹€.

λ‹€λ₯Έ μ–Έμ–΄μ—μ„œ ν”νžˆ λ³΄μ΄λŠ” get set을 μ‚¬μš©ν•˜λŠ”λ°,

get없이 set만 μžˆμ„ μˆ˜λŠ” μ—†λ‹€. 그러면 ν•¨μˆ˜λ₯Ό λ§Œλ“œλŠ” 편이 λ‚«λ‹€.

Get

get은 값을 μ–»κ³ μž ν•˜λŠ” κ²½μš°μ— μ‚¬μš©ν•œλ‹€. λ”°λΌμ„œ get μ•ˆμ—μ„œλŠ” 값을 리턴해주면 λœλ‹€. set없이 get만 μ‚¬μš©ν•  λ•ŒλŠ” ꡳ이 get을 μ‚¬μš©ν•΄μ£Όμ§€ μ•Šμ•„λ„ λœλ‹€.

// lazy var game = Concentration(numberOfPairsOfCards: (cardButtons.count+1)/2)

lazy var game = Concentration(numberOfPairsOfCards: numberOfPairsOfCards)

var numberOfPairsOfCards: Int {
  return (cardButtons.count+1) / 2
}

Set

setμ—μ„œ newValueλŠ” μƒλž΅ν•΄μ€„ 수 μžˆλ‹€. 잘 ν™œμš©ν•˜λ©΄ μ½”λ“œλ₯Ό κ°„κ²°ν•˜κ³  μ§κ΄€μ μ΄κ²Œ λ§Œλ“€μ–΄μ€€λ‹€.

var indexOfOneAndOnlyFaceUpCard: Int?

func chooseCard(at index: Int) {
  if let matchIndex = indexOfOneAndOnlyFaceUpCard, matchIndex != index {
    if cards[matchIndex].identifire == cards[index].identifire {
      cards[matchIndex].isMatched = true
      cards[index].isMatched = true
    }
    cards[index].isFaceUp = true
    indexOfOneAndOnlyFaceUpCard = nil
  } else {
    for downFlipIndex in cards.indices {
      cards[downFlipIndex].isFaceUp = false
    }
    cards[index].isFaceUp = true
    indexOfOneAndOnlyFaceUpCard = index
  }
}

이 μ½”λ“œλ₯Ό μ΄λ ‡κ²Œ κ°œμ„ ν•΄μ€„ 수 μžˆλ‹€. μ΄λ ‡κ²Œ computed Propertyλ₯Ό μ‚¬μš©ν•¨μœΌλ‘œμ¨ chooseCardμ—μ„œλŠ” μ§„μ§œ μΉ΄λ“œλ₯Ό μ„ νƒν•˜λŠ” μΌμ—λ§Œ 집쀑할 수 μžˆκ²Œλœλ‹€.

var indexOfOneAndOnlyFaceUpCard: Int? {
  get {
    var foundIndex: Int?
    for index in cards.indicies {
      if cards[index].isFaceUp {
      	if indexOfOneAndOnlyFaceUpCard == nil {
          foundIndex = index
        } else {
					return nil
        }
      }
    }
    return foundIndex
  }
  
  set {
    for index in cards.indicies {
    	cards[index].isFaceUp = (index == newValue)
    }
  }
}

func chooseCard(at index: Int) {
  if let matchIndex = indexOfOneAndOnlyFaceUpCard, matchIndex != index {
    if cards[matchIndex].identifire == cards[index].identifire {
      cards[matchIndex].isMatched = true
      cards[index].isMatched = true
    }
    cards[index].isFaceUp = true
    //indexOfOneAndOnlyFaceUpCard = nil
  } else {
    /*
    for downFlipIndex in cards.indices {
      cards[downFlipIndex].isFa0ceUp = false
    }
    cards[index].isFaceUp = true
    */
    indexOfOneAndOnlyFaceUpCard = index
  }
}

Access Control

μ ‘κ·Όμ œμ–΄μžλŠ” λ³€μˆ˜λ‚˜ ν•¨μˆ˜, 클래슀 ꡬ쑰체 λ“± μ•žμ— λΆ™μ—¬μ„œ 접근을 μ œν•œν•  수 μžˆλ‹€.

internal

κΈ°λ³Έκ°’μœΌλ‘œ λ”°λ‘œ μ ‘κ·Όμ œμ–΄μžλ₯Ό μ„€μ •ν•˜μ§€ μ•ŠλŠ”λ‹€λ©΄ internal이 κΈ°λ³Έκ°’μœΌλ‘œ λ“€μ–΄κ°„λ‹€. internal은 μ•±μ΄λ‚˜ ν”„λ ˆμž„μ›Œν¬μ˜ λͺ¨λ“  μš”μ†Œκ°€ μ ‘κ·Όκ°€λŠ₯ν•œ μ½”λ“œμ΄λ‹€.

private

μ™ΈλΆ€μ—μ„œ 읽고 μ“°λŠ” 것을 μ°¨λ‹¨ν•œλ‹€.

private(set)

μ™ΈλΆ€μ—μ„œ μ½λŠ” 것은 κ°€λŠ₯ν•˜μ§€λ§Œ μˆ˜μ •μ€ μ°¨λ‹¨ν•œλ‹€.

fileprivate

파일 μ•ˆμ—μ„œλŠ” 자유둭게 읽고 μ“Έ 수 μžˆλ‹€.

public

μ™ΈλΆ€μ—μ„œ 읽을 수 μžˆμ§€λ§Œ μˆ˜μ •μ€ μ°¨λ‹¨ν•œλ‹€

open

μ™ΈλΆ€μ—μ„œ 읽고 μ“°λŠ” 것을 μ™„μ „ κ°œλ°©ν•œλ‹€.

Assertion

assert(쑰건문, κ²½κ³  메세지) 와 같은 μ‹μœΌλ‘œ μ‚¬μš©ν•œλ‹€.

쑰건문이 아닐 경우 μ—λŸ¬λ₯Ό λ°œμƒμ‹œν‚€κ³  κ²½κ³  메세지λ₯Ό 좜λ ₯ν•œλ‹€.

assert(cards.indicies.contains(index)), "Concentration.chooseCard(at: \(index)): chosen index not in the cards")

Extensions

extension을 μ΄μš©ν•΄ λ³€μˆ˜μ™€ ν•¨μˆ˜λ₯Ό λ‹€λ₯Έ ν΄λž˜μŠ€μ— μΆ”κ°€ν•  수 μžˆλ‹€.

값을 μ €μž₯ν•  수 μ—†λ‹€. κΈ°μ‘΄ 것을 ν™•μž₯ν•˜λŠ” ν˜•νƒœμ΄κΈ° λ•Œλ¬Έμ— μ €μž₯ν•˜λŠ” λ³€μˆ˜λŠ” λ‘˜ 수 μ—†λ‹€.

ν•΄λ‹Ή ν΄λž˜μŠ€μ— μ–΄μšΈλ¦¬μ§€ μ•ŠλŠ” λ³€μˆ˜λ‚˜ ν•¨μˆ˜λ₯Ό μΆ”κ°€ν•˜μ§€ μ•Šλ„λ‘ μ£Όμ˜ν•œλ‹€.

extension Int {
  var arc4random: Int {
  	return arc4random_uniform
  }
}

enum

μ—°κ΄€λœ 값을 λ¬Άμ–΄μ„œ μ •μ˜ν•  수 μžˆλ‹€. κ΅¬μ‘°μ²΄λ‚˜ ν΄λž˜μŠ€μ™€ 같이 ν•˜λ‚˜μ˜ νƒ€μž…μ΄λ‹€.

enum FastFoodItem {
  case hamburger
  case fries
  case drink
  case cookie
}

enum은 ν•„μˆ˜λŠ” μ•„λ‹ˆμ§€λ§Œ μ›ν•˜λŠ” κ²½μš°μ— 연관값을 κ°€μ§ˆ 수 μžˆλŠ”λ°, νŠœν”Œκ³Ό μœ μ‚¬ν•˜λ‹€

enum FastFoodItem {
  case hamburger(numberOfPatties: Int)
  case fries(size: FryOrderSize)
  case drink(String, ounces: Int)
  case cookie
}

enum은 ꡬ쑰체와 λ§ˆμ°¬κ°€μ§€λ‘œ μ €μž₯ 값을 κ°€μ§ˆ 수 μ—†μ§€λ§Œ λ³€μˆ˜λ‚˜ λ©”μ†Œλ“œλŠ” κ°€μ§ˆ 수 μžˆλ‹€. switchλ₯Ό μ‚¬μš©ν•΄ μ •μ˜ν•΄λ‘” μ—°κ΄€κ°’ λ˜ν•œ μ‚¬μš©ν•  수 μžˆλ‹€. fires, cookies처럼 , 둜 λ¬Άμ–΄μ„œ μ‚¬μš©ν•  μˆ˜λ„ 있고 _ λ₯Ό μ‚¬μš©ν•΄ μƒλž΅ν•  μˆ˜λ„ μžˆλ‹€.

enum FastFoodItem {
  ...
  func isIncludedInSpecialOrder(number: Int) -> Bool {
    switch self {
      case .hamburger(let patteyCount): return patteyCount == number
      case .fires, .cookies: return true
      case .drink(_, let ounces): return ounces == 16
    }
  }
  case hamburger(numberOfPatties: Int)
  case fries(size: FryOrderSize)
  case drink(String, ounces: Int)
  case cookie
}

enum의 값을 λ³€κ²½ν•  μˆ˜λ„ μžˆλŠ”λ°, κ΅¬μ‘°μ²΄λ‚˜ enum은 λ‚΄λΆ€ μƒνƒœλ₯Ό λ³€κ²½ν•  λ•ŒλŠ” λ°˜λ“œμ‹œ mutating 을 λΆ™μ—¬μ€˜μ•Ό ν•œλ‹€.

enumκ³Ό ꡬ쑰체 같은 value type은 μ“°κΈ°λ₯Ό ν•  λ•Œ λ³΅μ œκ°€ μΌμ–΄λ‚œλ‹€. μ“°κΈ°λ₯Ό μ‹€ν–‰ν•˜κΈ° μ „μ—λŠ” λ³΅μ œκ°€ μΌμ–΄λ‚˜μ§€ μ•ŠκΈ° λ•Œλ¬Έμ— μ–΄λ–€ ν•¨μˆ˜κ°€ μ“°κΈ°λ₯Ό μ›ν•˜λŠ”μ§€ μ•Œλ €μ€˜μ•Όν•œλ‹€. 이λ₯Ό μ•Œλ €μ£ΌλŠ”κ²Œ mutating 이닀.

Optional

μ˜΅μ…”λ„μ€ enum으둜 κ°œλ…μƒ μ•„λž˜μ™€ 같이 λ³Ό 수 μžˆλ‹€.

enum Optional<T> {
  case none
  case some(<T>)
}

var hello: String?							var hello: Optional<String> = .none
var hello: String? = "hello"		var hello: Optional<String> = .some("hello")
var hello: String? = nil				var hello: Optional<String> = .none

맀번 switchλ₯Ό μ‚¬μš©ν•˜λ©΄ μ½”λ“œκ°€ 길어지기 λ•Œλ¬Έμ— if let, guard, ??, ! λ“± λ‹€μ–‘ν•œ 방법을 μ œκ³΅ν•œλ‹€.

/* κ°•μ œ μ–Έλž˜ν•‘ μ‚¬μš©μ‹œ */
let hello: String? = ...
print(hello!)

// 값이 μ—†λ‹€λ©΄ ν¬λž˜μ‹œ
switch hello {
  case .none: // raise an exception (crash)
  case .some(let data): print(data)
}

/* guard */
if let greeting = hello {
 	print(greeting)
} else {
  // do something
}

// 값이 없을 λ•Œ 경우 처리
switch hello {
  case .some(let data): print(data)
  case .none: { /* do something */ }
}

Optional Chaining

μ˜΅μ…”λ„ μ²΄μ΄λ‹μ΄λž€ κ°œλ…μƒ μ•„λž˜μ™€ 같은 방식이닀, 쀑간에 μ–΄λŠ ν•˜λ‚˜λΌλ„ nil 값이 μžˆλ‹€λ©΄ nil이 λœλ‹€.

/* Optional Chaining */
let x: String? = ...
let y = x?.foo()?.bar?.z

switch x {
  case .none: y = nil
  case .some(let data1):
  	switch data1.foo() {
      case .none: y = nil
      case .some(let data2):
      	switch data2.bar {
          case .none: y = nil
          case .some(let data3): y = data3.z
        }
    }
}

Data Structures

Swiftμ—μ„œ μ•Œμ•„μ•Ό ν•  ν•„μˆ˜ 자료ꡬ쑰 4가지

  • class
  • struct
  • enum
  • protocol

Class

ν΄λž˜μŠ€λŠ” 객체지ν–₯ λ””μžμΈμ„ μ§€μ›ν•œλ‹€.

κΈ°λŠ₯κ³Ό 데이터 λͺ¨λ‘μ—κ²Œ 단일 상속을 μ§€λ‹Œλ‹€. 즉, 데이터λ₯Ό 상속

Reference Type (ν΄λž˜μŠ€λŠ” νž™μ— μ €μž₯되고 포인터λ₯Ό μ „λ‹¬ν•œλ‹€)

*Memory Management

ARC(Automatic Reference Counting)

레퍼런슀 νƒ€μž…μ€ νž™ 내에 μ‘΄μž¬ν•˜κ²Œ λ˜λŠ”λ° μ–Έμ œ μ–΄λ–»κ²Œ μ‚¬λΌμ§ˆκΉŒ? 이λ₯Ό μœ„ν•΄μ„œ Swiftμ—μ„œλŠ” ARC 방식을 μ‚¬μš©ν•œλ‹€. SwiftλŠ” νž™ 내에 μ°Έμ‘° 카운트λ₯Ό λ§Œλ“€ λ•Œλ§ˆλ‹€ SwiftλŠ” μ–΄λ”˜κ°€μ— μžˆλŠ” μΉ΄μš΄ν„°μ— 1을 λ”ν•œλ‹€. 그리고 κ°€λ¦¬ν‚€λŠ” 것이 μ—†μ–΄μ§€κ±°λ‚˜ 더 이상 가리킀지 μ•Šκ²Œ λ˜μ—ˆμ„ λ•Œ nil둜 μ„€μ •λ˜κ³  μΉ΄μš΄νŠΈκ°€ 1 μ€„μ–΄λ“€κ²Œ λœλ‹€. κ·Έλž˜μ„œ μΉ΄μš΄νŠΈκ°€ 0이 되면 νž™μ—μ„œ μ œκ±°ν•œλ‹€. 가비지 μ½œλ ‰μ…˜μ²˜λŸΌ 흔적을 μ«“κ±°λ‚˜ λ§ˆν‚Ήν•΄μ„œ μ“Έμ–΄λ²„λ¦¬λŠ”κ²Œ μ•„λ‹ˆλΌ 더 이상 κ°€λ¦¬ν‚€λŠ” 포인터가 μ—†λŠ” μ¦‰μ‹œ μ‚­μ œν•˜λŠ” 방식이닀.

Influencing ARC

reference type을 μ§€μ •ν•΄μ€ŒμœΌλ‘œμ¨ ARC 방식에 영ν–₯을 쀄 수 μžˆλ‹€.

  • strong
  • weak
  • unowned

strong - 포인터

strong 은 κΈ°λ³Έκ°’μœΌλ‘œ ν‰λ²”ν•œ μ°Έμ‘° 방식이닀. λ§Œμ•½ μ–΄λ–€ 포인터가 strong이라면 포인터가 가리킀고 μžˆλŠ” ν•œ νž™ 내에 계속 λ‘κ²Œλœλ‹€.

weak - μ˜΅μ…”λ„ 포인터!

weak 은 μƒλŒ€κ°€ λ‚˜ν•œν…Œ 관심이 μžˆμ„ λ•Œλ§Œ 관심을 κ°–λŠ”λ‹€.

νž™ 내에 μžˆλŠ” μ–΄λ–€ 것을 가리킀고 μžˆμ§€λ§Œ, λ‚˜λ‘œμΈν•΄ κ°€λ¦¬ν‚€λŠ” λŒ€μƒμ„ νž™ 내에 두지 μ•ŠλŠ”λ‹€.

λͺ¨λ“  strong 포인터가 사라지면 nil을 λ°›μ•„μ„œ νž™μ—μ„œ μ œκ±°ν•œλ‹€. λ”°λΌμ„œ weakλŠ” μ˜΅μ…”λ„ 포인터이닀.

λŒ€ν‘œμ μœΌλ‘œ oultetμ΄λ‚˜ delegateμ—μ„œ 많이 μ‚¬μš©λœλ‹€.

unowned

μ°Έμ‘°ν•˜μ§€ μ•ŠλŠ”λ‹€λŠ” μ˜λ―Έμ΄λ‹€. λ§Œμ•½ νž™ λ‚΄μ˜ μ–΄λ–€ 것을 가리킀고 μžˆμ„ λ•Œ strong ν¬μΈν„°λ‘œ μΈμ‹ν•˜μ§€ μ•Šκ³  νž™μ—μ„œ μ‚¬λΌμ‘Œμ„ λ•Œ μ ‘κ·Όν•˜μ§€ μ•ŠλŠ” 것을 μ˜λ―Έν•œλ‹€.

λ©”λͺ¨λ¦¬ 사이클을 ν”Όν•˜κΈ° μœ„ν•΄ μ‚¬μš©ν•œλ‹€.

주둜 ν΄λ‘œμ €μ—μ„œ 많이 μ‚¬μš©λœλ‹€.

λ©”λͺ¨λ¦¬ μ‚¬μ΄ν΄μ΄λž€ νž™ λ‚΄μ˜ μ–΄λ–€ 것이 νž™ λ‚΄μ˜ λ‹€λ₯Έ μ–΄λ–€ 것을 가리킀고 그게 λ‹€μ‹œ κ°€λ¦¬ν‚€λŠ” 것을 μ˜λ―Έν•œλ‹€. μ„œλ‘œ κ°€λ¦¬ν‚€λ©΄μ„œ νž™ 내에 μœ μ§€λ˜μ§€λ§Œ μ„œλ‘œλ₯Ό κ°€λ¦¬ν‚€λŠ” 것을 μ œμ™Έν•˜κ³ λŠ” 아무것도 가리킀지 μ•Šμ•„μ„œ μ“Έλͺ¨μ—†λŠ” λ©”λͺ¨λ¦¬ λ‚­λΉ„λ₯Ό μ΄ˆλž˜ν•œλ‹€.

struct

value νƒ€μž…μ΄κΈ° λ•Œλ¬Έμ— νž™ 내에 μ‘΄μž¬ν•˜μ§€ μ•Šκ³  λ³΅μ œλœλ‹€.

"copy on write" 방식인데 이λ₯Ό μ‚¬μš©ν•˜κΈ° μœ„ν•΄μ„œλŠ” mutating ν‚€μ›Œλ“œκ°€ ν•„μš”ν•˜λ‹€.

상속이 μ—†λ‹€.

enum

value νƒ€μž…, μ—°κ΄€ 값을 κ°€μ§ˆ 수 있으며

funtional inheritance (κΈ°λŠ₯ 상속)을 κ°€μ§ˆ 수 μžˆλ‹€.

protocol

κΈ°λŠ₯ μƒμ†μ΄λž€ protocol을 톡해 이루어진닀.