Skip to content

Latest commit

ย 

History

History

CHAPTER4

Folders and files

NameName
Last commit message
Last commit date

parent directory

..
ย 
ย 
ย 
ย 
ย 
ย 

CHAPTER4

  • Quick demo of mutationg
  • protocols
  • String
  • NSAttributedString
  • Closures (and functions as type in general)

value type์—์„œ๋Š” copy on write (์“ฐ๊ธฐ ์‹œ ๋ณต์‚ฌ) ๊ฐ€ ์ผ์–ด๋‚˜๊ธฐ ๋•Œ๋ฌธ์— ์–ธ์ œ ๋ฐ”๋€Œ๋Š” ์ž‘์—…์„ ํ•˜๋Š”์ง€ ์•Œ์•„์•ผ ๋ฏธ๋ฆฌ ์‚ฌ๋ณธ์„ ๋งŒ๋“ค์–ด ๋‘˜ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

value type์€ ํž™ ๋ฉ”๋ชจ๋ฆฌ์— ์ €์žฅ๋˜์ง€ ์•Š๊ณ  ์‚ฌ์šฉํ•  ๋•Œ๋งˆ๋‹ค ๋งค๋ฒˆ ๋ณต์‚ฌํ•ด์•ผ ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋งค์šฐ ๋น„ํšจ์œจ์ ์ด๋‹ค. ํ•˜์ง€๋งŒ Swift์—์„œ๋Š” ๋‚ด์šฉ์ด ๋ณ€๊ฒฝ๋˜์—ˆ์„ ๋•Œ๋งŒ ๋ณต์‚ฌํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒƒ์„ copy on write ์“ฐ๊ธฐ ์‹œ ๋ณต์‚ฌ ๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค. ์ด๊ฒŒ ๋ฐ”๋กœ ๊ตฌ์กฐ์ฒด์˜ ๋‹ค๋ฅธ ์ ์ธ๋ฐ, class๋Š” ์ด๊ฒŒ ์—†๋‹ค. ์—ฌ๋Ÿฌ ๊ณณ์œผ๋กœ ์ „๋‹ฌ๋  ๋•Œ ํฌ์ธํ„ฐ๋ฅผ ์ฃผ๊ณ ๋ฐ›๋Š”๋‹ค.

Protocol

protocl ์€ swift ์ž๋ฃŒ๊ตฌ์กฐ์˜ ํ•ต์‹ฌ์„ ์ค‘ ํ•˜๋‚˜์ด๋‹ค.

protocol ์ž์ฒด๋Š” ๊ฐ„๋‹จํ•˜๋‹ค. ๊ทธ์ € ๋ณ„๋„์˜ ๊ตฌํ˜„์ด ์—†๋Š” ๋ณ€์ˆ˜์™€ ๋ฉ”์†Œ๋“œ์˜ ๋ฆฌ์ŠคํŠธ์ด๋‹ค.

ํ•˜์ง€๋งŒ ๊ทธ ์šฉ๋„๊ฐ€ ๋งค์šฐ ์ค‘์š”ํ•˜๋‹ค.

Protocol์€ ์™œ ์กด์žฌํ• ๊นŒ?

Protocol์€ ๋ฌด์—‡์ผ๊นŒ?

protocol์€ API์—์„œ ์›ํ•˜๋Š” ๊ฒƒ์„ ๋ถˆ๋Ÿฌ์˜ค๋Š” ๋ฐฉ์‹์ž…๋‹ˆ๋‹ค. ์–ด๋–ค struct, class, enum ์ƒ๊ด€์—†์ด ์–ด๋–ค ๊ฒƒ์ด๋“  ์ „๋‹ฌํ•  ์ˆ˜ ์žˆ๋‹ค.

ํ”„๋กœํ† ์ฝœ์€ API๋ฅผ ๋งค์šฐ ์œ ์—ฐํ•˜๊ณ  ๋” ์ž˜ ์ดํ•ดํ•  ์ˆ˜ ์žˆ๋„๋ก ๋งŒ๋“ค์–ด์ค๋‹ˆ๋‹ค. Blind ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜ ๊ตฌ์กฐ์— ๋งค์šฐ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค. MVC์—์„œ View์™€ Controller ๊ฐ„์˜ ์ปค๋ฎค๋‹ˆ์ผ€์ด์…˜์—์„œ will, did, should, data at, count ๋“ฑ์ด ๋ชจ๋‘ blind ์ƒํƒœ์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค. ์™œ๋ƒํ•˜๋ฉด View๋Š” ๋งค์šฐ ์ผ๋ฐ˜์ ์ธ ๋ฐ˜๋ฉด Controller๋Š” ๊ตฌ์ฒด์ ์ž…๋‹ˆ๋‹ค. ํ”„๋กœํ† ์ฝœ์ด ์ด๊ฒƒ์„ ๊ฐ€๋Šฅํ•˜๊ฒŒ ํ•ด์ฃผ๊ณ  ๊ถŒํ•œ์„ ์ฃผ๋Š”๋ฐ ์œ ์šฉํ•ฉ๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ ๋“ค์–ด, Dictionary์—์„œ ๋”•์…”๋„ˆ๋ฆฌ๋Š” ํ•ด์‹œ ํ…Œ์ด๋ธ”์ž…๋‹ˆ๋‹ค.

swift์—์„œ protocol์€ ๋ชจ๋“  ๋ฉ”์†Œ๋“œ๊ฐ€ ํ•„์ˆ˜์ ์œผ๋ก ๊ตฌํ˜„๋˜์–ด์•ผ ํ•œ๋‹ค.
ํ•˜์ง€๋งŒ objective-c์—์„œ๋Š” ๊ทธ๋ ‡์ง€ ์•Š๋‹ค. objective-c์—์„œ๋Š” ํ”„๋กœํ† ์ฝœ์˜ ๋ฉ”์†Œ๋“œ ๊ตฌํ˜„์ด ์„ ํƒ์ ์ด๋‹ค.
swift์—์„œ ์•ž์— @objc๋ฅผ ๋ถ™์—ฌ์ฃผ๋ฉด objective-c ํ”„๋กœํ† ์ฝœ์ฒ˜๋Ÿผ ์‚ฌ์šฉํ•  ์ˆ˜๊ฐ€ ์žˆ๋‹ค. @objc ๋Š” objective-c๋ฅผ ์ด์šฉํ•ด์„œ ๋””์ž์ธ ๋˜์—ˆ์„ ๋•Œ๋งŒ ์‚ฌ์šฉํ•œ๋‹ค. view์™€ controller์˜ ๋ธ”๋ผ์ธ๋“œ ๊ด€๊ณ„์—์„œ delegate๊ฐ€ objective-c์˜ ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•œ๋‹ค.

protocol ์„ ์–ธ

protocol์€ protocol์„ ์ƒ์†๋ฐ›์„ ์ˆ˜ ์žˆ๋Š”๋ฐ ์ƒ์†๋ฐ›์€ protocol์˜ ๋ฉ”์†Œ๋“œ๋ฅผ ๋ชจ๋‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

์ˆœ์ˆ˜ ์„ ์–ธ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ตฌํ˜„ ์ฝ”๋“œ๋Š” ์—†๊ณ  ๋ณ€์ˆ˜๋Š” get set ์†์„ฑ์„ ์ •ํ•ด์ฃผ์–ด์•ผ ํ•œ๋‹ค.

์ด ํ”„๋กœํ† ์ฝœ์ด ๊ตฌ์กฐ์ฒด์—์„œ ์ •์˜๋˜์—ˆ๋Š”๋ฐ, ์ˆ˜์ •๋˜์–ด์•ผ ํ•œ๋‹ค๋ฉด mutating ์„ ๋ถ™์—ฌ์ค˜์•ผ ํ•œ๋‹ค.

๋งŒ์•ฝ ํ™•์‹คํžˆ ๊ตฌ์กฐ์ฒด์—์„œ ์ •์˜๋˜์ง€ ์•Š๋Š” protocol์ด๋ผ๋ฉด : class ๋ฅผ ๋ถ™์—ฌ์„œ ๋ช…์‹œํ•ด์ค˜์•ผ ํ•œ๋‹ค.

protocol SomeProtocol: InheritedProtocol1, InheritiedProtocol2 {
  var someProperty: Int { get set }
  func aMethod(arg1: Double, anotherAgrument: String) -> SomeType
  mutating func changeIt() // ๊ตฌ์กฐ์ฒด์—์„œ ์ •์˜๋˜๊ณ  ๋ณ€๊ฒฝ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ์„ ๋•Œ
  init(arg: Type)
}

// struct์—์„œ๋Š” ์ •์˜๋  ์ˆ˜ ์—†๋Š” ๋…€์„์ด๋ผ๊ณ  ๋ช…์‹œํ•ด์คŒ.
protocol SomeProtocol: class, InheritedProtocol1, InheritiedProtocol2 {
  var someProperty: Int { get set }
  func aMethod(arg1: Double, anotherAgrument: String) -> SomeType
  func changeIt() // : class ๋ฅผ ์‚ฌ์šฉํ•ด ๊ตฌ์กฐ์ฒด์—์„œ ์ •์˜๋˜์ง€ ์•Š๋Š”๋‹ค๊ณ  ๋ช…์‹œํ•ด์คฌ๊ธฐ ๋•Œ๋ฌธ์— mutating ์ œ๊ฑฐ
  init(arg: Type)
}

protocol ์‚ฌ์šฉ

struct SomeStruct: SomeProtocol, AnotherProtocol {
  // SomeProtocol ๊ตฌํ˜„
  // SomeProtocol, AnotherProtocol์˜ ๋‚ด์šฉ์„ ๋ชจ๋‘ ๊ตฌํ˜„ํ•ด์•ผ ํ•œ๋‹ค.
}

์ •์˜์—์„œ : ๋’ค์— ์›ํ•˜๋Š” protocol์„ ๋ถ™์—ฌ์คŒ์œผ๋กœ์จ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, ๋‹น์—ฐํžˆ protocol์˜ ๋‚ด์šฉ์„ ๋ชจ๋‘ ๊ตฌํ˜„ํ•ด์ค˜์•ผ ํ•˜๊ณ , Protocol์„ ๋ช‡ ๊ฐœ๋“  ์ƒ๊ด€์—†๋‹ค. ์ด๊ฒŒ protocol์ด ๋‹ค์ค‘ ์ƒ์†์„ ์ง€์›ํ•œ๋‹ค๋Š” ์˜๋ฏธ์ด๋‹ค.

๋งŒ์•ฝ protocol ๋‚ด์— init์ด ์žˆ๊ณ  ํด๋ž˜์Šค๋กœ ๊ตฌํ˜„๋˜๋ ค๊ณ  ํ•œ๋‹ค๋ฉด, required ํ‘œ์‹œ๊ฐ€ ๋˜์–ด์žˆ์–ด์•ผ ํ•œ๋‹ค. ์™œ๋ƒํ•˜๋ฉด ์„œ๋ธŒ ํด๋ž˜์Šค๊ฐ€ ๋”ฐ๋ผ์˜ค๋Š” ๊ฒƒ์„ ์›์น˜ ์•Š๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค. ์„œ๋ธŒ ํด๋ž˜์Šค๊ฐ€ init์„ ๋ฐ›์•„์„œ ๋” ์ด์ƒ ์Šˆํผํด๋ž˜์Šค์—์„œ init์ด ์ž‘๋™ํ•˜์ง€ ์•Š์„ ์ˆ˜ ์žˆ๋‹ค. ์„œ๋ธŒํด๋ž˜์Šค์—์„œ ๊ทธ๋ ‡๊ฒŒ ํ•˜๊ธฐ๋ฅผ ์›์น˜ ์•Š๋Š” ์ด์œ ๋Š”, ๊ทธ ์„œ๋ธŒ ํด๋ž˜์Šค๋Š” ๋” ์ด์ƒ ์ด ํ”„๋กœํ† ์ฝœ์„ ๊ตฌํ˜„ํ•˜์ง€ ์•Š์ง€๋งŒ ์ƒ์†๋ฐ›์•˜๊ธฐ ๋•Œ๋ฌธ์— ๋˜๋Š”๊ฑธ๋กœ ์ƒ๊ฐํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

extension ํ™œ์šฉ

ํด๋ž˜์Šค๋‚˜ ๊ตฌ์กฐ์ฒด์—์„œ extension์„ ์‚ฌ์šฉํ•ด protocol์„ ๊ตฌํ˜„ํ•ด์ค„ ์ˆ˜๋„ ์žˆ๋‹ค.

์ฝ”๋“œ๋ฅผ ์ •๋ฆฌํ•˜๊ฑฐ๋‚˜ ํ”„๋กœํ† ์ฝœ ์ž์ฒด๋ฅผ ๊ตฌํ˜„ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•œ๋‹ค. ๋ฌถ์–ด ๋†“์œผ๋ฉด ๋ณด๊ธฐ์ข‹์•„์š” ๐Ÿ™ƒ

extension Something: SomeProtocol {
  // protocol ๊ตฌํ˜„
  // stored properties๋Š” ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.
}

protocol์„ ํƒ€์ž…์— ๋งž๊ฒŒ ์‚ฌ์šฉํ•˜๊ธฐ

protocol Moveable {
  mutating func move(to point: CGPoint)
}
class Car: Moveable {
  mutating func move(to point: CGPoint) { ... }
  func changeOil()
}
struct Shape: Moveable {
  mutating func move(to point: CGPoint) { ... }
  func draw()
}

let prius: Car = Car()
let square: Shape = Shape()

protocol ์ด๋Ÿฐ ์‹์œผ๋กœ ์ •์˜ํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

์ด์ œ ์—ฌ๊ธฐ์— ์›€์ง์ผ ์ˆ˜ ์žˆ๋Š” Moveable ๋ณ€์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•ด๋ณด์ž. prius๋Š” Moveable ํƒ€์ž…์„ ์ƒ์†๋ฐ›๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‹น์—ฐํžˆ prius๋ฅผ ํ• ๋‹นํ•  ์ˆ˜ ์žˆ๋‹ค. ํ•˜์ง€๋งŒ ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด thingToMove.move ๋Š” ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, thingToMove.changeOil์€ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค. Moveable ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์ด๋‹ค.

๊ทธ๋ฆฌ๊ณ  thingToMove์—๋Š” prius์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ Moveable์„ ์ƒ์†๋ฐ›์€ square๋„ ํ• ๋‹นํ•ด์ค„ ์ˆ˜๊ฐ€ ์žˆ๋‹ค. thingsToMove: [Moveable] ๋ผ๋Š” Moveable ๋ฐฐ์—ด๋กœ ์™„์ „ํžˆ ๋‹ค๋ฅธ ๋‘˜์„ ๊ฐ™์€ ๋ฐฐ์—ด์— ๋‘˜ ์ˆ˜๋„ ์žˆ๋‹ค.

...
var thingToMove: Moveable: prius
thingToMove.move(to: ...) // Ok
thingToMove.changeOil()		// Error!

thingToMove = square
let thingsToMove: [Moveable] = [prius, square]

Moveable ํƒ€์ž…์˜ slider๋ฅผ ๋ฐ›์•„์„œ move๋ฅผ ์‹คํ–‰ํ•˜๋Š” slide(slider:) ํ•จ์ˆ˜๋„ ๋งŒ๋“ค ์ˆ˜๊ฐ€ ์žˆ๋‹ค.

func slide(slider: Moveable) {
  let positionToSlideTo = ...
  slider.move(to: positiontoSlideTo)
}
slide(prius)
slide(square)

์—ฌ๋Ÿฌ ๊ฐœ์˜ ํ”„๋กœํ† ์ฝœ์„ ๊ตฌํ˜„ํ•ด์•ผ ํ•˜๋Š” ์ธ์ˆ˜๋ฅผ ๋ฐ›๋Š” ํ•จ์ˆ˜๋ฅผ ๊ฐ€์งˆ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

func slipAndSlide(x: Slippery & Moveable)
slipAndSlide(prius) // Error!!, prius๋Š” Slippery๋ฅผ ์ƒ์†๋ฐ›๊ณ  ์žˆ์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๋‹ค.

Protocol์˜ ํ™œ์šฉ - Delegation

protocols์˜ ์ค‘์š”ํ•œ ์‚ฌ์šฉ ๋ฐฉ์‹ ์ค‘ ํ•˜๋‚˜๋Š” View์™€ Controller ์‚ฌ์ด์— blind communication์„ ๊ตฌํ˜„ํ•˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค.

6๊ฐ€์ง€ ๊ณผ์ •์„ ๊ฑฐ์นฉ๋‹ˆ๋‹ค.

  1. ๋ทฐ๊ฐ€ Delegate protocol์„ ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค. ์—ฌ๊ธฐ์—” will, did, should์™€ ๊ฐ™์ด ๋ณด๋‚ด๊ณ ์ž ํ•˜๋Š” ๊ฒƒ์ด ๋‹ด๊ฒจ์žˆ์Šต๋‹ˆ๋‹ค.
  2. ๋ทฐ์—๋Š” public ๋ณ€์ˆ˜๋กœ delegation protocol์ธ weak delegate ๋ณ€์ˆ˜๋ฅผ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
  3. ๋ทฐ๊ฐ€ will, did, should์™€ ๊ฐ™์ด ์–ด๋–ค ๊ฒƒ์„ ๋ณด๋‚ด๊ณ  ์‹ถ์„ ๋•Œ delegate ๋ณ€์ˆ˜์— ๋ณด๋ƒ…๋‹ˆ๋‹ค.
  4. ์ปจํŠธ๋กค๋Ÿฌ๋Š” delegate protocol์„ ๊ตฌํ˜„ํ•˜๊ฒ ๋‹ค๊ณ  ์„ ์–ธํ•ฉ๋‹ˆ๋‹ค.
  5. ๊ทธ๋ฆฌ๊ณ  view์˜ delegate๋ฅผ ์ž๊ธฐ ์ž์‹ ์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.
  6. ์ปจํŠธ๋กค๋Ÿฌ๋Š” delegate protocol์„ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค.

์ด์ œ ๋ทฐ์™€ ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์—ฎ์ด๊ฒŒ ๋˜์ง€๋งŒ, ๋ทฐ์—์„  ์—ฌ์ „ํžˆ ์–ด๋””์„œ ์‚ฌ์šฉ๋˜๋Š”์ง€ ๋ชจ๋ฅธ์ฑ„ ๊ทธ์ € delegate ๋ณ€์ˆ˜์— ๋ณด๋‚ด๊ธฐ๋งŒ ํ•˜๋ฉด ๋ฉ๋‹ˆ๋‹ค.

Example

UIScrollView ์—์„œ delegate ๋ณ€์ˆ˜๋ฅผ ๊ฐ–์Šต๋‹ˆ๋‹ค.

weak var delegate: UIScrollViewDeleagte?

์™œ weak์ผ๊นŒ์š”? ์—ฌ๊ธฐ์„œ ๋ทฐ๋Š” ์ปจํŠธ๋กค๋Ÿฌ๋Š” ๊ฐ€๋ฆฌํ‚ค๋Š” ํฌ์ธํ„ฐ๋ฅผ ๊ฐ–๊ณ  ์žˆ๊ณ  ์ปจํŠธ๋กค๋Ÿฌ๋„ ๋‹ค๋ฅธ ์—ฌ๋Ÿฌ ๋ทฐ์™€ ์—ฐ๊ฒฐ๋œ ํฌ์ธํ„ฐ๋ฅผ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. Heap ๋ฉ”๋ชจ๋ฆฌ ์•ˆ์—์„œ ์œ ์ง€๋œ ์ฑ„ ๋ง์ด์ฃ . View์—์„œ ํ•˜๊ณ  ์‹ถ์€ ์ผ์€ ์ž์‹ ์˜ will, did, should๋ฅผ ๋ฐ›๋Š” ๊ฒƒ์„ ๊ฐ€๋ฆฌํ‚ค๋Š” ์ผ์ž…๋‹ˆ๋‹ค. ๋งŒ์•ฝ ๊ทธ ๋Œ€์ƒ์ด heap์„ ๋น ์ ธ๋‚˜๊ฐ€๋ ค ํ•œ๋‹ค๋ฉด, ๊ทธ๋ƒฅ ๊ทธ ๋Œ€์ƒ์„ nil๋กœ ๋ฐ”๊พธ๊ณ  ๋” ์ด์ƒ ๋ฉ”์„ธ์ง€๋ฅผ ๋ณด๋‚ด์ง€ ์•Š์œผ๋ฉด ๋ฉ๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ๋” ์ด์ƒ ๋ทฐ๋Š” ๊ฐ€๋ฆฌํ‚ค๋˜ ๋Œ€์ƒ(controller)์„ ํž™ ์•ˆ์— ๋‘์ง€ ์•Š๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

UIScrollViewDelegate ๋Š” ์ด๋ ‡๊ฒŒ ์ƒ๊ฒผ์Šต๋‹ˆ๋‹ค.

@objc protocol UIScrollViewDelegate {
  optional func scrollViewDidScroll(scrollView: UIScrollView)
  optional func viewForZooming(in scrollView: UIScrollView) -> View
  ... and many more ...
}

ViewController์—์„œ๋Š” ์ด๋ ‡๊ฒŒ delegate๋ฅผ ์ž์‹ ์œผ๋กœ ์„ค์ •ํ•ฉ๋‹ˆ๋‹ค.

class MyViewController: UIViewController, UIScrollViewDelegate {
  // @IBOutlet์˜ didSet ์—์„œ
  scrollView.delegate = self
}

Protocol์˜ ํ™œ์šฉ - Being a key in Dictionary

dictionary์˜ key๊ฐ€ ๋˜๊ธฐ ์œ„ํ•ด์„œ๋Š” unique ํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

Hashable protocol์€ uniqueํ•œ hashValue Int(ํ•ด์‹œ๊ฐ’)๋ฅผ ์ œ๊ณตํ•˜๊ณ , Hashable์„ ์ƒ์†๋ฐ›์•„ dictionary์˜ key๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

protocol Hashable: Equatable {
  var hashValue: Int { get }
}

์ฃผ๋ชฉํ•  ์ ์€ Hashable์€ Equatable protocol์„ ์ƒ์†๋ฐ›๊ณ  ์žˆ๋Š”๋ฐ, Equatable์„ ์ƒ์†๋ฐ›์Œ์œผ๋กœ์จ hashValue๊ฐ€ ๊ณ ์œ ํ•œ์ง€ ํ™•์ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Equatable์€ ์•„๋ž˜์™€ ๊ฐ™์ด ์ƒ๊ฒผ๊ณ  ๋น„๊ตํ•˜๋Š” == ๋ฉ”์†Œ๋“œ ํ•˜๋‚˜๋งŒ์„ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ •์  ๋ฉ”์†Œ๋“œ๋กœ ํƒ€์ž…์— ์ง์ ‘ ๊ด€์—ฌํ•ฉ๋‹ˆ๋‹ค. ํ•ด์‹œ ๊ฐ€๋Šฅํ•œ์ง€ ํ™•์ธํ•˜๊ธฐ ์œ„ํ•ด ์•„๋ž˜ ๋ฉ”์†Œ๋“œ๋ฅผ ๋จผ์ € ๊ตฌํ˜„ํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. ํ•ด์‹œ๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ์–ด๋–ค ํด๋ž˜์Šค์—์„œ๋„ ์ด ํ”„๋กœํ† ์ฝœ์„ ์‚ฌ์šฉํ•œ๋‹ค๋ฉด == ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

protocol Equatable {
  static func ==(lhs: Self, rhs: Self) -> Bool
}

์ฆ‰, Dictionary์˜ key๋Š” Hashable ๊ตฌํ˜„๋ฉ๋‹ˆ๋‹ค. Hashableํ•˜๊ธฐ๋งŒ ํ•˜๋‹ค๋ฉด ์–ด๋–ค ํƒ€์ž…์ด๋“  key๊ฐ€ ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Dictionary<Key: Hashable, Value>

Concentration ๊ฒŒ์ž„์—์„œ emoji Dictionary์˜ key๋กœ Int๋ฅผ ์‚ฌ์šฉํ–ˆ์—ˆ๋Š”๋ฐ, ์œ„์— ๋ฐฐ์šด ๊ฒƒ์„ ํ™œ์šฉํ•ด Card๋ฅผ key๋กœ ํ•ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ๋” ์ด์ƒ identifire๋ฅผ ๊ณต๊ฐœํ•˜์ง€ ์•Š์•„๋„ ๋ฉ๋‹ˆ๋‹ค.

struct Card: Hashable {
  
  static func ==(lhs: Self, rhs: Self) -> Bool {
    return lhs.identifire == rhs.identifire
  }
  
  private var identifier: Int
  ...
}

Protocol์˜ ํ™œ์šฉ - Multiple Inheritance ๋‹ค์ค‘ ์ƒ์†

CountableRange (๊ณ„์ˆ˜ ๊ฐ€๋Šฅ ๋ฒ”์œ„) ๋Š” ๋งŽ์€ protocols๋ฅผ ๊ตฌํ˜„ํ•ฉ๋‹ˆ๋‹ค. ๊ทธ ์ค‘ ๋‘ ๊ฐ€์ง€ Seqeunce, Collection ๋ฅผ ์‚ดํŽด๋ณด๊ฒ ์Šต๋‹ˆ๋‹ค.

Sequence : makeIterator, ํ˜„์žฌ ์š”์†Œ๊ฐ€ ์žˆ๊ณ  ๋‹ค์Œ์ด ์žˆ๋Š” ์ˆ˜๋กœ ๋‹ค์Œ ์š”์†Œ๋กœ ๋„˜์–ด๊ฐ€๋Š” next ํ•จ์ˆ˜ ๋งŒ์„ ๊ฐ–๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๊ฑธ๋กœ for in ์„ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Collection : subscripting ([ ]), index(offsetBy:), index(of:), etc ๊ฐ™์€ ๊ฒƒ๋“ค์ด ์žˆ์Šต๋‹ˆ๋‹ค.

์™œ ์ด๋ ‡๊ฒŒ ๋งŽ์€ protocol์ด ํ•„์š”ํ• ๊นŒ์š”?

Array, Set, Dictionary, String ๋“ฑ๋“ฑ Apple์˜ ๋งŽ์€ Generic ์ฝ”๋“œ๋“ค์ด ๊ฐ™์€ ๊ฒƒ์„ ๊ตฌํ˜„ํ•˜๊ณ  ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ด๋ ‡๊ฒŒ ํ•จ์œผ๋กœ์จ ํ”„๋กœ๊ทธ๋ž˜๋จธ๋Š” CountableRange๊ฐ€ ์ˆ˜์—ด์ด๋ผ๋Š” ์‚ฌ์‹ค ํ•˜๋‚˜๋งŒ ๋ฐฐ์šฐ๋ฉด ๋ฉ๋‹ˆ๋‹ค.

๋ฟ๋งŒ ์•„๋‹ˆ๋ผ ๊ธฐ๋ณธ ๊ตฌํ˜„์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค. min(), max(), index, ๋“ฑ๋“ฑ ํ•˜๋‚˜๋งŒ ๊ตฌํ˜„ํ•ด๋†“์œผ๋ฉด Array, Set, Dictionary ๋“ฑ๋“ฑ ์—ฌ๋Ÿฌ ๊ณณ์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

Swift์—์„œ ์ œ๊ณตํ•˜๋Š” Generic, Value Type, var์ด๋‚˜ let๊ฐ™์€ ๋ถˆ๋ณ€ ๋ณ€์ˆ˜ ์ œ์–ด, protocol์„ ์ด์šฉํ•œ ์ œ์•ฝ, protocol extension ๋“ฑ์€ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ์ง€์›ํ•ฉ๋‹ˆ๋‹ค. Swift์˜ ์žฅ์ ์€ ๊ฐ์ฒด์ง€ํ–ฅ๊ณผ ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์„ ๋ชจ๋‘ ์ง€์›ํ•œ๋‹ค๋Š” ์ ์ž…๋‹ˆ๋‹ค.

String

String์€ sequnce๊ฐ€ ์•„๋‹ˆ๋ผ ์œ ๋‹ˆ์ฝ”๋“œ๋กœ ์ด๋ฃจ์–ด์ ธ์žˆ์Šต๋‹ˆ๋‹ค. ์œ ๋‹ˆ์ฝ”๋“œ๋ž€ ๋ฐ”์ดํŠธ ๋‹จ์œ„์˜ ๋ฐ์ดํ„ฐ๋กœ ๊ฑฐ์˜ ๋ชจ๋“  ์–ธ์–ด๋ฅผ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. String์—์„œ Character๋Š” ๋‹จ์ˆœํžˆ ํ•˜๋‚˜์˜ ์œ ๋‹ˆ์ฝ”์˜ ๊ฐœ๋…์€ ์•„๋‹™๋‹ˆ๋‹ค. ํ•˜๋‚˜์˜ Character๋Š” ์—ฌ๋Ÿฌ ๊ฐœ์˜ ์œ ๋‹ˆ์ฝ”๋“œ์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

์˜ˆ๋ฅผ๋“ค์–ด, cafe๋Š” c-a-f-รฉ ๋กœ 4๊ฐœ์˜ ์œ ๋‹ˆ์ฝ”๋“œ์ผ ์ˆ˜๋„ ์žˆ๊ณ  c-a-f-e-' ๋กœ 5๊ฐœ์ผ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋ ‡๊ธฐ ๋•Œ๋ฌธ์— String์„ Int๋กœ ์ƒ‰์ธํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋Œ€์‹  String.Index๋ผ๋Š” ํŠน๋ณ„ํ•œ ์ƒ‰์ธ์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

์ด๋Ÿฐ์‹์œผ๋กœ ์‚ฌ์šฉํ•ด๋ณผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

var emojiChoices = "๐Ÿ‘ฟ๐ŸŽƒ๐Ÿ‘ป๐Ÿญ๐Ÿฌ๐ŸŽ"

...
let randomIndex = emojiChoices.index(emojiChoices.startIndex, offsetBy: emojiChoices.count.arc4random)
emoji[card] = String(emojiChoices.remove(at: randomIndex))

NSAttributedString

let attributes: [NSAttributedStringKey : Any]
let attributeText = NSAttributedString(string: "Flips: 0", attributes: attributes)
flipCountLabel.attributedText = attributeText

Function Type

"function type"์˜ ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ํ•จ์ˆ˜์™€ ๋งˆ์ฐฌ๊ฐ€์ง€๋กœ ๋ฐ›๋Š” ์ธ์ž์˜ ํƒ€์ž…๊ณผ ๋ฆฌํ„ด ํƒ€์ž…์„ ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

var operation: (Double) -> (Double)
operation = sqrt
let result = operation(4.0) // result will be 2.0

Closure

closure๋Š” ์ธ๋ผ์ธ ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค. ๋‹น์—ฐํžˆ ํ•จ์ˆ˜๋ฅผ ํด๋กœ์ €๋กœ ๋งŒ๋“ค ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

func changeSign(operand: Double) -> Double { return -operand }
var operation: (Double) -> (Double)
operation = chagneSign
let result = operation(4.0)

// closure
var operation: (Double) -> (Double)
operation = { (operand: Double) -> Double in return -operand }
let result = operation(4.0)

// return ํƒ€์ž…์ด ์ถ”๋ก  ๊ฐ€๋Šฅ
var operation: (Double) -> (Double)
operation = { (operand: Double) in return -operand }
let result = operation(4.0)

// ํ”ผ ์—ฐ์‚ฐ์ž ํƒ€์ž…๋„ ์ด๋ฏธ ์•Œ๊ณ  ์žˆ์Œ
var operation: (Double) -> (Double)
operation = { (operand) in return -operand }
let result = operation(4.0)

// ์ด๋ฏธ ์–ด๋–ค ๊ฒƒ์„ ๋ฆฌํ„ดํ•œ๋‹ค๋Š” ๊ฑธ ์•Œ๊ณ  ์žˆ์Œ
var operation: (Double) -> (Double)
operation = { (operand) in -operand }
let result = operation(4.0)

// ์ธ์ž๋„ ์ ์–ด์ค„ ํ•„์š”๊ฐ€ ์—†๋‹ค.
// ์ฒซ๋ฒˆ์งธ ์š”์†Œ๋ฅผ 0์œผ๋กœ $0, $1, $2 ... 
var operation: (Double) -> (Double)
operation = { -$0 }
let result = operation(4.0)

์–ธ์ œ ํด๋กœ์ €๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ• ๊นŒ

์›ํ•˜๋Š” ์‹œ์ ์— ์ž‘์—…ํ•ด์ฃผ๊ณ  ์‹ถ์„ ๋•Œ

ํ•จ์ˆ˜๋Š” ๋ฌด์—‡์„ ํ•  ์ง€ ์•Œ๋ ค์ฃผ๋Š” ์ข‹์€ ๋ฐฉ๋ฒ•์ด๋‹ค. ์–ด๋–ค ์˜ค๋ฅ˜๊ฐ€ ์žˆ์„ ๋•Œ, ์–ด๋–ค ์ž‘์—…์ด ๋๋‚ฌ์„ ๋•Œ ํ•ด์•ผํ•  ์ผ ๋“ฑ ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์„ ํด๋กœ์ €๋กœ ๋„˜๊ฒจ์ค˜์„œ ๊ทธ ์ž‘์—…์ด ํ•„์š”ํ•  ๋•Œ ํ•จ์ˆ˜๋ฅผ ๋ถˆ๋Ÿฌ์™€ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค.

๋ฐ˜๋ณต์ ์ธ ์ผ์„ ํ•  ๋•Œ

๋˜ ๋ฐ˜๋ณต์ ์ธ ์ผ์„ ํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด, ๋ฐฐ์—ด์— ๊ฐ™์€ ์ž‘์—…์„ ํ•ด์ฃผ๊ณ  ์‹ถ๋‹ค๋ฉด map์„ ์‚ฌ์šฉํ•ด ํด๋กœ์ €๋ฅผ ๋„˜๊ฒจ ์ž‘์—… ํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.

let primes = [2.0, 3.0, 5.0, 10.0]
let negativePrimes = primes.map { -$0 }
let invertedPrimes = primes.map { 1.0/$0 }
let primeStrings = primes.map { String($0) }

์†์„ฑ์„ ์ดˆ๊ธฐํ™”ํ•ด์ค„ ๋•Œ

var someProperty: Type {
  ...
  return Type
}()

lazy ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•˜๋ฉด ๋”์šฑ ํšจ๊ณผ์ ์ž…๋‹ˆ๋‹ค.

Capturing

clousure๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ ์ฃผ์˜ํ•  ์ ์€ ์ฃผ๋ณ€ ๋ณ€์ˆ˜๋ฅผ ํฌ์ฐฉํ•œ๋‹ค๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ํด๋กœ์ €๋Š” static ๋ณ€์ˆ˜๋‚˜ ์ฃผ๋ณ€ ์ง€์—ญ ๋ณ€์ˆ˜ ๋“ฑ ๋‹ค๋ฅธ ๋ณ€์ˆ˜๋ฅผ ๋ฐ›์„ ์ˆ˜๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ์ด๋•Œ ํด๋กœ์ €๋Š” reference type ์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ทธ ๋ณ€์ˆ˜๋“ค์ด ํž™ ๋ฉ”๋ชจ๋ฆฌ์— ์กด์žฌํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

var ltuae = 42
operation = { ltuae * $0 }
arrayOfOperations.append(operation)

์œ„ ์˜ˆ์ œ์—์„œ operation ํด๋กœ์ € ์•ˆ์—์„œ ์ง€์—ญ๋ณ€์ˆ˜ ltuae๋ฅผ ์‚ฌ์šฉํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  operation์€ arrayOfOperation ๋ฐฐ์—ด์— ๋“ค์–ด๊ฐ€๊ฒŒ ๋˜๋Š”๋ฐ ltuae๋ฅผ ๋ชจ๋ฅด๋ฉด ์‚ฌ์šฉํ•  ์ˆ˜๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ltuae๋Š” ํž™ ๋ฉ”๋ชจ๋ฆฌ์— ๋“ค์–ด๊ฐ€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.