๊ธ€ ์ž‘์„ฑ์ž: ๊ฐœ๋ฐœํ•˜๋Š” ํ›ˆ์ด

์Šค์œ„ํ”„ํŠธ 100๋ฌธ 100๋‹ต์„ ๋ชฉํ‘œ๋กœ!

์•„๋ž˜ ์ €์žฅ์†Œ์— ๋” ๋นจ๋ฆฌ ์—…๋ฐ์ดํŠธ๋ฉ๋‹ˆ๋‹ค! ์ž˜๋ชป๋œ ๋‹ต๋ณ€์ด ์žˆ๋‹ค๋ฉด ์•Œ๋ ค์ฃผ์‹œ๊ณ , ๋” ๊ณต๋ถ€ํ• ๊ฑฐ๋ฆฌ๊ฐ€ ์žˆ๋‹ค๋ฉด 100๊ฐœ์˜ ์งˆ๋ฌธ์„ ์ฑ„์šฐ๊ธฐ ์œ„ํ•ด ๋Œ“๊ธ€์ด๋‚˜ PR๋กœ ์•Œ๋ ค์ฃผ์„ธ์š”!

 

GitHub - jeonyeohun/Getting-Ready-For-Interview: ๐Ÿฅท ๊ธฐ์ˆ ๋ฉด์ ‘์„ ์ค€๋น„ํ•˜๋Š” ์ €์žฅ์†Œ: ์šด์˜์ฒด์ œ, ๋„คํŠธ์›Œํฌ, ๋ฐ์ด

๐Ÿฅท ๊ธฐ์ˆ ๋ฉด์ ‘์„ ์ค€๋น„ํ•˜๋Š” ์ €์žฅ์†Œ: ์šด์˜์ฒด์ œ, ๋„คํŠธ์›Œํฌ, ๋ฐ์ดํ„ฐ๋ฒ ์ด์Šค, ์ž๋ฃŒ๊ตฌ์กฐ, iOS์™€ Swift๋ฅผ ๋‹ค๋ฃน๋‹ˆ๋‹ค. - GitHub - jeonyeohun/Getting-Ready-For-Interview: ๐Ÿฅท ๊ธฐ์ˆ ๋ฉด์ ‘์„ ์ค€๋น„ํ•˜๋Š” ์ €์žฅ์†Œ: ์šด์˜์ฒด์ œ, ๋„คํŠธ์›Œ

github.com

 

1. ์Šค์œ„ํ”„ํŠธ์—์„œ Extension์€ ์–ด๋–ป๊ฒŒ ์‚ฌ์šฉ๋˜๋‚˜์š”? (What are Extensions used for in Swift?)

๐Ÿ’ก Extension์€ ํด๋ž˜์Šค, ๊ตฌ์กฐ์ฒด, ์—ด๊ฑฐํ˜• ํƒ€์ž…์— ์ƒˆ๋กœ์šด ๋ฉ”์„œ๋“œ, ํ”„๋กœํผํ‹ฐ, ์ƒ์„ฑ์ž๋ฅผ ์ถ”๊ฐ€์ ์œผ๋กœ ์ •์˜ํ•ด ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ์ด๋•Œ ์ €์žฅ ํ”„๋กœํผํ‹ฐ๋Š” extension์— ์ •์˜ํ•  ์ˆ˜ ์—†๊ณ , ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ๋งŒ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ์†Œ๋ฉธ์ž(deinitializer)๋Š” ์ถ”๊ฐ€ํ•  ์ˆ˜ ์—†๊ณ  ์ƒ์„ฑ์ž๋Š” convenience init ๋งŒ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ๊ตฌ์กฐ์ฒด์˜ ๊ฒฝ์šฐ์—๋Š” ๊ธฐ์กด ๊ตฌ์กฐ์ฒด์—์„œ๋Š” ์ƒ์„ฑ์ž๋ฅผ ์ง์ ‘ ๊ตฌํ˜„ํ•˜๋ฉด memberwise initializer(๊ธฐ๋ณธ ์ƒ์„ฑ์ž)๊ฐ€ ์‚ฌ๋ผ์ง€์ง€๋งŒ ๊ตฌ์กฐ์ฒด์˜ Extension์— ์ƒ์„ฑ์ž๋ฅผ ์ •์˜ํ•˜๋ฉด memberwise initializer๊ฐ€ ์‚ฌ๋ผ์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก where์„ ์‚ฌ์šฉํ•˜๋ฉด ํŠน์ •ํ•œ ์กฐ๊ฑด์„ ๊ฐ€์ง„ ํƒ€์ž…์— ๋Œ€ํ•ด์„œ๋งŒ Extension์„ ์ ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  // https://stackoverflow.com/questions/30746190/swift-where-array-extensions
  // Idable ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๋Š” ํƒ€์ž…์˜ ๋ฐฐ์—ด๋งŒ ์ด Extension์„ ์‚ฌ์šฉ๊ฐ€๋Šฅ
  extension Array where Element : Idable {
      func filterWithId(id : String) -> [Element] {
          return self.filter { (item) -> Bool in
              return item.id == id
          }
      }
  }

 

2. Swift์˜ upcasting๊ณผ downcasting์˜ ์ฐจ์ด์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What is the difference between Upcast and Downcast in Swift?)

๐Ÿ’ก ์„œ๋กœ ์ƒ์† ๊ด€๊ณ„์— ์žˆ๋Š” ํด๋ž˜์Šค์—์„œ ์ž์‹ ํด๋ž˜์Šค๋ฅผ ๋ถ€๋ชจ ํด๋ž˜์Šค๋กœ ํƒ€์ž…์บ์ŠคํŒ… ํ•˜๋Š” ๊ฒƒ์„ ์—… ์บ์ŠคํŒ…์ด๋ผ๊ณ  ํ•˜๊ณ  as๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์—… ์บ์ŠคํŒ…ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ์ปดํŒŒ์ผ ํƒ€์ž„์— ์—…์บ์ŠคํŒ…์ด ๊ฐ€๋Šฅํ•œ์ง€ ์—ฌ๋ถ€๊ฐ€ ํŒ๋ณ„๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ์ผ์ด ๋˜๋ฉด ํ•ญ์ƒ ์„ฑ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  class Student {
      let name: String

      init(name: String) {
          self.name = name
      }
  }

  class HighSchoolStudent: Student {
      let gpa: Double

      init(name: String, gpa: Double) {
          self.gpa = gpa
          super.init(name: name)
      }
  }

  let hun = HighSchoolStudent(name: "hun", gpa: 4.5)
  let updacasted = hun as Student

  print(hun.name, hun.gpa)
  print(updacasted.name, updacasted.gpa) // compile error

๐Ÿ’ก ๋‹ค์šด์บ์ŠคํŒ…๋„ as ๋ฅผ ์‚ฌ์šฉํ•˜์ง€๋งŒ ๋‹ค์šด ์บ์ŠคํŒ…์€ ์‹คํŒจํ•  ์ˆ˜๋„ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— as?๋‚˜ as!๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก as!๋Š” ๋Ÿฐํƒ€์ž„์— ํƒ€์ž… ์บ์ŠคํŒ…์„ ํ•˜๊ณ  ๋งŒ์•ฝ ํƒ€์ž… ์บ์ŠคํŒ…์— ์‹คํŒจํ•˜๋ฉด ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.
๐Ÿ’ก as?๋Š” ๋Ÿฐํƒ€์ž„์— ํƒ€์ž… ์บ์ŠคํŒ…์„ ํ•˜๊ณ  ๋งŒ์•ฝ ํƒ€์ž… ์บ์ŠคํŒ…์— ์‹คํŒจํ•˜๋ฉด nil์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

  let donwcastedHun = hun as? HighSchoolStudent
  print(donwcastedHun) // nil

  let forcelyDowncCastedHun = hun as! HighSchoolStudent // runtime error
  print(forcelyDowncCastedHun)

 

3. == ์—ฐ์‚ฐ์ž์™€ === ์—ฐ์‚ฐ์ž๋Š” ์–ด๋–ป๊ฒŒ ๋‹ค๋ฅธ๊ฐ€์š”? (What’s the difference between == and ===?)

๐Ÿ’ก == ์—ฐ์‚ฐ์ž๋Š” ๊ฐ’์„ ๋น„๊ตํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋˜๊ณ , === ์—ฐ์‚ฐ์ž๋Š” ์ฐธ์กฐ ๊ฐ’์„ ๋น„๊ตํ•˜๋Š”๋ฐ ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.

 

4. Dispatch Queue์˜ Serial Queue์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What is a Serial Queue?)

๐Ÿ’ก ์ง๋ ฌ ํ(serial queue)๋Š” ์ž‘์—…์„ ํ•œ ๋ฒˆ์— ํ•˜๋‚˜์”ฉ ์ฒ˜๋ฆฌํ•˜๋Š” ์ž‘์—… ํ์ž…๋‹ˆ๋‹ค. ์ง๋ ฌ ํ๋Š” ์Šค๋ ˆ๋“œ์— ๋จผ์ € ํ• ๋‹นํ•œ ์ž‘์—…์ด ์™„์ „ํžˆ ๋๋‚˜์•ผ ํ์—์„œ ๋Œ€๊ธฐ ์ค‘์ธ ๋‹ค์Œ ์ž‘์—…์„ ์Šค๋ ˆ๋“œ์— ์ƒˆ๋กœ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.

 

5. let๊ณผ var์˜ ์ฐจ์ด๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”? (What is the difference between let and var in Swift?)

๐Ÿ’ก let์€ ํ•œ๋ฒˆ ํ• ๋‹น๋œ ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์—†๋Š” ์ƒ์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ธฐ ์œ„ํ•œ ๋ช…๋ น์–ด์ด๊ณ , var๋Š” ๊ฐ’์„ ๋ณ€๊ฒฝํ•  ์ˆ˜ ์žˆ๋Š” ๋ณ€์ˆ˜๋ฅผ ์„ ์–ธํ•˜๊ธฐ ์œ„ํ•œ ๋ช…๋ น์–ด์ž…๋‹ˆ๋‹ค.
๐Ÿ’ก ์‚ฌ์‹ค Obejctive-C ๊ด€์ ์—์„œ let์€ ์ฃผ์†Œ์— ๋Œ€ํ•œ ํฌ์ธํ„ฐ๋ฅผ ๋ฐ”๊ฟ€ ์ˆ˜ ์—†๋‹ค๋Š” ์˜๋ฏธ์ž…๋‹ˆ๋‹ค. ์ด ๋•Œ๋ฌธ์— ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค์˜ var๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜์˜ ๊ฐ’์„ ๋ฐ”๊พธ๋Š” ๊ฒƒ์€ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

  let hun = Student(name: "hun")
  hun.name = "hunihun965"

  print(hun.name) // hunihun956

 

6. function๊ณผ method์˜ ์ฐจ์ด๋ฅผ ๋งํ•ด๋ณด์„ธ์š”. (What are the differences between functions and methods in Swift?)

๐Ÿ’ก function์€ ์žฌ์‚ฌ์šฉ ๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ ๋ธ”๋ก์„ ์˜๋ฏธํ•˜๊ณ , method๋Š” ํด๋ž˜์Šค, ๊ตฌ์กฐ์ฒด, ์—ด๊ฑฐํ˜•์— ํฌํ•จ๋˜๋Š” function์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

 

7. ์ปค์Šคํ…€ ๊ฐ์ฒด์˜ ๋ฐฐ์—ด์ด ์žˆ์„ ๋•Œ, ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ธฐ์ค€์œผ๋กœ ๋ฐฐ์—ด์„ ์–ด๋–ป๊ฒŒ ์ •๋ ฌํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”? (How to sort array of custom objects by property value in Swift?)

๐Ÿ’ก sorted ๋ฉ”์„œ๋“œ์— ์ง์ ‘ ์†ŒํŒ… ํด๋กœ์ €๋ฅผ ์ง€์ •ํ•ด์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  struct Node {
      let id: Int
  }

  let array = [
      Node(id: 5),
      Node(id: 4),
      Node(id: 3),
      Node(id: 2),
      Node(id: 1)
  ]

  let sorted = array.sorted(by: { $0.id < $1.id })
  print(sorted)
  // [PS.Node(id: 1), PS.Node(id: 2), PS.Node(id: 3), PS.Node(id: 4), PS.Node(id: 5)]

 

8. mutaing ํ‚ค์›Œ๋“œ์˜ ์˜๋ฏธ๋ฅผ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What does the Swift mutating keyword mean?)

๐Ÿ’ก ์Šค์œ„ํ”„ํŠธ์—์„œ ๊ฐ’ ํƒ€์ž… ํ”„๋กœํผํ‹ฐ๋“ค์„ ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ์— ์˜ํ•ด ์ˆ˜์ •๋  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก mutaing ํ‚ค์›Œ๋“œ๋ฅผ ๋ฉ”์„œ๋“œ ์•ž์— ๋ถ™์ด๋ฉด ๊ตฌ์กฐ์ฒด๋‚˜ ์—ด๊ฑฐํ˜• ์ธ์Šคํ„ด์Šค์—์„œ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ˆ˜์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก mutating ํ‚ค์›Œ๋“œ๊ฐ€ ๋ถ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์Šค์œ„ํ”„ํŠธ๋Š” ์ƒˆ๋กœ์šด ๊ตฌ์กฐ์ฒด๋ฅผ ์ƒ์„ฑํ•ด ๋ณ€๊ฒฝ๋œ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์„ ํ• ๋‹นํ•˜๊ณ  ๋ฐ˜ํ™˜ํ•ด ํ˜„์žฌ ๊ตฌ์กฐ์ฒด๋ฅผ ๋Œ€์ฒดํ•ฉ๋‹ˆ๋‹ค. ๊ตฌ์กฐ์ฒด์˜ ๋ถˆ๋ณ€์„ฑ์„ ์ง€ํ‚ค๊ธฐ ์œ„ํ•ด ์ด๋Ÿฐ ๋ฐฉ๋ฒ•์„ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

9. ํ”„๋กœํ† ์ฝœ๊ณผ ํด๋ž˜์Šค์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What’s the difference between a protocol and a class in Swift?)

๐Ÿ’ก ํด๋ž˜์Šค๋Š” ์ธ์Šคํ„ด์Šค ๋ฉ”์„œ๋“œ์˜ ์‹ค์ œ ๊ตฌํ˜„์ฒด๋ฅผ ๊ฐ€์ง€๊ณ  ์žˆ์ง€๋งŒ ํ”„๋กœํ† ์ฝœ์€ ๋ฉ”์„œ๋“œ์˜ ์ธํ„ฐํŽ˜์ด์Šค๋งŒ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค. ํ”„๋กœํ† ์ฝœ์ด ๊ตฌํ˜„์ฒด๋ฅผ ๊ฐ€์ง€๊ฒŒ ํ•˜๋ ค๋ฉด ํ”„๋กœํ† ์ฝœ์˜ Extension์„ ๋งŒ๋“ค์–ด ๊ตฌํ˜„์ฒด๋ฅผ ์ž‘์„ฑํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

10. Enum์—์„œ raw value์™€ associated value์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (In Swift enumerations, what’s the difference between raw values and associated values?)

๐Ÿ’ก raw value๋Š” ์›์‹œ๊ฐ’์œผ๋กœ ์—ด๊ฑฐํ˜•์˜ ๋ชจ๋“  case๋“ค์ด ๋™์ผํ•œ ํƒ€์ž…์„ ๊ฐ€์ง€๊ณ  ํ•˜๋‚˜์˜ ๊ฐ’๋งŒ ๊ฐ€์งˆ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ๋ฐ˜๋ฉด์— associated value๋Š” ํŠœํ”Œ์„ ํ†ตํ•ด ๊ฐ case๋“ค์ด ๋‹ค๋ฅธ ํƒ€์ž…์„ ๊ฐ€์ง€๊ฒŒ ํ•  ์ˆ˜๋„ ์žˆ๊ณ , named tuple๋กœ ์ด๋ฆ„์„ ๋ถ™์ผ ์ˆ˜๋„ ์žˆ์œผ๋ฉฐ, ์—ฌ๋Ÿฌ๊ฐœ์˜ ๊ฐ’์„ ๊ฐ€์ง€๊ฒŒ ํ•˜๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

  // associated values
  enum Fruits {
  case apple(origin: String, cost: Double)
  case grape(origin: String, cost: Double, size: Double)
  case orange(color: String)
  }

  let apple: Fruits = .apple(origin: "Korea", cost: 1000)
  let grape: Fruits = .grape(origin: "Korea", cost: 100, size: 10)
  let orange: Fruits = .orange(color: "Orange")

  // raw values
  enum Numbers: Int {
  case one = 1
  case two, three, four
  }

  print(Numbers.one.rawValue)   // 1
  print(Numbers.two.rawValue)   // 2
  print(Numbers.three.rawValue) // 3

 

11. inout์€ ์–ธ์ œ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์„๊นŒ์š”? (What is a good use case for an inout parameter?)

๐Ÿ’ก inout ํŒŒ๋ผ๋ฏธํ„ฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ๊ฐ’ ํƒ€์ž… ๋ณ€์ˆ˜๊ฐ€ ์ €์žฅ๋œ ์ฃผ์†Œ์˜ ๊ฐ’์„ ํ•จ์ˆ˜ ์•ˆ๊ณผ ๋ฐ–์—์„œ ๋™์ผํ•˜๊ฒŒ ์‚ฌ์šฉํ•˜๊ฒŒ ๋ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•จ์ˆ˜๊ฐ€ ์ž…๋ ฅ๊ณผ ๋™์ผํ•œ ์ถœ๋ ฅ์„ ์ œ๊ณตํ•˜๊ณ , ํ•จ์ˆ˜ ๋‚ด์—์„œ ์ ์šฉ๋œ ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ํ•จ์ˆ˜ ์™ธ๋ถ€์—์„œ๋„ ๋™์ผํ•˜๊ฒŒ ์ ์šฉ๋˜์–ด์•ผํ•  ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก Swap์„ ์ง์ ‘ ๊ตฌํ˜„ํ•˜๊ณ ์ž ํ•œ๋‹ค๋ฉด inout์ด ์ข‹์€ ์„ ํƒ์ด ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  // https://stackoverflow.com/questions/62266178/swift-function-that-swaps-two-values
  func swap<T>(a: inout T, b: inout T) {
      (a, b) = (b, a)
  }
  var a = 0, b = 1
  swap(a: &a, b: &b)

 

12. ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ์™€ ํด๋กœ์ €๋ฅผ ๊ฐ€์ง€๋Š” ์ €์žฅ ํ”„๋กœํผํ‹ฐ์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What is the difference between a computed property and a property set to a closure?)

๐Ÿ’ก ํด๋กœ์ €๋ฅผ ๊ฐ€์ง€๋Š” ์ €์žฅ ํ”„๋กœํผํ‹ฐ๋Š” ํ”„๋กœํผํ‹ฐ์˜ ์ƒ์„ฑ์‹œ์ ์— ํด๋กœ์ €๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ๋˜ํ•œ var ํ‚ค์›Œ๋“œ๋กœ ์ƒ์„ฑ๋˜์–ด ์žˆ๋‹ค๋ฉด ๋‹ค๋ฅธ ํด๋กœ์ €๋ฅผ ํ• ๋‹นํ•ด์ฃผ๋Š” ๊ฒƒ๋„ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ๋Š” ํ”„๋กœํผํ‹ฐ๋ฅผ ์ฐธ์กฐํ•  ๋•Œ๋งˆ๋‹ค ํด๋กœ์ €๋ฅผ ์ƒ์„ฑํ•˜๊ณ  ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.

 

13. as? ์™€ as! ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What is difference between as?, as! and as in Swift?)

๐Ÿ’ก as? ์™€ as! ๋ชจ๋‘ ๋Ÿฐํƒ€์ž„์— ๋‹ค์šด ์บ์ŠคํŒ…์„ ์œ„ํ•ด ์‚ฌ์šฉ๋˜์ง€๋งŒ as? ๋Š” ์บ์ŠคํŒ…์— ์‹คํŒจํ–ˆ์„ ๋•Œ nil์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  as! ๋Š” ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๋ฅผ ๋ฐœ์ƒ์‹œํ‚ต๋‹ˆ๋‹ค.

 

14. ๋ฉ”์„œ๋“œ ์•ˆ์—์„œ ์–ธ์ œ self๋ฅผ ์‚ฌ์šฉํ•ด์•ผํ• ๊นŒ์š”? (When would you use self in a method?)

๐Ÿ’ก ํŒŒ๋ผ๋ฏธํ„ฐ์˜ ์ด๋ฆ„์ด ์ธ์Šคํ„ด์Šค์˜ ํ”„๋กœํผํ‹ฐ ์ด๋ฆ„๊ณผ ๊ฒน์น  ๊ฒฝ์šฐ์— ์ธ์Šคํ„ด์Šค์˜ ํ”„๋กœํผํ‹ฐ์ž„์„ ๋ช…์‹œํ•˜๊ธฐ ์œ„ํ•ด์„œ self๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

15. Class์™€ Struct์˜ ๊ณตํ†ต์ ๊ณผ ์ฐจ์ด์ ์„ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What Classes and Structs have in common in Swift and what are their differences?)

๐Ÿ’ก Class ์™€ Struct ๋ชจ๋‘ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ •์˜ํ•ด ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅํ•˜๊ณ  ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค์–ด ๊ฐ์ฒด์˜ ํ˜•ํƒœ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก Class ์™€ Struct ๋ชจ๋‘ ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก Class ๋Š” ์ฐธ์กฐ ํƒ€์ž…์ด์ง€๋งŒ Struct๋Š” ๊ฐ’ ํƒ€์ž…์ž…๋‹ˆ๋‹ค.
๐Ÿ’ก Class ๋Š” ์ฐธ์กฐ ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์— ์ตœ์ ํ™”๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์ง€๋งŒ ๊ตฌ์กฐ์ฒด๋Š” ๊ฐ’ ํƒ€์ž…์˜ ๋ณต์‚ฌ๋ฅผ ์ตœ์ ํ™”ํ•˜๊ธฐ ์œ„ํ•ด์„œ Copy-On-Write๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ์‹ค์ œ๋กœ ๋ณ€๊ฒฝ์ด ์ผ์–ด๋‚˜๊ธฐ ์ „๊นŒ์ง€๋Š” ๊ตฌ์กฐ์ฒด๋ฅผ ๋‹ค๋ฅธ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•˜๋”๋ผ๋„ ๊ฐ™์€ ์ฃผ์†Œ์˜ ๊ตฌ์กฐ์ฒด๋ฅผ ๊ณต์œ ํ•˜๋‹ค๊ฐ€ ๋ณ€๊ฒฝ์ด ๋ฐœ์ƒํ•˜๋ฉด ์ƒˆ๋กœ์šด ์ฃผ์†Œ์— ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•ด ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก Class ๋Š” ํž™ ์˜์–ต์— ์ธ์Šคํ„ด์Šค๋ฅผ ์ €์žฅํ•˜๊ณ  ์ธ์Šคํ„ด์Šค์˜ ์ฃผ์†Œ๊ฐ’์„ ์Šคํƒ ์˜์—ญ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด์— Struct๋Š” ์Šคํƒ ์˜์—ญ์— ์ธ์Šคํ„ด์Šค๊ฐ€ ์ €์žฅ๋ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก Class ๋Š” ์ธ์Šคํ„ด์Šค๋ผ๋ฆฌ์˜ ์ƒ์†์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ Struct๋Š” ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค. ๋Œ€์‹  ํ”„๋กœํ† ์ฝœ์„ ํ†ตํ•ด ์ƒ์†์˜ ๋™์ž‘์„ ๊ตฌํ˜„ํ•  ์ˆ˜๋Š” ์žˆ์Šต๋‹ˆ๋‹ค.

 

16. ๊ฐ•ํ•œ ์ฐธ์กฐ๋Š” ๋ฌด์—‡์ด๊ณ  ์™œ ํ•„์š”ํ•œ๊ฐ€์š”? (What’s a strong reference, and why do we need it?)

๐Ÿ’ก ๊ฐ•ํ•œ ์ฐธ์กฐ๋Š” ์ฐธ์กฐ ํƒ€์ž… ์ธ์Šคํ„ด์Šค๋ฅผ ๋ณ€์ˆ˜์— ํ• ๋‹นํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์Šค์œ„ํ”„ํŠธ์˜ ARC๋Š”๊ฐ•ํ•œ ์ฐธ์กฐ์— ์ฐธ์กฐ ์นด์šดํŠธ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค๊ณ , ๊ฐ•ํ•œ ์ฐธ์กฐ๊ฐ€ ํ•ด์ œ๋˜๋ฉด ์ฐธ์กฐ ์นด์šดํŠธ๋ฅผ ๊ฐ์†Œ์‹œํ‚ต๋‹ˆ๋‹ค.
๐Ÿ’ก ์ฐธ์กฐ ์นด์šดํŠธ๊ฐ€ 0์ด ๋˜๋ฉด ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ธ์Šคํ„ด์Šค๋ฅผ ํ•ด์ œํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ๋”ฐ๋ผ์„œ ๊ฐ•ํ•œ ์ฐธ์กฐ๊ฐ€ ์žˆ์–ด์•ผ๋งŒ ์Šค์œ„ํ”„ํŠธ์—์„œ ์ฐธ์กฐ ํƒ€์ž…์˜ ์ธ์Šคํ„ด์Šค๋ฅด ๋ฉ”๋ชจ๋ฆฌ์— ์œ ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

17. strong, weak, unowned reference๋Š” ๊ฐ๊ฐ ์–ธ์ œ ์‚ฌ์šฉํ• ๊นŒ์š”? (When to use strong, weak and unowned references?)

๐Ÿ’ก ๋ฉ”๋ชจ๋ฆฌ์—์„œ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•ด์ œ๋˜๋Š” ๊ฒƒ์„ ๋ง‰๊ธฐ ์œ„ํ•ด ๊ฐ•ํ•œ ์ฐธ์กฐ์ธ strong reference๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. strong reference๋Š” ์ฐธ์กฐ ์นด์šดํŠธ๋ฅผ 1 ์ฆ๊ฐ€์‹œํ‚ค๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ๊ธฐ๋ณธ์ ์œผ๋กœ ์ฐธ์กฐ์˜ ๋ฐฉํ–ฅ์ด ๋‹จ๋ฐฉํ–ฅ์œผ๋กœ ์ด๋ฃจ์–ด์ง€๋ฉด strong reference๋Š” ํ•ญ์ƒ ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก weak reference๋Š” ์ฐธ์กฐ ์นด์šดํŠธ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. weak reference๋Š” ํ•ญ์ƒ var ๋กœ ์„ ์–ธ๋˜๋Š” ์˜ต์…”๋„ ํƒ€์ž…์ด ๋˜์–ด์•ผํ•ฉ๋‹ˆ๋‹ค. weak์œผ๋กœ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•ด์ œ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค. ์ˆœํ™˜ ์ฐธ์กฐ์˜ ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ์ƒํ™ฉ์—์„œ weak์„ ํ†ตํ•ด ๋ฐฉ์ง€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก unowned reference๋Š” weak ๊ณผ ๋™์ผํ•˜๊ฒŒ ์ฐธ์กฐ ์นด์šดํŠธ๋ฅผ ์ฆ๊ฐ€์‹œํ‚ค์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๊ทธ๋ฆฌ๊ณ  ๋™์‹œ์— unowned ๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๋Š” nil์„ ๊ฐ€์งˆ ์ˆ˜ ์—†๋‹ค๋Š” ํŠน์ง•์ด ์žˆ์Šต๋‹ˆ๋‹ค. unowned ๋กœ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•ด์ œ๋˜๋ฉด unowned ๋Š” nil์ด ์•„๋‹ˆ๋ผ ๋” ์ด์ƒ ์ฐธ์กฐํ•  ์ˆ˜ ์—†๋Š” ์ฃผ์†Œ๋ฅผ ๊ณ„์† ์ฐธ์กฐํ•˜๊ฒŒ ๋˜๊ณ  unowned ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋ ค๊ณ  ํ•˜๋ฉด ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ unowned๋Š” ํ•ด๋‹น ๋ณ€์ˆ˜๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ์ธ์Šคํ„ด์Šค๋ณด๋‹ค ๋จผ์ € ํ•ด์ œ๋˜๋Š” ๊ฒƒ์ด ํ™•์‹คํ•œ ์ƒํ™ฉ์—์„œ๋งŒ ์‚ฌ์šฉํ•ด์•ผ ํ•ฉ๋‹ˆ๋‹ค. Optional์ด ์•„๋‹ˆ๊ธฐ ๋•Œ๋ฌธ์— ์บก์ณ ๋ฆฌ์ŠคํŠธ๋‚˜ ์˜ต์…”๋„ ๋ฐ”์ธ๋”ฉ์„ ์‚ฌ์šฉํ•˜์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.

 

18. Array, Set, Dictionary์˜ ์ฐจ์ด์ ์ด ๋ญ˜๊นŒ์š”? (What's the main difference between the Array, Set and Dictionary collection type?)

๐Ÿ’ก Array๋Š” ๋ฆฌ์ŠคํŠธ ์ปฌ๋ ‰์…˜์œผ๋กœ Random Access๊ฐ€ ๊ฐ€๋Šฅํ•ด ์ธ๋ฑ์Šค๋ฅผ ํ†ตํ•ด ์š”์†Œ์— ์ ‘๊ทผํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก Set์€ Hashable ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๋Š” ๊ฐ’์„ ์ €์žฅํ•ด ์ค‘๋ณต๋˜์ง€ ์•Š์€ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ฝœ๋ ‰์…˜์ž…๋‹ˆ๋‹ค. ์ˆœ์„œ๊ฐ€ ๋ณด์žฅ๋˜์ง€ ์•Š์œผ๋ฉฐ, ๊ต์ง‘ํ•ฉ, ์ฐจ์ง‘ํ•ฉ ๋“ฑ ์ง‘ํ•ฉ ์—ฐ์‚ฐ์„ ๋ฉ”์„œ๋“œ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก Dictionary ๋Š” Key-Value ํ˜•ํƒœ๋กœ ๋ฐ์ดํ„ฐ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ์ฝœ๋ ‰์…˜์ž…๋‹ˆ๋‹ค. ๋”•์…”๋„ˆ๋ฆฌ์˜ Key๋กœ ์‚ฌ์šฉ๋  ํƒ€์ž…์€ Hashable ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๊ณ  ์ค‘๋ณต๋œ ํ‚ค๋ฅผ ํ—ˆ์šฉํ•˜์ง€ ์•Š์œผ๋ฉฐ ์ˆœ์„œ๋ฅผ ๋ณด์žฅํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

19. required ํ‚ค์›Œ๋“œ์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What does the required keyword in Swift mean?)

๐Ÿ’ก required ํ‚ค์›Œ๋“œ๊ฐ€ ๋ถ™์€ ํด๋ž˜์Šค์˜ ์ƒ์„ฑ์ž๋Š” ํ•ด๋‹น ํด๋ž˜์Šค๋ฅผ ์ƒ์†๋ฐ›๋Š” ์ž์‹ ํด๋ž˜์Šค๊ฐ€ ํ•ด๋‹น ์ƒ์„ฑ์ž๋ฅผ ๋ฐ˜๋“œ์‹œ ๊ตฌํ˜„ํ•˜๋„๋ก ๊ฐ•์ œํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก required ์—๋Š” override ํ‚ค์›Œ๋“œ์˜ ๊ธฐ๋Šฅ์ด ํฌํ•จ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— override๋ฅผ ์ƒ๋žตํ•˜๊ณ  ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

20. Self์™€ self์˜ ์ฐจ์ด๊ฐ€ ๋ญ˜๊นŒ์š”? (What's the difference between Self vs self?)

๐Ÿ’ก self๋Š” ํ˜„์žฌ ์ธ์Šคํ„ด์Šค๋ฅผ ๊ฐ€๋ฆฌํ‚ต๋‹ˆ๋‹ค.
๐Ÿ’ก Self๋Š” ํ”„๋กœํ† ์ฝœ์—์„œ ์‚ฌ์šฉ๋˜๋ฉด ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๋Š” ํƒ€์ž…์„ ์˜๋ฏธํ•˜๊ณ , ํด๋ž˜์Šค, ๊ตฌ์กฐ์ฒด, ์—ด๊ฑฐํ˜•์—์„œ ์‚ฌ์šฉ๋˜๋ฉด ์‹ค์ œ ์„ ์–ธ์— ์‚ฌ์šฉ๋œ ํƒ€์ž…์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

  class Superclass {
  func f() -> Self { return self }
  }
  let x = Superclass()
  print(type(of: x.f()))
  // Prints "Superclass"

  class Subclass: Superclass { }
  let y = Subclass()
  print(type(of: y.f()))
  // Prints "Subclass"

  let z: Superclass = Subclass()
  print(type(of: z.f()))
  // Prints "Subclass"

-> MetaType์— ๋Œ€ํ•œ ๊ณต๋ถ€๊ฐ€ ํ•„์š”ํ•  ๊ฒƒ ๊ฐ™์Šต๋‹ˆ๋‹คใ…  ํ—ท๊ฐˆ๋ฆฌ๋„ค์š”..

 

21. Array๋ณด๋‹ค Set์„ ์‚ฌ์šฉํ•˜๋Š”๊ฒŒ ๋” ์ข‹์„ ๋•Œ๋Š” ์–ธ์ œ์ผ๊นŒ์š”? (When to use a set rather than an array in Swift?)

๐Ÿ’ก ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•˜์ง€ ์•Š๊ณ  ๋ฐ์ดํ„ฐ๋ฅผ ์ค‘๋ณต์—†์ด ๊ณ ์œ ํ•˜๊ฒŒ ๊ด€๋ฆฌํ•  ๋•Œ Set์„ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ํŠนํžˆ, Set์€ ์‚ญ์ œ, ์‚ฝ์ž…, ์กฐํšŒ๋ฅผ ๋ชจ๋‘ O(1)์— ํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ์ˆœ์„œ๊ฐ€ ์ค‘์š”ํ•˜์ง€ ์•Š์œผ๋ฉด์„œ ์‚ญ์ œ์™€ ์‚ฝ์ž…์ด ๋นˆ๋ฒˆํ•  ๋•Œ๋„ Set์ด ๋” ์ข‹์„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

22. Trailing Closure์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What is trailing closure syntax?)

๐Ÿ’ก ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋“ค์–ด๊ฐˆ ํด๋กœ์ €๋ฅผ ํ•จ์ˆ˜ ํ˜ธ์ถœ ์™ธ๋ถ€๋กœ ๋ถ„๋ฆฌํ•ด์„œ ์ฝ”๋“œ๋ฅผ ์ž‘์„ฑํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
๐Ÿ’ก trailing closure์˜ ํŒŒ๋ผ๋ฏธํ„ฐ ๋ ˆ์ด๋ธ”์„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ๊ณ , ๋งŒ์•ฝ ํ˜ธ์ถœํ•˜๋Š” ํ•จ์ˆ˜์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ํด๋กœ์ € ๋ฟ์ด๋ผ๋ฉด () ๋„ ์ƒ๋žตํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  func someFunctionThatTakesAClosure(closure: () -> Void) {
  // function body goes here
  }

  // Here's how you call this function without using a trailing closure:

  someFunctionThatTakesAClosure(closure: {
      // closure's body goes here
  })

  // Here's how you call this function with a trailing closure instead:

  someFunctionThatTakesAClosure() {
      // trailing closure's body goes here
  }

 

23. @objc๋Š” ์–ธ์ œ ์‚ฌ์šฉํ•˜๋‚˜์š”? (When to use @objc attribute?)

๐Ÿ’ก @objc ๋Š” ์Šค์œ„ํ”„ํŠธ์˜ API๋ฅผ Objective-C ๋Ÿฐํƒ€์ž„์— ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

24. deinit์€ ์–ธ์ œ ์‚ฌ์šฉํ• ๊นŒ์š”? (When should I use deinit?)

๐Ÿ’ก deinit์€ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜๊ธฐ ์ง์ „์— ํ˜ธ์ถœ๋ฉ๋‹ˆ๋‹ค. ์ธ์Šคํ„ด์Šค๋ฅผ ํ•ด์ œํ•˜๊ธฐ ์ „์— ์„ ํ–‰๋˜์–ด์•ผ ํ•˜๋Š” ์ž‘์—…์ด ์žˆ๋‹ค๋ฉด deinit์— ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

25. DispatchQueue.main.async ์™€ DispatchQueue.main.sync ์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (Explain the difference between DispatchQueue.main.async and DispatchQueue.main.sync?)

๐Ÿ’ก ๋‘ ๋ฐฉ๋ฒ• ๋ชจ๋‘ DispatchQueue์— ์ž‘์—…์„ ๋“ฑ๋กํ•˜๊ณ  Main ์Šค๋ ˆ๋“œ์—์„œ ์ž‘์—…์ด ์ˆ˜ํ–‰๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก DispatchQueue.main.async๋Š” ์ž‘์—…์„ ๋“ฑ๋กํ•  ๋•Œ async ํ•˜๊ฒŒ ๋“ฑ๋กํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋“ฑ๋กํ•œ ์ž‘์—…์ด ๋๋‚˜๊ธธ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๋“ฑ๋ก ํ›„ ๊ณง๋ฐ”๋กœ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก DispatchQueue.main.sync๋Š” ์ž‘์—…์„ ๋“ฑ๋กํ•  ๋•Œ sync ํ•˜๊ฒŒ ๋“ฑ๋กํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋“ฑ๋กํ•œ ์ž‘์—…์ด ๋๋‚  ๋•Œ ๊นŒ์ง€ ๋‹ค์Œ ์ฝ”๋“œ๋กœ ์ง„ํ–‰ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ์ด๋•Œ ์ž‘์—…์„ ๋“ฑ๋กํ•œ ์Šค๋ ˆ๋“œ ์—ญ์‹œ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋ผ๋ฉด ์Šค๋ ˆ๋“œ๊ฐ€ sync์— ์˜ํ•ด ๋™์ž‘์„ ๋ฉˆ์ถ˜ ์ƒํƒœ์—์„œ ๋ฉ”์ธ์Šค๋ ˆ๋“œ์— ํ์— ๋“ฑ๋ก๋œ ์ž‘์—…์ด ํ• ๋‹น๋ฉ๋‹ˆ๋‹ค. ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋Š” ํ์— ๋“ฑ๋กํ–ˆ๋˜ ์ž‘์—…์ด ๋๋‚˜๊ธธ ๊ธฐ๋‹ค๋ฆฌ๊ณ , ๋™์‹œ์— ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์— ํ• ๋‹น๋œ ์ž‘์—…์€ ์‹คํ–‰๋˜๊ธธ ๊ธฐ๋‹ค๋ฆฌ๊ธฐ ๋•Œ๋ฌธ์— ๋ฐ๋“œ๋ฝ ์ƒํƒœ์— ๋น ์ง€๊ฒŒ ๋ฉ๋‹ˆ๋‹ค.

 

26. Defer์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (Explain the defer usage in Swift)

๐Ÿ’ก defer๋Š” ํด๋กœ์ €์— ์ •์˜๋œ ์ฝ”๋“œ๊ฐ€ ์ฝ์–ด์ง„ ์ดํ›„์— ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜๊ธฐ ์ „ ๋งˆ์ง€๋ง‰์— ์‹คํ–‰๋˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค.

  func deferTest() {
      print(1)
      defer {
          print("last")
      }
      print(2)
  }

  deferTest()
  // 1
  // 2
  // last

๐Ÿ’ก defer ์ฝ”๋“œ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์œผ๋ฉด ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜๋„ ํด๋กœ์ €๋Š” ์‹คํ–‰๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  func deferTest() {
      print(1)
      return
      defer {
          print("last")
      }
      print(2)
  }

  deferTest()
  // 1

๐Ÿ’ก ์—ฌ๋Ÿฌ๊ฐœ์˜ defer๊ฐ€ ์‹คํ–‰๋˜์—ˆ๋‹ค๋ฉด ์ฝํ˜€์ง„ ์—ญ์ˆœ์œผ๋กœ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

  func deferTest() {
      print(1)
      defer {
          print("last1")
      }
      defer {
          print("last2")
      }
      defer {
          print("last3")
      }
      print(2)
  }

  deferTest()
  // 1
  // 2
  // last3
  // last2
  // last1

๐Ÿ’ก ์ค‘์ฒฉ๋œ defer๋Š” ๋ฐ”๊นฅ์ชฝ defer ๋ถ€ํ„ฐ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.

  func deferTest() {
      print(1)
      defer {
          print("last1")
          defer {
              print("last2")
              defer {
                  print("last3")
              }
          }
      }
      print(2)
  }

  deferTest()
  // 1
  // 2
  // last1
  // last2
  // last3

 

27. open๊ณผ public ํ‚ค์›Œ๋“œ์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What is the difference between open and public keywords in Swift?)

๐Ÿ’ก open๊ณผ public ํ‚ค์›Œ๋“œ ๋ชจ๋‘ ์™ธ๋ถ€ ๋ชจ๋“ˆ์—์„œ์˜ ์ ‘๊ทผ๊นŒ์ง€ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก open์€ ํด๋ž˜์Šค์—์„œ๋งŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก open์€ ์™ธ๋ถ€ ๋ชจ๋“ˆ์—์„œ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•˜๋Š” ๊ฒƒ๊ณผ ๋ฉ”์†Œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋”ฉ์ด ๊ฐ€๋Šฅํ•˜์ง€๋งŒ, public์€ ์™ธ๋ถ€ ๋ชจ๋“ˆ์—์„œ์˜ ํด๋ž˜์Šค ์ƒ์†๊ณผ ๋ฉ”์†Œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋”ฉ์„ ์ œํ•œํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ๋™์ผํ•œ ๋ชจ๋“ˆ ๋‚ด์—์„œ๋Š” open๊ณผ public ๋ชจ๋‘ ํด๋ž˜์Šค ์ƒ์†๊ณผ ๋ฉ”์†Œ๋“œ ์˜ค๋ฒ„๋ผ์ด๋”ฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

28. fileprivate์„ ์„ค๋ช…ํ•˜๊ณ  ์–ธ์ œ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์„์ง€ ์ด์•ผ๊ธฐํ•ด๋ณด์„ธ์š”. (When to use fileprivate access modifier in Swift?)

๐Ÿ’ก fileprivate์€ ๊ฐ™์€ ์†Œ์ŠคํŒŒ์ผ ๋‚ด์—์„œ์˜ ์ ‘๊ทผ๋งŒ ํ•˜์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก fileprivate์ธ ์ธ์Šคํ„ด์Šค๋ฅผ ํ• ๋‹นํ•˜๋Š” ๋ณ€์ˆ˜๋Š” private์ด๊ฑฐ๋‚˜ fileprivate์œผ๋กœ ์ ‘๊ทผ์ด ์ œํ•œ๋˜์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก fileprivate์ธ ํด๋ž˜์Šค๋ฅผ ์ƒ์†ํ•  ๋•Œ๋„ ์ƒ์†๋ฐ›๋Š” ํด๋ž˜์Šค๊ฐ€ private์ด๊ฑฐ๋‚˜ fileprivate์ด์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ๊ฐ™์€ ํŒŒ์ผ ๋‚ด๋ถ€์—์„œ๋งŒ ์‚ฌ์šฉ๋˜๋Š” ํด๋ž˜์Šค์ผ ๋•Œ fileprivate๋กœ ์ œํ•œํ•˜๋ฉด ์œ ์šฉํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

29. fileprivate๊ณผ private์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What is the difference between fileprivate and private?)

๐Ÿ’ก fileprivate์€ ๊ฐ™์€ ํŒŒ์ผ ๋‚ด๋ถ€์— ์žˆ๋‹ค๋ฉด ์ ‘๊ทผ์„ ํ—ˆ์šฉํ–ˆ์ง€๋งŒ private์€ ๊ฐ™์€ ํŒŒ์ผ์— ์žˆ์–ด๋„ private์œผ๋กœ ์„ ์–ธํ•œ ๋Œ€์ƒ์˜ ๊ตฌํ˜„๋ถ€ ๋‚ด๋ถ€, ๊ทธ๋ฆฌ๊ณ  ๊ฐ™์€ ํŒŒ์ผ์— ์žˆ๋Š” ๋™์ผํ•œ ์„ ์–ธ์˜ Extension ์—์„œ์˜ ์ ‘๊ทผ๋งŒ ํ—ˆ์šฉํ•ฉ๋‹ˆ๋‹ค.

  // A.swift
  private class A {
    public init() {}
    private var data: String
  }

  extension A { // ๊ฐ™์€ ํŒŒ์ผ์— ์žˆ์„ ๋•Œ๋งŒ ๊ฐ€๋Šฅ
    func updateData(data: String) {
      self.data = data
    }
  }

  // A+External swift
  extension A { // Error. Cannot find type 'A' in scope
    func printExternal() {
        print(self.data)
    }
  }

 

30. static func ์™€ class func์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What is the difference between static func and class func in Swift?)

๐Ÿ’ก static func, class func ๋ชจ๋‘ ํƒ€์ž… ๋ฉ”์†Œ๋“œ์ด๊ธฐ ๋•Œ๋ฌธ์— ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š๊ณ  ํƒ€์ž…์— ์ ‘๊ทผํ•ด ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก class func๋Š” ์˜ค๋ฒ„๋ผ์ด๋”ฉ์„ ํ—ˆ์šฉํ•˜์ง€๋งŒ static func๋Š” ์˜ค๋ฒ„๋ผ์ด๋”ฉ์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ์Šค์œ„ํ”„ํŠธ์—์„œ ์œ ์ผํ•˜๊ฒŒ ์ง์ ‘์ ์ธ ์ƒ์†์„ ์ง€์›ํ•˜๋Š” ๊ฐ์ฒดํƒ€์ž…์ด ํด๋ž˜์Šค๋ผ๋Š” ๊ฒƒ์„ ์ƒ๊ฐํ•ด๋ณด๋ฉด class๋งŒ ์˜ค๋ฒ„๋ผ์ด๋”ฉ์„ ํ—ˆ์šฉํ•˜๋Š” ๊ฒƒ๊ณผ ์‰ฝ๊ฒŒ ์—ฐ๊ฒฐ์‹œํ‚ฌ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค!

 

31. Function๊ณผ Closure์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What is the difference between functions and closures?)

๐Ÿ’ก Function๊ณผ Closure ๋ชจ๋‘ ์‹คํ–‰๊ฐ€๋Šฅํ•œ ์ฝ”๋“œ๋ธ”๋ก์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก Function์€ func ํ‚ค์›Œ๋“œ์™€ ํ•จ๊ป˜ ์„ ์–ธ๋˜๊ณ  ํ•จ์ˆ˜์˜ ์ด๋ฆ„์„ ํ•ญ์ƒ ๊ฐ€์ ธ์•ผํ•ฉ๋‹ˆ๋‹ค. ๋ฐ˜๋ฉด์— ํด๋กœ์ €๋Š” ์ด๋ฆ„์„ ๊ฐ€์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

 

32. ์Šค์œ„ํ”„ํŠธ์—์„œ ์ถ”์ƒ ํด๋ž˜์Šค๋ฅผ ๋งŒ๋“ค๋ ค๋ฉด ์–ด๋–ป๊ฒŒ ํ•ด์•ผํ• ๊นŒ์š”? (Is there a way to create an abstract class in Swift?)

๐Ÿ’ก ์Šค์œ„ํ”„ํŠธ๋Š” ์ถ”์ƒ ํด๋ž˜์Šค ๋ฌธ๋ฒ•์„ ์ง€์›ํ•˜์ง€๋Š” ์•Š์ง€๋งŒ ํ”„๋กœํ† ์ฝœ์„ ํ†ตํ•ด ๋™์ผํ•œ ๋™์ž‘์„ ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ํ”„๋กœํผํ‹ฐ์™€ ๋ฉ”์„œ๋“œ์˜ ์›ํ˜•์„ ํ”„๋กœํ† ์ฝœ์— ์„ ์–ธํ•ด๋‘๊ณ , Extension์„ ํ†ตํ•ด ํ”„๋กœํ† ์ฝœ ๋ฉ”์„œ๋“œ์˜ ๊ธฐ๋ณธ ๊ตฌํ˜„์ฒด๋ฅผ ๋งŒ๋“ค์–ด์ฃผ๋ฉด ์ถ”์ƒํด๋ž˜์Šค์™€ ๋™์ผํ•œ ๊ฐœ๋…์˜ ๊ตฌํ˜„์„ ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

33. Any์™€ AnyObject์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What’s the difference between Any and AnyObject?)

๐Ÿ’ก Any์™€ AnyObject ๋ชจ๋‘ ๋ฒ”์šฉํƒ€์ž…์œผ๋กœ ์—ฌ๋Ÿฌ ํƒ€์ž…์„ ํ•œ๋ฒˆ์— ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ฃผ์ง€๋งŒ AnyObject๋Š” ํด๋ž˜์Šค ํƒ€์ž…๋งŒ ์ €์žฅํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ์ œํ•œ์กฐ๊ฑด์ด ์ถ”๊ฐ€๋ฉ๋‹ˆ๋‹ค.

 

34. ์–ธ์ œ ํด๋ž˜์Šค ๋Œ€์‹  ๊ตฌ์กฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ข‹์„๊นŒ์š”? (When should you use Structs over Classes?)

๐Ÿ’ก ์Šค์œ„ํ”„ํŠธ์—์„œ๋Š” ๊ธฐ๋ณธ์ ์œผ๋กœ ๊ตฌ์กฐ์ฒด๋ฅผ ์‚ฌ์šฉํ•˜๊ธธ ๊ถŒ์žฅํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ๊ตฌ์กฐ์ฒด๋Š” ๋ถˆ๋ณ€์„ฑ์„ ์œ ์ง€ํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ๋“ค์ด ํ•œ ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๋‹ค์ค‘ ์Šค๋ ˆ๋“œ ํ™˜๊ฒฝ์—์„œ๋„ ์•ˆ์ „ํ•˜๊ฒŒ ์‚ฌ์šฉ๋  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ๊ตฌ์กฐ์ฒด๋Š” ์Šคํƒ์— ์ €์žฅํ•˜๊ธฐ ๋•Œ๋ฌธ์— ๋” ๋น ๋ฆ…๋‹ˆ๋‹ค. ํž™์— ์ €์žฅ๋˜๋Š” ํด๋ž˜์Šค๋Š” ํž™์— ์ธ์Šคํ„ด์Šค๋ฅผ ์ €์žฅํ•˜๊ณ  ๊ทธ ์ฐธ์กฐ๊ฐ’์„ ์Šคํƒ์— ์ €์žฅํ•ฉ๋‹ˆ๋‹ค.

 

35. ์–ธ์ œ ๊ตฌ์กฐ์ฒด ๋Œ€์‹  ํด๋ž˜์Šค๋ฅผ ์„ ํƒํ•ด์•ผํ• ๊นŒ์š”? (When should you use Classes over Structs?)

๐Ÿ’ก ๊ตฌ์กฐ์ฒด๋Š” ๊ฐ’ ํƒ€์ž…์ด๊ธฐ ๋•Œ๋ฌธ์— ๊ฐ’์ด ๊ฐ™์€ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋งค๋ฒˆ ๋ณต์‚ฌ๋˜์–ด ์‚ฌ์šฉ๋ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ๋”ฐ๋ผ์„œ ๋งŒ์•ฝ ์–ด๋–ค ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ๊ฐ’์˜ ๊ณ ์œ ์„ฑ์„ ์œ ์ง€ํ•˜๊ณ  ์‹ถ๋‹ค๋ฉด ํด๋ž˜์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ๋˜ํ•œ Objective-C์˜ API๋ฅผ ์‚ฌ์šฉํ•  ๋•Œ๋Š” ํด๋ž˜์Šค๊ฐ€ ๋ฐ˜๋“œ์‹œ ํ•„์š”ํ•˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค. i.e.)NSCache์˜ value์—๋Š” ๊ตฌ์กฐ์ฒด ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.

 

36. weak๊ณผ unowned ์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•˜๊ณ  ์˜ˆ๋ฅผ ๋“ค์–ด์ฃผ์„ธ์š”. (Explain the difference between weak and unowned references. Provide an example.)

๐Ÿ’ก weak์€ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•ด์ œ๋˜๋Š” ๊ฒƒ์„ ์—ผ๋‘ํ•˜์—ฌ ํ•ญ์ƒ Optionalํ•œ ํƒ€์ž…์„ ๊ฐ€์ง‘๋‹ˆ๋‹ค. ๋งŒ์•ฝ weak์œผ๋กœ ์„ ์–ธํ•œ ๋ณ€์ˆ˜๊ฐ€ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜๋ฉด ํ•ด๋‹น ๋ณ€์ˆ˜์˜ ๊ฐ’์€ nil๋กœ ์ฑ„์›Œ์ง‘๋‹ˆ๋‹ค.
๐Ÿ’ก unowned๋Š” ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ unowned ๋ณ€์ˆ˜ ์ด์ „์—๋Š” ์ ˆ๋Œ€ ํ•ด์ œ๋˜์ง€ ์•Š์Œ์„ ๋ณด์žฅํ•˜๋Š” ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก unwoend๋Š” Optional์„ ํ—ˆ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ unowned๊ฐ€ ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋˜ ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•ด์ œ๋œ ์ดํ›„์— unowned ๋ณ€์ˆ˜๋ฅผ ์ฐธ์กฐํ•˜๋ฉด ๋Ÿฐํƒ€์ž„ ์—๋Ÿฌ๊ฐ€ ๋ฐœ์ƒํ•ฉ๋‹ˆ๋‹ค.

  // https://stackoverflow.com/questions/24011575/what-is-the-difference-between-a-weak-reference-and-an-unowned-reference
  class Person {
      let name: String
      init(name: String) { self.name = name }
      var apartment: Apartment?
  }

  class Apartment {
      let number: Int
      init(number: Int) { self.number = number }
      weak var tenant: Person?
  }
  // Person ===(strong)==> Apartment
  // Person <==(weak)===== Apartment

  class Customer {
      let name: String
      var card: CreditCard?
      init(name: String) { self.name = name }
  }

  class CreditCard {
      let number: UInt64
      unowned let customer: Customer
      init(number: UInt64, customer: Customer) { self.number = number; self.customer = customer }
  }

  // Customer ===(strong)==> CreditCard
  // Customer <==(unowned)== CreditCard

 

37. unowned๋Š” ์–ธ์ œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ• ๊นŒ์š”? (When is it safe to use an unowned reference?)

๐Ÿ’ก unowned๋กœ ์„ ์–ธ๋œ ๋ณ€์ˆ˜๊ฐ€ ์ฐธ์กฐํ•˜๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•ด๋‹น unowned ๋ณ€์ˆ˜๊ฐ€ ํ•ด์ œ๋œ ์ดํ›„์— ํ•ด์ œ๋˜๋Š” ๊ฒƒ์ด ๋ณด์žฅ๋˜๋Š” ์ƒํ™ฉ์—์„œ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ์•ˆ์ „ํ•ฉ๋‹ˆ๋‹ค.

  // https://www.advancedswift.com/strong-weak-unowned-in-swift/
  extension HomeVC {
      // Calling loadAPI no longer creates a Retain Cycle:
      // 1. Self (HomeVC) has a strong reference to api
      // 2. api has a strong reference to completion
      // 3. completion has a unowned reference to self (HomeVC)
      func loadAPI() {
          api.completion = { [unowned self] (data, error) in
              self.hideLoadingIndicator()
          }
      }
      // HomeVC -> api -> completion === (unonwned) ===> HomeVC
  }

 

38. Swift์˜ Copy-on-Write์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What is Copy on Write (Cow) in Swift?)

๐Ÿ’ก COW๋Š” ๊ฐ’ ํƒ€์ž…์˜ ๋ณต์‚ฌ๋ฅผ ์‹ค์ œ๋กœ ๊ฐ’์ด ์ˆ˜์ •๋˜๊ธฐ ์ „๊นŒ์ง€๋Š” ๋ฐœ์ƒ์‹œํ‚ค์ง€ ์•Š์•„ ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์„ ์ตœ์ ํ™”ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค. ์˜ˆ๋ฅผ ๋“ค์–ด์„œ ๊ฐ’ํƒ€์ž…์ธ ๋ฐฐ์—ด์„ ๋‘ ๋ณ€์ˆ˜์— ์ €์žฅํ•ด๋‘๋ฉด ๋‘ ๊ฐœ์˜ ๋‹ค๋ฅธ ์ธ์Šคํ„ด์Šค๊ฐ€ ์ƒ์„ฑ๋  ๊ฒƒ์„ ๊ธฐ๋Œ€ํ•˜์ง€๋งŒ ์‹ค์ œ๋กœ๋Š” ์ฃผ์†Œ ๊ฐ’์„ ๊ณต์œ ํ•˜๊ณ  ์žˆ๋‹ค๊ฐ€ ๋ณ€์ˆ˜์— ๋ณ€๊ฒฝ์‚ฌํ•ญ์ด ์ƒ๊ฒผ์„ ๋•Œ ์ƒˆ๋กœ์šด ์ธ์Šคํ„ด์Šค๋ฅผ ํ• ๋‹นํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ์ด๋ ‡๊ฒŒ ํ•˜๋ฉด ์ˆ˜์ •์ด ์ผ์–ด๋‚˜์ง€ ์•Š๋Š” ๊ฐ’ ํƒ€์ž… ๋ฐ์ดํ„ฐ๋Š” ๋ณต์‚ฌ๋ณธ์„ ๋งŒ๋“ค์ง€ ์•Š๊ณ  ์‚ฌ์šฉ๋˜๊ธฐ ๋•Œ๋ฌธ์— ๋ฉ”๋ชจ๋ฆฌ ์‚ฌ์šฉ์„ ์ตœ์ ํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  import Foundation

  func address(of valueTypePointer: UnsafeRawPointer) -> Int {
      return Int(bitPattern: valueTypePointer)
  }

  func compareValueTypeInstance(of arr1:[Int], with arr2:[Int]) {
      if address(of: arr1) == address(of: arr2) {
          print("same instance")
      } else {
          print("different istance")
      }
  }

  let arr1 = [1, 2, 3, 4]
  var arr2 = arr1

  compareValueTypeInstance(of: arr1, with: arr2) // "same instance"

  arr2.append(5)

  compareValueTypeInstance(of: arr1, with: arr2) // "different istance"

 

39. staic ๋ณ€์ˆ˜์™€ class ๋ณ€์ˆ˜์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What’s the difference between a static variable and a class variable?)

๐Ÿ’ก static ๋ณ€์ˆ˜์™€ class ๋ณ€์ˆ˜ ๋ชจ๋‘ ํƒ€์ž… ํ”„๋กœํผํ‹ฐ๋กœ ํด๋ž˜์Šค, ๊ตฌ์กฐ์ฒด, ์—ด๊ฑฐํ˜•์— ๋ชจ๋‘ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ํƒ€์ž… ํ”„๋กœํผํ‹ฐ๋Š” lazyํ•˜๊ฒŒ ๋™์ž‘ํ•ด์„œ ์‹ค์ œ๋กœ ๋ถˆ๋ฆฌ๊ธฐ ์ „๊นŒ์ง€๋Š” ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ํƒ€์ž… ํ”„๋กœํผํ‹ฐ๋Š” ํ•œ ๋ฒˆ ๋ถˆ๋ฆฌ๋ฉด ๋ฉ”๋ชจ๋ฆฌ์— ๋กœ๋“œ๋˜๊ณ  ๊ทธ ์ดํ›„๋กœ๋Š” ์ƒˆ๋กœ ์ƒ์„ฑ๋˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ํƒ€์ž… ํ”„๋กœํผํ‹ฐ๋Š” ํƒ€์ž… ์ด๋ฆ„์„ ํ†ตํ•ด์„œ๋งŒ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๊ณ  ์ดˆ๊ธฐ๊ฐ’์„ ํ•ญ์ƒ ๊ฐ€์ ธ์•ผํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก class๋กœ ์„ ์–ธ๋œ ํƒ€์ž… ํ”„๋กœํผํ‹ฐ๋Š” ์˜ค๋ฒ„๋ผ์ด๋”ฉ์ด ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ๋ฐ˜๋ฉด์— static์œผ๋กœ ์„ ์–ธ๋œ ํƒ€์ž… ํ”„๋กœํผํ‹ฐ๋Š” ์˜ค๋ฒ„๋ผ์ด๋”ฉ์ด ๋ถˆ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

40. ARC์™€ GC๋Š” ์–ด๋–ค ์ฐจ์ด์ ์ด ์žˆ๋‚˜์š”? (What is the difference between ARC (automatic reference counting) and GC (garbage collection)?)

๐Ÿ’ก ARC์™€ GC์˜ ๊ฐ€์žฅ ํฐ ์ฐจ์ด์ ์€ ๋Ÿฐํƒ€์ž„์— ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š”์ง€, ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ฒ˜๋ฆฌ๋ฅผ ํ•˜๋Š”์ง€์— ์žˆ์Šต๋‹ˆ๋‹ค. ARC๋Š” Retain๊ณผ Release๋ฅผ ์ปดํŒŒ์ผ๋Ÿฌ๊ฐ€ ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ž๋™์œผ๋กœ ์‚ฝ์ž…ํ•ด Reference Count๋ฅผ ์กฐ์ ˆํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ๋ฐ˜๋ณ€์— GC๋Š” ๊ฐ€๋น„์ง€ ์ฝœ๋ ‰ํ„ฐ๋ฅผ ๋Ÿฐํƒ€์ž„์— ๋ณ„๋„๋กœ ์‹คํ–‰ํ•˜๋ฉด์„œ ๋ฉ”๋ชจ๋ฆฌ์˜ ์ƒํƒœ๋ฅผ ๊ฐ์‹œํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ARC๋Š” ๋‹จ์ˆœํžˆ ์นด์šดํŒ…์„ ํ†ตํ•ด ์ธ์Šคํ„ด์Šค๋“ค์„ ๊ด€๋ฆฌํ•˜๊ธฐ ๋•Œ๋ฌธ์— ์ˆœํ™˜์ฐธ์กฐ์˜ ์œ„ํ—˜์ด ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก GC๋Š” Mark-and-Sweep ๋ฐฉ์‹์œผ๋กœ ๋ฃจํŠธ๋…ธ๋“œ๋ถ€ํ„ฐ ๋„๋‹ฌ ๊ฐ€๋Šฅํ•œ ์ธ์Šคํ„ด์Šค๋“ค์„ ๋ชจ๋‘ ์ฒดํฌํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ์ˆœํ™˜์ฐธ์กฐ๊ฐ€ ๋ฐœ์ƒํ•˜๋”๋ผ๋„ ๋‘ ์ธ์Šคํ„ด์Šค๋ฅผ ์ฐธ์กฐํ•˜๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•ด์ œ๋˜๋ฉด ๋ฃจํŠธ๋กœ๋ถ€ํ„ฐ ์ˆœํ™˜์ฐธ์กฐ๊ฐ€ ๋ฐœ์ƒํ•œ ์ธ์Šคํ„ด์Šค๋“ค์— ๋„๋‹ฌํ•  ์ˆ˜ ์žˆ๋Š” ๊ฒฝ๋กœ๊ฐ€ ์—†๊ธฐ ๋•Œ๋ฌธ์— ๋‘ ์ธ์Šคํ„ด์Šค๋ฅผ ๋ชจ๋‘ ํ•ด์ œํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

41. autoclosure attribute์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What is the autoclosure attribute and when to use it?)

๐Ÿ’ก autoclosure๋Š” ํด๋กœ์ €๊ฐ€ ์•„๋‹Œ ์ฝ”๋“œ๋ฅผ ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ๋ฐ›์„ ๋•Œ ์ด ์ฝ”๋“œ๋ฅผ ํด๋กœ์ €๋กœ ๋งŒ๋“ค์–ด์ฃผ๋Š” ํ‚ค์›Œ๋“œ์ž…๋‹ˆ๋‹ค.
๐Ÿ’ก autoclosure์˜ ์ฃผ๋œ ๋ชฉ์ ์€ ์ฝ”๋“œ์˜ ์‹คํ–‰์„ ์ง€์—ฐ์‹œํ‚ค๊ธฐ ์œ„ํ•จ์ž…๋‹ˆ๋‹ค. ํด๋กœ์ €๋ฅผ ์ธ์ž๋ฅผ ๋„˜๊ธฐ๋Š” ๊ฒƒ์œผ๋กœ๋„ ์ง€์—ฐ ์‹คํ–‰์„ ๋งŒ์กฑ์‹œํ‚ฌ ์ˆ˜ ์žˆ์ง€๋งŒ autoclosure๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ˜ธ์ถœํ•˜๋Š” ์ธก ์ฝ”๋“œ์˜ ๊ฐ€๋…์„ฑ์ด ์ข‹์•„์ง‘๋‹ˆ๋‹ค.

๐Ÿ’ก ํด๋กœ์ € ์‚ฌ์šฉ X

  // https://www.avanderlee.com/swift/autoclosure/

  struct Person: CustomStringConvertible {
  let name: String

  var description: String {
      print("Asking for Person description.")
      return "Person name is \(name)"
  }
  }

  let isDebuggingEnabled: Bool = false

  func debugLog(_ message: String) {
      /// You could replace this in projects with #if DEBUG
      if isDebuggingEnabled {
          print("[DEBUG] \(message)")
      }
  }

  let person = Person(name: "Bernie")
  debugLog(person.description) // ๋””๋ฒ„๊น… ๋ชจ๋“œ๊ฐ€ ์•„๋‹ˆ์–ด๋„ person.description์ด ์‹คํ–‰๋จ

๐Ÿ’ก ํด๋กœ์ € ์‚ฌ์šฉ

  let isDebuggingEnabled: Bool = false

  func debugLog(_ message: () -> String) {
      /// You could replace this in projects with #if DEBUG
      if isDebuggingEnabled {
          print("[DEBUG] \(message())")
      }
  }

  let person = Person(name: "Bernie")
  debugLog({ person.description }) // ํด๋กœ์ €๊ฐ€ ๋„˜์–ด๊ฐ€๊ธฐ ๋•Œ๋ฌธ์— description ์ฐธ์กฐ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์Œ

๐Ÿ’ก autoclosure ์‚ฌ์šฉ

  let isDebuggingEnabled: Bool = false

  func debugLog(_ message: @autoclosure () -> String) {
      /// You could replace this in projects with #if DEBUG
      if isDebuggingEnabled {
          print("[DEBUG] \(message())")
      }
  }

  let person = Person(name: "Bernie")
  debugLog(person.description) // ํด๋กœ์ €๋กœ ๋ž˜ํ•‘๋˜๋ฉด์„œ ๋“ค์–ด๊ฐ€๊ธฐ ๋•Œ๋ฌธ์— description ์ฐธ์กฐ๊ฐ€ ์‹คํ–‰๋˜์ง€ ์•Š์Œ

 

42. GCD์˜ QoS์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What is QoS (Quality of Service) in GCD?)

๐Ÿ’ก Qos ๋Š” DispatchQueue์— ๋“ฑ๋กํ•˜๋Š” ์ž‘์—…์˜ ์šฐ์„ ์ˆœ์œ„๋ฅผ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์€ ์ž‘์—…์€ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋‚ฎ์€ ์ž‘์—…๋ณด๋‹ค ๋จผ์ € ์‹คํ–‰๋˜์ง€๋งŒ ์•ฑ์˜ ๋ฆฌ์†Œ์Šค๋ฅผ ๋งŽ์ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก qos ์ˆ˜์ค€์€ ๋‹ค์Œ์œผ๋กœ ์ •์˜๋ฉ๋‹ˆ๋‹ค.

๐Ÿ’ก userInterative: ๊ฐ€์žฅ ์šฐ์„ ์ˆœ์œ„๊ฐ€ ๋†’์Šต๋‹ˆ๋‹ค. UI์ž‘์—… ๋“ฑ ์‚ฌ์šฉ์ž์—๊ฒŒ ์ฆ‰๊ฐ์ ์ธ ๋ฐ˜์‘์„ ํ•ด์•ผํ•˜๋Š” ์ž‘์—…์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก userInitiated: ๋ฌธ์„œ๋ฅผ ์—ด๋žŒํ•˜๊ฑฐ๋‚˜ ์ธํ„ฐํŽ˜์ด์Šค์— ์ œ์Šค์ณ๋ฅผ ์ทจํ•˜๋Š” ๋“ฑ ์‚ฌ์šฉ์ž์™€์˜ ์ƒํ˜ธ์ž‘์šฉ์ด ์‹œ์ž‘๋˜์—ˆ์„ ๋•Œ ๊ณง๋ฐ”๋กœ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ˜ํ™˜ํ•ด์•ผ ํ•˜๋Š” ์ž‘์—…์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก default: ๊ธฐ๋ณธ๊ฐ’์ž…๋‹ˆ๋‹ค. ์ผ๋ฐ˜์ ์ธ ์ž‘์—…์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก utility: ๋ฐ์ดํ„ฐ๋ฅผ ๋‹ค๋ฃฌ๋กœ๋“œ ํ•˜๋Š” ๋“ฑ ๊ฒฐ๊ณผ๋ฅผ ๋งŒ๋“ค๊ธฐ ์œ„ํ•ด ์‹œ๊ฐ„์ด ๊ฑธ๋ฆฌ๋Š” ์ž‘์—…์— ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœ๊ทธ๋ž˜์Šค ๋ฐ”๋‚˜ ์•กํ‹ฐ๋น„ํ‹ฐ ์ธ๋””์ผ€์ดํ„ฐ์™€ ํ•จ๊ป˜ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก background: ์‚ฌ์šฉ์ž๊ฐ€ ์ธ์ง€ํ•˜์ง€ ๋ชปํ•˜๋Š” ์˜์—ญ์—์„œ ์—๋„ˆ์ง€์™€ ๋ฆฌ์†Œ์Šค๋ฅผ ํšจ์œจ์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

 

43. Hashable ํ”„๋กœํ† ์ฝœ์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What is the use of Hashable protocol?)

๐Ÿ’ก Hashable ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๋Š” ํƒ€์ž…์€ ๋ชจ๋‘ ๊ฐ’์„ ์ •์ˆ˜์ธ ํ•ด์‹œ๊ฐ’์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ์Šค์œ„ํ”„ํŠธ์˜ ๊ธฐ๋ณธ ํƒ€์ž… ์ค‘ ๋ฌธ์ž์—ด, ์ •์ˆ˜, ์‹ค์ˆ˜, ๋ถˆ๋ฆฌ์–ธ, ๊ทธ๋ฆฌ๊ณ  Set ์ฝœ๋ ‰์…˜์ด Hashable ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก Hashable ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๋Š” ์ปค์Šคํ…€ ํƒ€์ž…์˜ ์ €์žฅ ํ”„๋กœํผํ‹ฐ๊ฐ€ ๋ชจ๋‘ Hashable ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๊ณ  ์žˆ๋‹ค๋ฉด, ๋ณ„๋‹ค๋ฅธ ๊ตฌํ˜„์—†์ด Hashable ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๋Š” ๊ฒƒ ๋งŒ์œผ๋กœ Hashableํ•œ ๋™์ž‘์„ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ๊ทธ๋ ‡์ง€ ์•Š๋‹ค๋ฉด == ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค๊ณ  hash(into:) ๊ตฌํ˜„ํ•ด์„œ ํ•ด์‹œ๊ฐ’์„ ์ƒ์„ฑํ•˜๋Š”๋ฐ ํ•„์š”ํ•œ ํ”„๋กœํผํ‹ฐ๋ฅผ ์ง€์ •ํ•ด์ฃผ์–ด์•ผํ•ฉ๋‹ˆ๋‹ค.

  // https://developer.apple.com/documentation/swift/hashable
  struct GridPoint {
  var x: Int
  var y: Int
  }

  extension GridPoint: Hashable {
  static func == (lhs: GridPoint, rhs: GridPoint) -> Bool {
      return lhs.x == rhs.x && lhs.y == rhs.y
  }

  func hash(into hasher: inout Hasher) {
      hasher.combine(x)
      hasher.combine(y)
  }
  }

 

44. Hashable ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•˜๋Š” ์ปค์Šคํ…€ ํƒ€์ž…์ด Equtable๋„ ์ฑ„ํƒํ•ด์•ผํ•˜๋Š” ์ด์œ ๊ฐ€ ๋ฌด์—‡์ธ๊ฐ€์š”?

๐Ÿ’ก ์–ด๋–ค ๊ฐ’์— ๋Œ€ํ•œ Hash ๊ฐ’์€ ๊ณ ์œ ํ•˜์ง€๋งŒ, Hash ๊ฐ’์„ ์ƒ์„ฑํ•˜๋Š” built in ๋ฉ”์†Œ๋“œ์ธ hasher(_:) ๊ฐ€ ์„œ๋กœ ๋‹ค๋ฅธ ๊ฐ’์— ๋Œ€ํ•ด ๋™์ผํ•œ Hash ๊ฐ’์„ ์ƒ์„ฑํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
๐Ÿ’ก ์ด๋Ÿฐ ๊ฒฝ์šฐ๋ฅผ ํ•ด์‹œ ์ถฉ๋Œ(Hash Collision)์ด๋ผ๊ณ  ํ•˜๊ณ , ํ•ด์‹œ ์ถฉ๋Œ์ด ๋ฐœ์ƒํ•˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์•Œ๊ธฐ ์œ„ํ•ด์„œ๋Š” ๋‘ ์ธ์Šคํ„ด์Šค๊ฐ€ ๊ฐ’์ด ์ผ์น˜ํ•˜๋Š” ํ™•์ธํ•ด์•ผํ•˜๊ธฐ ๋•Œ๋ฌธ์— Equatable ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.

Hashable์— ๋Œ€ํ•œ ์—„์ฒญ ์ข‹์€ ๊ธ€์ด ์žˆ๋„ค์š”! https://betterprogramming.pub/what-is-hashable-in-swift-6a51627f904

 

 

45. ์—ด๊ฑฐํ˜•๋„ Hashable์„ ์ฑ„ํƒํ–ˆ์„ ๋•Œ ์ž๋™์œผ๋กœ Hashableํ•˜๊ฒŒ ๋งŒ๋“ค ์ˆ˜ ์žˆ๋‚˜์š”?

๐Ÿ’ก ์—ด๊ฑฐํ˜•์€ associated value๊ฐ€ ์—†๋Š” ๊ฒฝ์šฐ์—๋Š” Hashable ํ”„๋กœํ† ์ฝœ๋งŒ ์ฑ„ํƒํ•ด๋„ Hashableํ•˜๊ฒŒ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ํ•˜์ง€๋งŒ associated value๊ฐ€ ์žˆ๋Š” ๊ฒฝ์šฐ์—๋Š” hash ๋ฉ”์„œ๋“œ๋ฅผ ๊ตฌํ˜„ํ•ด์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.

 

 

46. init?()๊ณผ init()์€ ์–ด๋–ค ์ฐจ์ด๊ฐ€ ์žˆ๋‚˜์š”? (What’s the difference between init?() and init()?)

๐Ÿ’ก init?()์€ ์‹คํŒจ๊ฐ€๋Šฅํ•œ ์ƒ์„ฑ์ž๋กœ ์ƒ์„ฑ์ž์˜ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•˜๋‹ค๊ฐ€ ๋ฌธ์ œ๊ฐ€ ์ƒ๊ฒผ์„ ๋•Œ nil์„ ๋ฐ˜ํ™˜ํ•˜๋„๋ก ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  class A {
  let a: String

  init?(a: String) {
      guard !a.isEmpty else { return nil }
      self.a = a
  }
  }

  print(A(a: ""))
  print(A(a: "abc")?.a)

 

47. Never ๋ฐ˜ํ™˜ ํƒ€์ž…์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What is the Never return type? When to use it over Void?)

๐Ÿ’ก Never ํƒ€์ž…์€ ๋น„์ •์ƒ์ ์ธ ์ข…๋ฃŒ์— ์‚ฌ์šฉ๋˜๋Š” ๋ฐ˜ํ™˜ ํƒ€์ž…์ด๋ฉฐ ๊ฐ’์„ ์ง€๋‹ˆ์ง€๋Š” ์•Š์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ํด๋กœ์ €, ํ•จ์ˆ˜์— ์—๋Ÿฌ๋ฅผ throwํ•˜๋Š” ๊ฒƒ์œผ๋กœ ์žก์„ ์ˆ˜ ์—†๋Š” ์‹ฌ๊ฐํ•œ ์˜ค๋ฅ˜๊ฐ€ ์žˆ์Œ์„ ์•Œ๋ฆด ๋•Œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  func crashAndBurn() -> Never {
      fatalError("Something very, very bad happened")
  }

 

48. weak๋งŒ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  unowned๋„ ์‚ฌ์šฉํ•˜๋Š” ์ด์œ ๊ฐ€ ๋ฌด์—‡์„๊นŒ์š”? (Why can not we just use weak everywhere and forget about unowned?)

๐Ÿ’ก unowned๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์˜ต์…”๋„์„ ์‹ ๊ฒฝ์“ฐ์ง€ ์•Š์•„๋„ ๋œ๋‹ค๋Š” ์žฅ์ ์ด ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก unowned๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ์ฐธ์กฐํ•˜๊ณ  ์žˆ๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ unowned ํ”„๋กœํผํ‹ฐ ์ด์ „์— ํ•ญ์ƒ ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜๋Š” ๊ฒƒ์„ ๋ช…์‹œ์ ์œผ๋กœ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

49. ARC๊ฐ€ ๋ฉ”๋ชจ๋ฆฌํ•ด์ œ๋ฅผ ํ•  ์ˆ˜ ์—†๋Š” ์ƒํ™ฉ์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. GC๋Š” ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”? (Explain the use case when ARC won't help you to release memory (but GC will)?)

๐Ÿ’ก ARC๋Š” ๊ฐ•ํ•œ ์ˆœํ™˜ ์ฐธ์กฐ ์ƒํ™ฉ์—์„œ ์ธ์Šคํ„ด์Šค๋ฅผ ํ•ด์ œํ•˜์ง€ ๋ชปํ•˜๋Š” ๋ฌธ์ œ๊ฐ€ ์žˆ์Šต๋‹ˆ๋‹ค. ๋งŒ์•ฝ ์–ด๋–ค ๋‘ ํด๋ž˜์Šค ์ธ์Šคํ„ด์Šค๊ฐ€ ํ”„๋กœํผํ‹ฐ์— ์„œ๋กœ๋ฅผ ๊ฐ•ํ•œ ์ฐธ์กฐ๋กœ ์ €์žฅํ•˜๊ณ  ์žˆ์„ ๋•Œ ๊ฐ•ํ•œ ์ˆœํ™˜ ์ฐธ์กฐ๊ฐ€ ๋ฐœ์ƒํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

๐Ÿ’ก ์ˆœํ™˜์ฐธ์กฐ ๋ฐœ์ƒ

  class A {
  var b: B?

  deinit {
      print("A deinitialzied")
  }
  }

  class B {
      var a: A?

      deinit {
          print("B deinitialzied")
      }
  }

  var a = A()
  var b = B()

  a.b = b
  b.a = a

  a = A()
  b = B()

  // retain cycle

๐Ÿ’ก weak๋กœ ์ˆœํ™˜์ฐธ์กฐ ํšŒํ”ผ

  class A {
  var b: B?

  deinit {
      print("A deinitialzied")
  }
  }

  class B {
      var a: A?

      deinit {
          print("B deinitialzied")
      }
  }

  var a = A()
  var b = B()

  a.b = b
  b.a = a

  a = A()
  b = B()

  // B deinitialzied
  // A deinitialzied

 

50. DispatchGroup์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (Explain what is DispatchGroup?)

๐Ÿ’ก DispatchGroup์€ ์—ฌ๋Ÿฌ ์Šค๋ ˆ๋“œ์— ๋ถ„๋ฐฐ๋˜์–ด ์žˆ๋Š” ์ž‘์—…๋“ค์„ ๊ทธ๋ฃน์œผ๋กœ ๋ฌถ์–ด์„œ ๋™๊ธฐ์ ์œผ๋กœ ๊ด€๋ฆฌํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก DispatchGroup์— ์ถ”๊ฐ€๋  ๋•Œ enter ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ž‘์—…์˜ ๊ฐœ์ˆ˜๋ฅผ 1 ๋Š˜๋ ค์ฃผ๊ณ , ์ž‘์—…์ด ๋๋‚  ๋•Œ DispatchGroup์—์„œ ๋น ์ ธ๋‚˜์˜ค๋ฉด์„œ leave ๋ฉ”์„œ๋“œ๋ฅผ ํ†ตํ•ด ์ž‘์—…์˜ ๊ฐœ์ˆ˜๋ฅผ ํ•˜๋‚˜ ์ค„์—ฌ์ค๋‹ˆ๋‹ค.
๐Ÿ’ก ์ž‘์—…์˜ ๊ฐœ์ˆ˜๊ฐ€ 0์ด๋˜๋ฉด notify ๋ฉ”์„œ๋“œ๊ฐ€ ์‹คํ–‰๋˜๋ฉด์„œ ๋ชจ๋“  ์ž‘์—…์ด ๋๋‚ฌ์„ ๋•Œ์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๋ฅผ ์ˆ˜ํ–‰ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก enter, leave, notoify๋ฅผ ์ด์šฉํ•ด์„œ ์—ฌ๋Ÿฌ๊ฐœ์˜ ๋น„๋™๊ธฐ ์ž‘์—…๋“ค์ด ์ „๋ถ€ ๋๋‚  ๋•Œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ฒŒ ํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

  // https://stackoverflow.com/questions/49376157/swift-dispatchgroup-notify-before-task-finish
  let group = DispatchGroup()
  let queueImage = DispatchQueue(label: "com.image")
  let queueVideo = DispatchQueue(label: "com.video")

  group.enter()
  queueImage.async(group: group) {
      sleep(2)
      print("image")
      group.leave()
  }

  group.enter()
  queueVideo.async(group: group) {
      sleep(3)
      print("video")
      group.leave()
  }

  group.notify(queue: .main) {
      print("all finished.")
  }

 

51. DispatchWorkItem์˜ ์žฅ์ ์ด ๋ฌด์—‡์ธ๊ฐ€์š”? (What are the benefits of using DispatchWorkItem in Swift?)

๐Ÿ’ก DispatchWorkItem์„ ์‚ฌ์šฉํ•˜๋ฉด DispatchQueue์— ๋“ฑ๋กํ•  ์ž‘์—…์„ ์บก์Šํ™”ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  let queue = DispatchQueue(label: "custom")
  let workItem = DispatchWorkItem {
  print("task is running")
  }
  queue.async(execute: workItem)

๐Ÿ’ก DispatchWorkItem์„ ์‚ฌ์šฉํ•˜๋ฉด cancel, wait ๋“ฑ ์ œ๊ณต๋˜๋Š” ๋ฉ”์„œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ์‰ฝ๊ฒŒ ์ž‘์—…์— ๋Œ€ํ•œ ๋™์ž‘์„ ์ง€์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  class SearchViewController: UIViewController, UISearchBarDelegate {
  // We keep track of the pending work item as a property
  private var pendingRequestWorkItem: DispatchWorkItem?

  func searchBar(_ searchBar: UISearchBar, textDidChange searchText: String) {
      // Cancel the currently pending item
      pendingRequestWorkItem?.cancel()

      // Wrap our request in a work item
      let requestWorkItem = DispatchWorkItem { [weak self] in
          self?.resultsLoader.loadResults(forQuery: searchText)
      }

      // Save the new work item and execute it after 250 ms
      pendingRequestWorkItem = requestWorkItem
      DispatchQueue.main.asyncAfter(deadline: .now() + .milliseconds(250),
                                      execute: requestWorkItem)
  }
  }

 

52. Concurrent์™€ Serial Queue๊ฐ€ async, sync์™€ ํ•จ๊ป˜ ์‚ฌ์šฉ๋˜๋Š” ์ƒํ™ฉ์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (Explain usage of Concurrent vs Serial Queues with async and sync blocks)

๐Ÿ’ก concurrent + sync: DispatchQueue์— ์ž‘์—…์ด syncํ•˜๊ฒŒ ๋“ฑ๋ก๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ž‘์—…์„ ๋“ฑ๋กํ•˜๋Š” ์Šค๋ ˆ๋“œ๋Š” ์ž‘์—…์„ ๋“ฑ๋กํ•˜๊ณ  ์ž‘์—…์ด ๋งˆ์ณ์งˆ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. DispatchQueue์— ๋“ฑ๋ก๋œ ์ž‘์—…์€ concurrentํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ž‘์—…์˜ ์ข…๋ฃŒ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ํ• ๋‹น ๊ฐ€๋Šฅํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด ํ์— ์žˆ๋Š” ์ž‘์—…์„ ์Šค๋ ˆ๋“œ์— ํ• ๋‹น์‹œ์ผœ ์ž‘์—…์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก concurrent + async: DispatchQueue์— ์ž‘์—…์ด asyncํ•˜๊ฒŒ ๋“ฑ๋ก๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ž‘์—…์„ ๋“ฑ๋กํ•˜๋Š” ์Šค๋ ˆ๋“œ๋Š” ๋“ฑ๋กํ•œ ์ž‘์—…์ด ๋๋‚˜๊ธธ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๊ณง๋ฐ”๋กœ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. DispatchQueue์— ์žˆ๋Š” ์ž‘์—…์€ concurrentํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ž‘์—…์˜ ์ข…๋ฃŒ์—ฌ๋ถ€์™€ ์ƒ๊ด€์—†์ด ํ• ๋‹น ๊ฐ€๋Šฅํ•œ ์Šค๋ ˆ๋“œ๊ฐ€ ์žˆ๋‹ค๋ฉด ํ์— ์žˆ๋Š” ์ž‘์—…์„ ์Šค๋ ˆ๋“œ์— ํ• ๋‹น์‹œ์ผœ ์ž‘์—…์„ ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก serial + sync: DispatchQueue์— ์ž‘์—…์ด syncํ•˜๊ฒŒ ๋“ฑ๋ก๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ž‘์—…์„ ๋“ฑ๋กํ•˜๋Š” ์Šค๋ ˆ๋“œ๋Š” ์ž‘์—…์„ ๋“ฑ๋กํ•˜๊ณ  ์ž‘์—…์ด ๋งˆ์ณ์งˆ ๋•Œ๊นŒ์ง€ ๊ธฐ๋‹ค๋ฆฝ๋‹ˆ๋‹ค. DispatchQueue์— ๋“ฑ๋ก๋œ ์ž‘์—…์€ serialํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํ˜„์žฌ ์ž‘์—…์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๊ฐ€ ๋๋‚˜๋ฉด ํ์— ๋“ฑ๋ก๋œ ๋‹ค์Œ ์ž‘์—…์„ ์Šค๋ ˆ๋“œ์— ํ• ๋‹นํ•ด ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก serial + async: DispatchQueue์— ์ž‘์—…์ด asyncํ•˜๊ฒŒ ๋“ฑ๋ก๋˜๊ธฐ ๋•Œ๋ฌธ์— ์ž‘์—…์„ ๋“ฑ๋กํ•˜๋Š” ์Šค๋ ˆ๋“œ๋Š” ๋“ฑ๋กํ•œ ์ž‘์—…์ด ๋๋‚˜๊ธธ ๊ธฐ๋‹ค๋ฆฌ์ง€ ์•Š๊ณ  ๊ณง๋ฐ”๋กœ ๋‹ค์Œ ์ฝ”๋“œ๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค. DispatchQueue์— ๋“ฑ๋ก๋œ ์ž‘์—…์€ serialํ•˜๊ฒŒ ์ฒ˜๋ฆฌ๋˜๊ธฐ ๋•Œ๋ฌธ์— ํ˜„์žฌ ์ž‘์—…์— ๋Œ€ํ•œ ์ฒ˜๋ฆฌ๊ฐ€ ๋๋‚˜๋ฉด ํ์— ๋“ฑ๋ก๋œ ๋‹ค์Œ ์ž‘์—…์„ ์Šค๋ ˆ๋“œ์— ํ• ๋‹นํ•ด ์‹œ์ž‘ํ•ฉ๋‹ˆ๋‹ค.

 

53. @escaping์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

๐Ÿ’ก @escaping์€ ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ์ „๋‹ฌ๋œ ํด๋กœ์ €๋ฅผ ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋œ ํ›„์— ์‹คํ–‰๋  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์†์„ฑ์ž…๋‹ˆ๋‹ค.

  func completionTest(completion: @escaping () -> Void) {
  DispatchQueue.global().async {
      completion()
  }
  print("1")
  }

  completionTest {
      print("end")
  }
  // 1
  // end

 

54. @objc์™€ dynamic์˜ ์ฐจ์ด์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. (What's the difference between marking a method as @objc vs dynamic, when would you do one vs the other?)

๐Ÿ’ก dynamic์„ ํ†ตํ•ด ์„ ์–ธ๋œ ๋ฉค๋ฒ„๋ณ€์ˆ˜๋‚˜ ๊ฐ์ฒด๋Š” Objective-C๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋™์ ์œผ๋กœ ๋””์ŠคํŒจ์น˜๋ฉ๋‹ˆ๋‹ค. ๋™์  ๋””์ŠคํŒจ์น˜๋Š” ๋Ÿฐํƒ€์ž„์— ํด๋ž˜์Šค๊ฐ€ ์—ฐ๊ด€ ํด๋ž˜์Šค๋“ค์˜ ๋ฉ”์„œ๋“œ ๊ตฌํ˜„์ฒด๋“ค ์ค‘ ์–ด๋–ค ํด๋ž˜์Šค์˜ ๊ตฌํ˜„์ฒด๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ๊ฒฐ์ •ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก @objc๋Š” ์Šค์œ„ํ”„ํŠธ์˜ API๋ฅผ Objective-C์—์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•˜๋Š” ์†์„ฑ์ด๋‹ˆ๋‹ค.

 

55. Extension์€ ๋ฉ”์„œ๋“œ๋ฅผ Override ํ•  ์ˆ˜ ์žˆ์„๊นŒ์š”?

๐Ÿ’ก Extension์—์„œ๋Š” ๋ฉ”์„œ๋“œ๋ฅผ override ํ•  ์ˆ˜ ์—†์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก Extension์€ ์ƒˆ๋กœ์šด ํ•จ์ˆ˜๋ฅผ ์ถ”๊ฐ€ํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋Šฅ์ด์ง€ ๊ธฐ์กด ํ•จ์ˆ˜๋ฅผ ๋Œ€์ฒดํ•˜๊ธฐ ์œ„ํ•œ ๊ธฐ๋Šฅ์€ ์•„๋‹™๋‹ˆ๋‹ค.

 

56. RunLoop์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

๐Ÿ’ก RunLoop๋Š” ์Šค๋ ˆ๋“œ ๋‹น ํ•˜๋‚˜์”ฉ ์ƒ์„ฑ๋˜์–ด์„œ Thread์— ์ž‘์—…์ด ์ƒ๊ธฐ๋ฉด ์ฒ˜๋ฆฌํ•˜๊ณ , ์•„๋‹ ๋•Œ๋Š” ๋Œ€๊ธฐ์‹œํ‚ค๋Š” ์—ญํ• ์„ ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก RunLoop๋Š” ๋ฉ”์ธ ์Šค๋ ˆ๋“œ๋ฅผ ์ œ์™ธํ•œ ์Šค๋ ˆ๋“œ์—์„œ๋Š” ์ž๋™์œผ๋กœ ์‹คํ–‰๋˜์ง€ ์•Š๊ณ  ๊ฐœ๋ฐœ์ž๊ฐ€ ์ง์ ‘ ์‹คํ–‰์‹œ์ผœ์ฃผ์–ด์•ผ ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก RunLoop๋ฅผ ์‹คํ–‰ํ•˜๋ฉด ์‹คํ–‰๋˜๋Š” ๋™์•ˆ ๋„์ฐฉํ•œ EventSource(input source, timer source)๋ฅผ ์‹คํ–‰ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก RunLoop๋Š” ํ•œ ๋ฒˆ๋งŒ ์‹คํ–‰๋˜๊ณ  ์‹คํ–‰์ด ๋๋‚˜๋ฉด ๋Œ€๊ธฐ์ƒํƒœ๋กœ ๋Œ์•„๊ฐ‘๋‹ˆ๋‹ค.

 

57. autoreleasepool์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

๐Ÿ’ก autorelease๋Š” ์ฐธ์กฐ ์นด์šดํŠธ์˜ ๊ฐ์†Œ๋ฅผ ์ฆ‰์‹œํ•˜์ง€ ์•Š๊ณ  ์˜ˆ์•ฝ์„ ํ•  ์ˆ˜ ์žˆ๊ฒŒํ•˜๋Š” ํ‚ค์›Œ๋“œ์ž…๋‹ˆ๋‹ค. ์˜ˆ์•ฝ๋œ release๋Š” autoreleasepool์— ๋“ฑ๋ก๋˜๊ณ , autoreleasepool ์ธ์Šคํ„ด์Šค๊ฐ€ ํ•ด์ œ๋˜๋ฉด ๋“ฑ๋ก๋˜์–ด ์žˆ๋˜ ์˜ˆ์•ฝ๋œ release๋“ค์ด ๋ชจ๋‘ ์‹คํ–‰๋ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ๋งŒ์•ฝ ํ•จ์ˆ˜๊ฐ€ ๋๋‚˜๊ธฐ ์ „์— ๋ฉ”๋ชจ๋ฆฌ์—์„œ ํ•ด์ œ๋˜์–ด์•ผ ํ•˜๋Š” ์ธ์Šคํ„ด์Šค๊ฐ€ ์žˆ๋‹ค๋ฉด autorelease pool๋กœ ๋ช…์‹œ์ ์œผ๋กœ ์ธ์Šคํ„ด์Šค์˜ ์ฐธ์กฐ ์นด์šดํŠธ๋ฅผ ์ค„์—ฌ์ค„ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  func useManyImages() {
    let filename = pathForResourceInBundle

    for _ in 0 ..< 5 {
        for _ in 0 ..< 1000 {
            let image = UIImage(contentsOfFile: filename) // 5000๊ฐœ ์ƒ์„ฑ
        }
    }
  // 5000๊ฐœ ํ•ด์ œ
  }

  func useManyImages() {
    let filename = pathForResourceInBundle

    for _ in 0 ..< 5 {
        autoreleasepool {
            for _ in 0 ..< 1000 {
                let image = UIImage(contentsOfFile: filename) // 1000๊ฐœ ์ƒ์„ฑ
            }
        } // 1000๊ฐœ ํ•ด์ œ
    }
  }

 

58. OperationQueue์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. DispatchQueue์™€๋Š” ์–ด๋–ค ๊ฒƒ์ด ๋‹ค๋ฅธ๊ฐ€์š”?

๐Ÿ’ก OperationQueue๋Š” ์ž‘์—…์„ ๋‚˜ํƒ€๋‚ด๋Š” Operation ํด๋ž˜์Šค์˜ ์‹คํ–‰์„ ๊ด€๋ฆฌํ•˜๋Š” ํ์ž…๋‹ˆ๋‹ค. GCD์™€๋Š” ๋‹ค๋ฅด๊ฒŒ OperationQueue๋Š” ๊ฐ์ฒดํ™”๋œ ์ž‘์—…์„ ํ์—์„œ ์ทจ์†Œํ•  ์ˆ˜ ์žˆ๊ณ , ํ์— ๋“ฑ๋ก๋  ์ตœ๋Œ€ ์ž‘์—…์˜ ๊ฐœ์ˆ˜๋ฅผ ์„ค์ •ํ•˜๊ฑฐ๋‚˜, ์ž‘์—… ๊ฐ„์˜ ์˜์กด์„ฑ(์–ด๋–ค ์ž‘์—…์ด ์„ ํ–‰๋˜์–ด์•ผ ํ•˜๋Š”์ง€)์— ๋Œ€ํ•œ ์ •๋ณด๋„ ์„ค์ •ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค. ์ฆ‰, DispatchQueue๋ณด๋‹ค ์ข€ ๋” ๊ณ ์ˆ˜์ค€์˜ API๋ฅผ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก OperationQueue๋Š” ๋‚ด๋ถ€์ ์œผ๋กœ DispatchQueue๋ฅผ ์ด์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก OperationQueue๋Š” ์ž‘์—…์„ ํ•œ๋ฒˆ ๊ฐ์ฒดํ™” ํ•˜๊ณ  ๊ณ ์ˆ˜์ค€ API๋ฅผ ์ง€์›ํ•˜๊ธฐ ๋•Œ๋ฌธ์— DispatchQueue๋ณด๋‹ค ๋” ๋งŽ์€ ๋ฆฌ์†Œ์Šค๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ๋ณต์žกํ•˜๊ณ  ์˜์กด์„ฑ์— ๋Œ€ํ•œ ์„ค์ •์ด ํ•„์š”ํ•œ ์ž‘์—…์ด ์•„๋‹ˆ๋ผ๋ฉด DispatchQueue๋ฅผ ์‚ฌ์šฉํ•˜๋Š” ๊ฒƒ์ด ๋” ์ข‹์„ ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

 

59. final ํ‚ค์›Œ๋“œ๋ฅผ ํด๋ž˜์Šค ์•ž์— ๋ถ™์ด๋ฉด ์–ด๋–ค ํšจ๊ณผ๊ฐ€ ์žˆ์„๊นŒ์š”?

๐Ÿ’ก ์–ด๋–ค ํด๋ž˜์Šค์˜ ํ”„๋กœํผํ‹ฐ๋‚˜ ๋ฉ”์†Œ๋“œ๋Š” ๋‹ค๋ฅธ ์ž์‹ ํด๋ž˜์Šค๋กœ๋ถ€ํ„ฐ override ๋  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์—, ์ด๋Ÿฐ override๋œ ๋ฉ”์†Œ๋“œ๋Š” ์‹ค์ œ๋กœ ์–ด๋–ค ๋ฉ”์†Œ๋“œ๋ฅผ ์‹คํ–‰ํ• ์ง€ vtable์„ ํ•œ ๋ฒˆ ํƒ์ƒ‰ํ•ด์„œ ๊ฒฐ์ •ํ•˜๊ฒŒ๋ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์ปดํŒŒ์ผ ํƒ€์ž„์ด ์•„๋‹Œ ๋Ÿฐํƒ€์ž„์— ์‹ค์ œ๋กœ ์‹คํ–‰ํ•  ๋ฉ”์†Œ๋“œ๊ฐ€ ๊ฒฐ์ •๋˜๋Š” ๊ฒƒ์ž…๋‹ˆ๋‹ค. ์ด๋ฅผ dynamic dispatch๋ผ๊ณ  ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก final ํ‚ค์›Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•˜๋ฉด ํ•ด๋‹น ํด๋ž˜์Šค, ํ”„๋กœํผํ‹ฐ, ๋ฉ”์†Œ๋“œ๊ฐ€ ๋‹ค๋ฅธ ํด๋ž˜์Šค์— ์˜ํ•ด ์ƒ์†๋˜๊ณ  ์žˆ์ง€ ์•Š๋‹ค๋Š” ๊ฒƒ์„ ์ปดํŒŒ์ผ๋Ÿฌ์—๊ฒŒ ์•Œ๋ ค์ฃผ๊ธฐ ๋•Œ๋ฌธ์— ์ปดํŒŒ์ผ ํƒ€์ž„์— ์–ด๋–ค ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ• ์ง€ ๋ฐ”๋กœ ๊ฒฐ์ •ํ•  ์ˆ˜ ์žˆ๊ณ , vtable์„ ๊ฑฐ์น˜์ง€ ์•Š๊ณ  ์ง์ ‘์ ์œผ๋กœ ํ˜ธ์ถœ๋˜๊ธฐ ๋•Œ๋ฌธ์— ์„ฑ๋Šฅ์ƒ ๋” ์ข‹์€ ํผํฌ๋จผ์Šค๋ฅผ ๋‚ผ ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

60. vtable์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

๐Ÿ’ก vtable์€ ๊ฐ€์ƒ ๋ฉ”์†Œ๋“œ ํ…Œ์ด๋ธ”๋กœ ์ปดํŒŒ์ผ ํƒ€์ž„์— ์ƒ์„ฑ๋˜์–ด ๋ฉ”์†Œ๋“œ๊ฐ€ ํ˜ธ์ถœ๋˜์—ˆ์„ ๋•Œ ์‚ฌ์šฉํ•  ๊ตฌํ˜„์ฒด๋ฅผ ๋Ÿฐํƒ€์ž„์— ํŠน์ •ํ•  ์ˆ˜ ์žˆ๊ฒŒ ํ•ด์ค๋‹ˆ๋‹ค.
๐Ÿ’ก vtable์€ ๋ฉ”์†Œ๋“œ ๊ตฌํ˜„์ฒด์˜ ์ฃผ์†Œ๋ฅผ ๋ฐฐ์—ด๋กœ ๊ฐ€์ง€๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ํด๋ž˜์Šค๋งˆ๋‹ค vtable์ด ์กด์žฌํ•ฉ๋‹ˆ๋‹ค.

-> ์•„์ง ์ •ํ™•ํžˆ ์ž˜ ๋ชจ๋ฅด๊ฒ ์–ด์„œ https://developer.apple.com/videos/play/wwdc2016/416/ ์ด๊ฑฐ๋ถ€ํ„ฐ ๋ณด๋ ค๊ตฌ์š”ใ… 

 

61. ํ”„๋กœํผํ‹ฐ ์˜ต์ €๋ฒ„์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

๐Ÿ’ก ํ”„๋กœํผํ‹ฐ ์˜ต์ €๋ฒ„๋Š” ์ €์žฅ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์ด ๋ณ€ํ™”ํ•˜๋Š” ๊ฒƒ์„ ๊ด€์ฐฐํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก willSet๊ณผ didSet์„ ์‚ฌ์šฉํ•ด์„œ ํ”„๋กœํผํ‹ฐ์˜ ๊ฐ’์ด ๋ณ€ํ™”ํ•  ๋•Œ ํ•จ๊ป˜ ์‹คํ–‰ํ•  ์ž‘์—…์„ ์ •์˜ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก willSet์€ ์ƒˆ๋กœ ๋ณ€ํ™”๋  ๊ฐ’์„ newValue๋ผ๋Š” ํ”„๋กœํผํ‹ฐ๋กœ ์ œ๊ณตํ•˜๊ณ , didSet์€ ๋ณ€ํ™”๋˜๊ธฐ ์ „ ๊ฐ’์„ oldValue๋ผ๋Š” ํ”„๋กœํผํ‹ฐ๋กœ ์ œ๊ณตํ•ฉ๋‹ˆ๋‹ค.

  class A {
  var name: String {
      willSet {
          print("\(name) will be changed to \(newValue)")
      }
      didSet {
          print("\(oldValue) is changed to \(name)")
      }
  }

  init(name: String) {
      self.name = name
  }
  }

  let a = A(name: "A")
  a.name = "B"
  // A will be changed to B
  // A is changed to B

๐Ÿ’ก ์—ฐ์‚ฐํ”„๋กœํผํ‹ฐ๋Š” ๋ถ€๋ชจ ํด๋ž˜์Šค์˜ ์—ฐ์‚ฐ ํ”„๋กœํผํ‹ฐ๋ฅผ ์˜ค๋ฒ„๋ผ์ด๋”ฉํ•˜๋Š” ๊ฒฝ์šฐ๋งŒ ํ”„๋กœํผํ‹ฐ ์˜ต์ €๋ฒ„๋ฅผ ์ถ”๊ฐ€ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

 

61. Property Wrapper์— ๋Œ€ํ•ด ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

๐Ÿ’ก ํ”„๋กœํผํ‹ฐ ๋ž˜ํผ๋Š” ์—ฌ๋Ÿฌ ํ”„๋กœํผํ‹ฐ์— ๋Œ€ํ•ด ๋ฐ˜๋ณต๋˜๋Š” ์ฝ”๋“œ๋ฅผ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋„๋ก ํ•ด์ฃผ๋Š” ๊ธฐ๋Šฅ์ž…๋‹ˆ๋‹ค.
๐Ÿ’ก @propertyWrapper๋กœ ๊ตฌ์กฐ์ฒด๋ฅผ ์ •์˜ํ•˜๊ณ  ๋‚ด๋ถ€์— ํ”„๋กœํผํ‹ฐ์— ๋Œ€ํ•œ ๋™์ž‘์„ ์ •์˜ํ•ด๋‘๋ฉด, ํ”„๋กœํผํ‹ฐ๋ฅผ ์„ ์–ธํ•  ๋•Œ ํ”„๋กœํผํ‹ฐ ๋ž˜ํผ๋ฅผ ํ‚ค์›Œ๋“œ๋กœ ๋ถ™์—ฌ ๋ฏธ๋ฆฌ ์ •์˜ํ•œ ๋™์ž‘์„ ์žฌ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

  @propertyWrapper
  struct TwelveOrLess {
      private var number = 0
      var wrappedValue: Int {
          get { return number }
          set { number = min(newValue, 12) }
      }
  }
  struct SmallRectangle {
  @TwelveOrLess var height: Int
  @TwelveOrLess var width: Int
  }

  var rectangle = SmallRectangle()
  print(rectangle.height)
  // Prints "0"

  rectangle.height = 10
  print(rectangle.height)
  // Prints "10"

  rectangle.height = 24
  print(rectangle.height)
  // Prints "12"

 

62. ๊ณ ์ฐจํ•จ์ˆ˜ ์ค‘ flatMap๊ณผ compactMap์˜ ์ฐจ์ด๋ฅผ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

๐Ÿ’ก compactMap์€ 1์ฐจ์› ๋ฐฐ์—ด์—์„œ ๊ฐ ์š”์†Œ์— ๋Œ€ํ•ด nil์„ ์ œ๊ฑฐํ•˜๊ณ  ์˜ต์…”๋„ ๋ฐ”์ธ๋”ฉ์„ ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐฐ์—ด๋กœ ๋งŒ๋“ค์–ด ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก flatMap์€ ๋ฐฐ์—ด์˜ ์š”์†Œ ํƒ€์ž…์ด ์˜ต์…”๋„์ด๋ผ๋ฉด, nil์„ ์ œ๊ฑฐํ•˜๊ณ  ์˜ต์…”๋„ ๋ฐ”์ธ๋”ฉ์„ ํ•œ ๊ฒฐ๊ณผ๋ฅผ ๋ฐฐ์—ด๋กœ ๋งŒ๋“ค์–ด ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก flatMap์€ 2์ฐจ์› ๋ฐฐ์—ด์ด๋ฉด์„œ ์š”์†Œ ํƒ€์ž…์ด ์˜ต์…”๋„์ด ์•„๋‹ˆ๋ผ๋ฉด, ๋ฐฐ์—ด์˜ ์š”์†Œ๋“ค์„ 1์ฐจ์›์œผ๋กœ ํ•ฉ์นœ ๋ฐฐ์—ด์„ ๋ฐ˜ํ™˜ํ•˜๊ณ  nil์˜ ์ œ๊ฑฐ์™€ ์˜ต์…”๋„ ๋ฐ”์ธ๋”ฉ์€ ํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

  let test = [1, nil, 2, nil, 3, nil]
  print(test.compactMap({ $0 }))
  // [1, 2, 3]

  let test = [1, nil, 2, nil, 3, nil]
  print(test.flatMap({ $0 }))
  // [1, 2, 3]

  let test = [[1, nil], [2, nil], [3, nil]]
  print(test.flatMap({ $0 }))
  // [Optional(1), nil, Optional(2), nil, Optional(3), nil]

  let test = [[1, nil], [2, nil], [3, nil]]
  print(test.flatMap({ $0 }).compactMap({ $0 }))
  // [1, 2, 3]

  let test = [[1, nil], [2, nil], [3, nil]]
  print(test.compactMap({ $0 }).flatMap({ $0 }))
  // [Optional(1), nil, Optional(2), nil, Optional(3), nil]

  let test = [[1, nil], [2, nil], [3, nil], nil]
  print(test.compactMap({ $0 }).flatMap({ $0 }))
  // [[Optional(1), nil], [Optional(2), nil], [Optional(3), nil]]

 

63. High Order Function์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

๐Ÿ’ก ๊ณ ์ฐจํ•จ์ˆ˜๋Š” ํ•จ์ˆ˜๋ฅผ ์ธ์ž๋กœ ๋ฐ›๊ฑฐ๋‚˜ ํ•จ์ˆ˜๋ฅผ ๊ฒฐ๊ณผ๋กœ ๋ฐ˜ํ™˜ํ•  ์ˆ˜ ์žˆ๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.

  func test(execution: () -> Void) {
  execution()
  }

 

64. ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ์€ ๋ฌด์—‡์ธ๊ฐ€์š”? Swift๋Š” ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ธ๊ฐ€์š”?

๐Ÿ’ก ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋žจ๋ฐ์€ ์ˆœ์ˆ˜ ํ•จ์ˆ˜๋ฅผ ๊ธฐ๋ฐ˜์œผ๋กœ ํ•˜๋Š” ํ”„๋กœ๊ทธ๋ž˜๋ฐ ํŒจ๋Ÿฌ๋‹ค์ž„์ž…๋‹ˆ๋‹ค. ์ˆœ์ˆ˜ ํ•จ์ˆ˜๋Š” ์–ด๋–ค ์ž…๋ ฅ์— ๋Œ€ํ•ด ํ•ญ์ƒ ๊ฐ™์€ ์ถœ๋ ฅ์„ ๋งŒ๋“œ๋Š” ํ•จ์ˆ˜๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ์ฆ‰, ์™ธ๋ถ€์— ์˜ํ–ฅ์„ ์ฃผ๊ฑฐ๋‚˜ ๋ฐ›๋Š” side effect๊ฐ€ ์—†์Šต๋‹ˆ๋‹ค.
๐Ÿ’ก ์Šค์œ„ํ”„ํŠธ๋Š” ํ•จ์ˆ˜ํ˜• ํ”„๋กœ๊ทธ๋ž˜๋ฐ ์–ธ์–ด์ด๋ฉด์„œ ๋™์‹œ์— ๊ฐ์ฒด ์ง€ํ–ฅ ํ”„๋กœ๊ทธ๋žจ๋ฐ ์–ธ์–ด์˜ ํŠน์ง•์ธ ์ƒ์†, ์€๋‹‰, ์บก์Šˆํ™”, ์ถ”์ƒํ™” ๋“ฑ์„ ์ œ๊ณตํ•˜๋Š” ๋ฉ€ํ‹ฐ ํŒจํ„ฐ๋‹ค์ž„ ์–ธ์–ด์ž…๋‹ˆ๋‹ค.

 

65. ์ˆœ์ˆ˜ํ•จ์ˆ˜๊ฐ€ ๋ฌด์—‡์ธ๊ฐ€์š”?

๐Ÿ’ก ์ˆœ์ˆ˜ํ•จ์ˆ˜๋Š” ๋™์ผํ•œ ์ž…๋ ฅ์— ๋Œ€ํ•ด ํ•ญ์ƒ ๋™์ผํ•œ ์ถœ๋ ฅ์„ ๊ฐ€์ง€๋Š” ํ•จ์ˆ˜์ž…๋‹ˆ๋‹ค.
๐Ÿ’ก ์ˆœ์ˆ˜ํ•จ์ˆ˜๋Š” ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๋ฅผ ๊ฐ€์ง€๋ฉด ์•ˆ๋ฉ๋‹ˆ๋‹ค.

 

66. ๊ทธ๋Ÿผ ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๋Š” ๋ฌด์—‡์ธ๊ฐ€์š”?

๐Ÿ’ก ์‚ฌ์ด๋“œ ์ดํŽ™ํŠธ๋Š” ํ•จ์ˆ˜๋ฅผ ํ†ตํ•ด ํ•จ์ˆ˜ ์™ธ๋ถ€ ๊ฐ’์˜ ์ƒํƒœ๊ฐ€ ๋ณ€ํ•˜๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.

  var name = “hunihun956”
    func getName() -> String { // input(()) -> output(String from outer scope) | Side Effect
    return name
  }

  func getName(name: String) -> String {  // input(String) -> output(String) | No Side Effect
    return name
  }

 

67. ์ˆœ์ˆ˜ ํ•จ์ˆ˜๊ฐ€ ์™œ ํ•„์š”ํ•˜๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋‚˜์š”?

๐Ÿ’ก ๊ฐ™์€ ์ž…๋ ฅ์— ๋Œ€ํ•ด ํ•ญ์ƒ ๊ฐ™์€ ์ถœ๋ ฅ์„ ๋งŒ์กฑํ•˜๋Š” ์ˆœ์ˆ˜ํ•จ์ˆ˜๋Š” ํ…Œ์ŠคํŠธ๊ฐ€ ์šฉ์ดํ•ฉ๋‹ˆ๋‹ค. ์™ธ๋ถ€ ์ƒํƒœ์— ์˜ํ–ฅ์„ ๋ฐ›์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํ•ด๋‹น ํ•จ์ˆ˜๋งŒ ํ…Œ์ŠคํŠธํ•  ์ˆ˜ ์žˆ๊ธฐ ๋•Œ๋ฌธ์ž…๋‹ˆ๋‹ค.
๐Ÿ’ก ์‚ฌ์ดํŠธ ์ดํŽ™ํŠธ๊ฐ€ ์—†๋‹ค๋Š” ๊ฒƒ์€ ์ˆœ์ˆ˜ ํ•จ์ˆ˜๋“ค์„ ํฌํ•จํ•˜๋Š” ๊ฐ์ฒด์˜ ์œ ์ง€๋ณด์ˆ˜์„ฑ์ด ์ข‹๋‹ค๋Š” ๊ฒƒ์„ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค. ํ”„๋กœํผํ‹ฐ๋‚˜ ํ•จ์ˆ˜๋“ค์ด ๋‹ค๋ฅธ ํ•จ์ˆ˜๋“ค์— ์˜์กด์ ์ด์ง€ ์•Š๊ธฐ ๋•Œ๋ฌธ์— ํ™•์žฅ๊ณผ ๋ณ€๊ฒฝ์ด ์‰ฝ๊ฒŒ ๊ฐ€๋Šฅํ•ฉ๋‹ˆ๋‹ค.

 

68. 1๊ธ‰ ๊ฐ์ฒด(ํ˜น์€ 1๊ธ‰ ์‹œ๋ฏผ)์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”. Swift์—๋Š” ์–ด๋–ค 1๊ธ‰ ๊ฐ์ฒด๋“ค์ด ์žˆ๋‚˜์š”?

๐Ÿ’ก 1๊ธ‰ ๊ฐ์ฒด๋Š” ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ์ „๋‹ฌ๋˜๊ฑฐ๋‚˜ ๋ฐ˜ํ™˜ ๊ฐ’์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด๋ฅผ ์˜๋ฏธํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ๋˜ 1๊ธ‰ ๊ฐ์ฒด๋Š”๋ณ€์ˆ˜๋‚˜ ์ƒ์ˆ˜์— ํ• ๋‹น ํ•  ์ˆ˜ ์žˆ๋Š” ๊ฐ์ฒด์ž…๋‹ˆ๋‹ค.
๐Ÿ’ก ์Šค์œ„ํ”„ํŠธ๋Š” ๊ธฐ๋ณธ ํƒ€์ž…๋“ค๊ณผ ํ•จ์ˆ˜๋‚˜ ํด๋กœ์ €๊นŒ์ง€ ๋ชจ๋‘ 1๊ธ‰ ๊ฐ์ฒด์— ํ•ด๋‹นํ•ฉ๋‹ˆ๋‹ค.

 

69. Optional์€ ๋‚ด๋ถ€์ ์œผ๋กœ ์–ด๋–ป๊ฒŒ ๊ตฌํ˜„๋˜์–ด ์žˆ๋‚˜์š”?

๐Ÿ’ก Optional์€ associated value๋ฅผ ๊ฐ€์ง€๋Š” enum์œผ๋กœ ๊ตฌํ˜„๋˜์–ด ์žˆ์Šต๋‹ˆ๋‹ค. ๊ฐ’์ด ์กด์žฌํ•  ๋•Œ๋Š” some์— ์ €์žฅ๋œ ๊ฐ’์„ ๋ฐ˜ํ™˜ํ•˜๊ณ , ๊ฐ’์ด ์กด์žฌํ•˜์ง€ ์•Š์œผ๋ฉด nil์„ ๋ฐ˜ํ™˜ํ•ฉ๋‹ˆ๋‹ค.

@frozen
enum Optional<Wrapped> {
  case none
  case some(Wrapped)
}

 

70. Swift์—์„œ ์ฐธ์กฐ ํƒ€์ž…์„ ๋งํ•ด๋ณด์„ธ์š”.

๐Ÿ’ก ํด๋ž˜์Šค, ํ•จ์ˆ˜, ํด๋กœ์ €๊ฐ€ ๋ชจ๋‘ ์ฐธ์กฐ ํƒ€์ž…์ž…๋‹ˆ๋‹ค.

 

71. String์€ ์™œ subscript๋กœ ์ ‘๊ทผํ•  ์ˆ˜ ์—†์„๊นŒ์š”?

๐Ÿ’ก String์„ ๊ตฌ์„ฑํ•˜๋Š” ๊ฐ ๋ฌธ์ž๋“ค์€ ์—ฌ๋Ÿฌ๋ฌธ์ž๊ฐ€ ํ•ฉ์„ฑ๋œ Unicode Scalar ๋กœ ์ด๋ฃจ์–ด์ ธ ์žˆ์Šต๋‹ˆ๋‹ค. ๋”ฐ๋ผ์„œ ํ•œ ๋ฌธ์ž๊ฐ€ ๊ฐ™์€ ํฌ๊ธฐ์˜ ๋ฉ”๋ชจ๋ฆฌ๋ฅผ ๊ฐ€์ง€์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

// https://docs.swift.org/swift-book/LanguageGuide/StringsAndCharacters.html#//apple_ref/doc/uid/TP40014097-CH7-ID285
let eAcute: Character = "\u{E9}"                         // é
let combinedEAcute: Character = "\u{65}\u{301}"          // e followed by ฬ
// eAcute is é, combinedEAcute is é

 

72. Result ํƒ€์ž…์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

๐Ÿ’ก Result๋Š” success์™€ failure case ๋ฅผ ๊ฐ€์ง€๋Š” enum์ž…๋‹ˆ๋‹ค.
๐Ÿ’ก failure ์ผ€์ด์Šค์˜ associated value๋Š” ๋ฐ˜๋“œ์‹œ Error ํ”„๋กœํ† ์ฝœ์„ ์ฑ„ํƒํ•ด์•ผํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก ๋„คํŠธ์›Œํฌ์™€ ๊ฐ™์ด ์‹คํŒจํ•  ๊ฐ€๋Šฅ์„ฑ์ด ์žˆ๋Š” ์ž‘์—…์˜ ์„ฑ๊ณต์—ฌ๋ถ€์™€ ๊ฒฐ๊ณผ๋ฅผ ์‰ฝ๊ฒŒ ํ‘œํ˜„ํ•  ์ˆ˜ ์žˆ์Šต๋‹ˆ๋‹ค.

// https://www.hackingwithswift.com/articles/161/how-to-use-result-in-swift
fetchUnreadCount1(from: "https://www.hackingwithswift.com") { result in
  switch result {
  case .success(let count):
      print("\(count) unread messages.")
  case .failure(let error):
      print(error.localizedDescription)
  }
}

 

73. some ํ‚ค์›Œ๋“œ์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

๐Ÿ’ก some์€ opqaue result type์ž…๋‹ˆ๋‹ค.
๐Ÿ’ก ํ•จ์ˆ˜ ๋‚ด๋ถ€์—์„œ ๋ฐ˜ํ™˜๋˜๋Š” ํƒ€์ž…์„ ์™ธ๋ถ€์—์„œ ๋ช…ํ™•ํ•˜๊ฒŒ ์•Œ ์ˆ˜ ์—†๋„๋กํ•ฉ๋‹ˆ๋‹ค.

// Error. ๊ตฌ์ฒดํƒ€์ž…์„ ๋ช…์‹œํ•˜์ง€ ์•Š์Œ
func someList() -> Collection {
  return [1,2,3]
}

// OK. ๊ตฌ์ฒดํƒ€์ž…์„ ์•Œ ์ˆ˜๋Š” ์—†์ง€๋งŒ Collection์„ ์ฑ„ํƒํ•˜๋Š” ํƒ€์ž…์ด ๋ฐ˜ํ™˜๋  ๊ฒƒ์„ ๋ณด์ฆํ•จ
func someList() -> some Collection {
  return [1,2,3]
}

 

74. KVC์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

๐Ÿ’ก KVC๋Š” Key-Value Coding์œผ๋กœ ๊ฐ์ฒด์˜ ๊ฐ’์„ ์ง์ ‘ ์‚ฌ์šฉํ•˜์ง€ ์•Š๊ณ  KeyPath๋ฅผ ์ด์šฉํ•ด ๊ฐ„์ ‘์ ์œผ๋กœ ์‚ฌ์šฉํ•˜๊ณ  ์ˆ˜์ •ํ•˜๋Š” ๋ฐฉ๋ฒ•์ž…๋‹ˆ๋‹ค.
๐Ÿ’ก {๋ฐฑ์Šฌ๋ž˜์‹œ(\)}.{ํƒ€์ž…}.{keypath} ๋กœ keypath๋ฅผ ๋งŒ๋“ค์–ด ์‚ฌ์šฉํ•  ์ˆ˜๋„ ์žˆ์Šต๋‹ˆ๋‹ค.

struct A {
    var data = "Data"
}

var aInstance = A()
print(aInstance[keyPath: \.data]) // Data
print(aInstance.data) // Data
aInstance[keyPath: \.data] = "Data2"
print(aInstance[keyPath: \.data]) // Data2

let key = \A.data
print(aInstance[keyPath: key]) // Data2

 

75. KVO์— ๋Œ€ํ•ด์„œ ์„ค๋ช…ํ•ด๋ณด์„ธ์š”.

๐Ÿ’ก KVO๋Š” Key-Value Oberving์œผ๋กœ ์–ด๋–ค Key์— ๋“ฑ๋ก๋œ ๋ณ€์ˆ˜๊ฐ€ ๋ณ€๊ฒฝ์ด ๋˜๋Š” ๊ฒƒ์„ ๊ด€์ฐฐํ•˜๊ณ  ๋ณ€๊ฒฝ์ด ๋ฐœ์ƒํ•  ๋•Œ๋งˆ๋‹ค ํŠน์ •ํ•œ ์ž‘์—…์„ ์ˆ˜ํ–‰ํ•˜๊ธฐ ์œ„ํ•ด ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.
๐Ÿ’ก Objective-C ๋Ÿฐํƒ€์ž„์— ์˜์กดํ•˜๊ธฐ ๋•Œ๋ฌธ์— NSObject๋ฅผ ์ฑ„ํƒํ•ด์•ผํ•˜๊ณ , ๊ด€์ฐฐํ•  ํ”„๋กœํผํ‹ฐ์—๋Š” @objc ์™€ dynamic ํ‚ค์›Œ๋“œ๋ฅผ ๋ถ™์—ฌ์•ผ ํ•ฉ๋‹ˆ๋‹ค.

class Obj: NSObject {
    @objc dynamic var data = "Data"
}

let obj = Obj()
let observer = obj.observe(\.data, options: [.new, .old]) { _, changeInfo in
    print("\(changeInfo.oldValue) has been changed to \(changeInfo.newValue)")
}

obj.data = "Data2"
// Optional("Data") has been changed to Optional("Data2")

Questions Source

๐Ÿ’ก https://www.fullstack.cafe/interview-questions/swift
๐Ÿ’ก https://github.com/JeaSungLEE/iOSInterviewquestions