๊ณต๋ถ€ ์—ฐ์Šต์žฅ :-)

์ปค์Šคํ…€ UICollectionViewCell์˜ ์˜คํ† ๋ ˆ์ด์•„์›ƒ- Relative to margin์˜ต์…˜

|

์ปค์Šคํ…€ ์ปฌ๋ ‰์…˜๋ทฐ ์…€์„ ์‚ฌ์šฉํ•˜๋‹ค๊ฐ€ ์•Œ๊ฒŒ๋œ Relative to margin์— ๊ด€ํ•œ๊ฒƒ๊ณผ ์‚ฝ์งˆ๊ธฐโ€ฆ

Background

  • ์•„๋ž˜์˜ HolidaysCellํด๋ž˜์Šค๋Š” ๋งˆํŠธ์ง€์ ์˜ ํœด๋ฎค์ผ์„ ํ‘œ์‹œํ•˜๋Š” ์ปค์Šคํ…€ ์ปฌ๋ ‰์…˜๋ทฐ ์…€
  • UIButton์„ ์ด์šฉํ•˜์—ฌ text ์ฃผ๋ณ€์— padding์„ ๋„ฃ๊ณ ์‹ถ์–ด์„œ UIButton์„ ํ”„๋กœํผํ‹ฐ๋กœ ๊ฐ–๊ณ ์žˆ์œผ๋ฉฐ, ๋ฒ„ํŠผ์˜ contentEdgeInsets์†์„ฑ์„ ์กฐ์ •ํ•˜์—ฌ padding ํšจ๊ณผ๋ฅผ ์ค€๋‹ค.
  • ์•ฑ ๋‚ด์— ๊ฐ๊ธฐ ๋‹ค๋ฅธ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ํœด๋ฌด์ผ์„ ํ‘œ์‹œํ•ด์•ผํ–ˆ๊ธฐ๋•Œ๋ฌธ์— ํ•ด๋‹น ์…€์„ ์žฌํ™œ์šฉํ•˜๊ณ ์‹ถ์—ˆ์Œ
  • ์ด๋ฅผ ์ด์šฉํ•˜๊ธฐ์œ„ํ•ด ์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ ๋˜‘๊ฐ™์€ ์—ญํ• ์„ ํ•˜๋Š” ๋‘ ๊ฐœ์˜ ์ฝœ๋ ‰์…˜๋ทฐ๋ฅผ ๋งŒ๋“ค์–ด์„œ ๊ฐ๊ฐ ๋‹ค๋ฅธ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์— ์˜ฌ๋ฆผ
  • ํ•˜์ง€๋งŒ ๋‘ ์ฝœ๋ ‰์…˜๋ทฐ ์…€์˜ ์ปค์Šคํ…€ํด๋ž˜์Šค๋˜ํ•œ ๋˜‘๊ฐ™์ด HolidaysCell ํด๋ž˜์Šค๋กœ ์ง€์ •ํ•ด์คŒ
class HolidaysCell: UICollectionViewCell {

    @IBOutlet weak var holidayDate: UIButton!

    override func awakeFromNib() {
        super.awakeFromNib()
        holidayDate.contentEdgeInsets = UIEdgeInsets(top: 3, left: 5, bottom: 3, right: 5)
        holidayDate.layer.cornerRadius = 7.0
        holidayDate.clipsToBounds = true
        holidayDate.backgroundColor = UIColor.darkGray
        holidayDate.titleLabel?.textColor = UIColor.white
        holidayDate.isUserInteractionEnabled = false
    }

    func setData(text: String) {
        holidayDate.setTitle(text, for: .normal)
        holidayDate.setAttributedTitle(self.makeTextWithAttributes(of: text), for: .normal)
    }
    // ...    
}

Issue!!

  • ํ•˜์ง€๋งŒ Delegate์—์„œ ๋˜‘๊ฐ™์€ ํฌ๊ธฐ๋กœ ์ง€์ •ํ•ด์ค˜๋„ ๋‹ค๋ฅด๊ฒŒ ๋ณด์ž„โ€ฆ Cellํด๋ž˜์Šค์˜ ์ปจํ…์ธ  margin๋•Œ๋ฌธ์— ๋‹ค๋ฅด๊ฒŒ ๋ณด์ด๋Š”๋“ฏํ•œ ๋Š๋‚Œ!!ใ… ใ… 
  • padding๊ฐ’์ด ๋‚ด๊ฐ€ ์›ํ•˜๋Š”๊ฒƒ๋ณด๋‹ค ๋” ํฌ๊ฒŒ ๋“ค์–ด๊ฐ€์„œ ๋ฒ„ํŠผ์œ„์˜ ํ…์ŠคํŠธ ๋๋ถ€๋ถ„์ด ์ž˜๋ ค๋ณด์˜€๋‹ค.
  • ์ฝ”๋“œ๋กœ ์•„๋ฌด๋ฆฌ ์ฝœ๋ ‰์…˜๋ทฐ์˜ inset์ด๋‚˜ ์…€์˜ inset์„ ๋ฐ”๊ฟ”๋ด๋„๋˜‘๊ฐ™์Œ

Resolve

  • ์Šคํ† ๋ฆฌ๋ณด๋“œ์™€ ๋ทฐ ๋””๋ฒ„๊ฑฐ์—์„œ ๋ณด๋‹ˆ margin์ด ์ ์šฉ๋œ autoLayout ์„ ์ด ์ฐจ์ด์ ์ž„์„ ๋ฐœ๊ฒฌ
  • autoLayout์„ค์ •์—์„œ first์™€ second item์—์„œ Relative to margin์˜ต์…˜์„ ์ฒดํฌํ•ด์ œํ•จ
  • margin์—†์ด cell์˜ ์ฝ˜ํ…์ธ ๊ฐ€ ์ ์šฉ๋˜์–ด ํ•ด๊ฒฐ!

  • Relative to margin์˜ต์…˜์ด ํ•ด์ œ๋œ constraint ๋ผ์ธ
  • Relative to margin์˜ต์…˜์ด ์ฒดํฌ๋œ constraint ๋ผ์ธ. ํ•ด๋‹น ์˜คํ† ๋ ˆ์ด์•„์›ƒ ๋ผ์ธ ์•ˆ์ชฝ์œผ๋กœ ์ปจํ…์ธ ๊ฐ€ ๋“ค์–ด๊ฐ€๊ฒŒ๋œ๋‹ค.



  • ์Šคํ† ๋ฆฌ๋ณด๋“œ์˜ ์ธ์ŠคํŽ™ํ„ฐ์—์„œ autoLayout์˜ Relative to margin ์˜ต์…˜์„ ํ•ด์ œํ•˜์—ฌ ํ•ด๊ฒฐ!

TIL_20180820 ~ 20180825

|

2018.08.20

  • ๋„ค๋น„๊ฒŒ์ด์…˜ bar์— ๊ฐ€๋ ค์ง€๋Š” frame ์ˆ˜์ •
  • ์ฝ”๋“œ๋กœ safeArea์˜์—ญ ์•Œ์•„๋‚ด๋Š”๋ฒ• ์„œ์นญ

2018.08.22

  • ํ‘ธ์‹œ์— ๋Œ€ํ•ด์„œ ๊ณต๋ถ€!
  • ๊ผผ๊ผผํ•œ ์žฌ์€์”จ - ๋กœ์ปฌํ‘ธ์‹œ๋ถ€ํ„ฐ ๋จผ์ € ใ…Ž_ใ…Ž

์งˆ๋ฌธํˆฌ์„ฑ์ด

์•Œ๋ฆฐ [8:08 PM]
์—ฌ๋Ÿฌ๋ถ„ใ… ใ…  ๋งŒ์•ฝ ๋ฃจํŠธ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ์‹ฑ๊ธ€ํ†ค ํ”„๋กœํผํ‹ฐ๋ฅผ ๊ฐ€์ง€๊ณ ์žˆ์œผ๋ฉด AppDelegate์˜ `application()`ํ•จ์ˆ˜๊ฐ€ ์‹คํ–‰๋˜๊ธฐ๋„ ์ „์— ๋จผ์ € ๋ฃจํŠธ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์˜ ํ”„๋กœํผํ‹ฐ๊ฐ€ ์ดˆ๊ธฐํ™”๋˜๋Š”๊ฑด๊ฐ€์š”โ€ฆ?
class MainViewController: UIViewController {
    let favorites = FavoriteList.shared().martList
    ...
}

์‹ฑ๊ธ€ํ†ค ํ”„๋กœํผํ‹ฐ๋Š” ์ €๋ ‡๊ฒŒ ๊ฐ€์ง€๊ณ ์žˆ๊ณ ์š”, ๋™์ž‘์„ ์ด์ƒํ•˜๊ฒŒ ํ•˜๊ธธ๋ž˜ ๋ธŒ๋ ˆ์ดํฌํฌ์ธํŠธ๋ฅผ ๊ฑธ์–ด๋ดค๋”๋‹ˆ ๋จผ์ € ์ € ์ฝ”๋“œ์˜  `let favorites = FavoriteList.shared().martList` ์ด๊ฒŒ ๋จผ์ € ์‹คํ–‰๋˜๊ณ  ๊ทธ ๋‹ค์Œ์— `application()`ํ•จ์ˆ˜๋ฅผ ํƒ€๋„ค์š”! ๋ญ”๊ฐ€ ์ด์ƒํ•œ๊ฑด์ง€ ํ™•์‹ ํ• ์ˆ˜๊ฐ€ ์—†์–ด์„œ ์งˆ๋ฌธํ•ฉ๋‹ˆ๋‹น!โ€ฆ?_?

๋ƒ…์Šคํ„ฐ [8:18 PM]
๋ทฐ๋””๋“œ๋กœ๋“œํ• ๋•Œ ์ดˆ๊ธฐํ™”ํ•˜๋ฉด ์–ด๋–จ๊นŒ์š”

Mason [8:36 PM]
static์€ ํ•ญ์ƒ ๋จผ์ € ํ• ๋‹น๋˜๋Š”๊ฑธ๋กœ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค
ํด๋ž˜์Šค๋‚˜ ๊ตฌ์กฐ์ฒด์•ˆ์— static์œผ๋กœ ์„ ์–ธ๋œ ํ”„๋กœํผํ‹ฐ๊ฐ€ ์žˆ์„๊ฒฝ์šฐ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•˜์ง€ ์•Š์•„๋„ ~์ ‘๊ทผํ• ์ˆ˜ ์žˆ๋Š”์ด์œ ๋กœ ์•Œ๊ณ  ์žˆ์–ด์š”~ static์€ ๊ธ€๋กœ๋ฒŒ ์˜์—ญ์ด๋ผ์„œ(๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค ์ œ์ด์ผ€์ด) (edited)
shared()๋„ ํƒ€์ž…๋ฉ”์„œ๋“œ๋ผ๋ฉด static์ฒ˜๋Ÿผ ๋จผ์ € ๋ฉ”๋ชจํžˆ์— ์˜ฌ๋ผ๊ฐ€์„œ ๊ทธ๋Ÿฌ์ง€ ์•Š์„๊นŒ์š”
๋งŒ์•ฝ์— FavoriteList๊ฐ€ ์‹ฑ๊ธ€ํ†ค ๊ฐ์ฒด๋ผ๋ฉด ๊ตณ์ด ํ”„๋กœํผํ‹ฐ๋กœ ๊ฐ–๊ณ  ์žˆ์„ ํ•„์š”๊ฐ€ ์—†์–ด๋„๋ ๊ฑฐ๊ฐ™์•„์š”

์•Œ๋ฆฐ [8:39 PM]
๋„ค๋„ค ์‚ฌ์‹ค ์ €๊ฑด ๋˜๋Š”์ง€ํ™•์ธ์„ ์œ„ํ•ด์„œ ๊ธ‰ํ•˜๊ฒŒ ์ง  ์ฝ”๋“œ๋ผโ€ฆใ…‹ใ…‹ใ…‹ ๊ทธ๋ž˜์„œ ์ง€๊ธˆ์€ ๋ฃจํŠธ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์˜ ํ”„๋กœํผํ‹ฐ๋ฅผ ์•ฑ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ์—์„œ ํ• ๋‹นํ•ด์ฃผ๋Š”๊ฑธ๋กœ ๋ฐ”๊ฟจ์–ด์š”
static์ด๋ผ์„œ ๋จผ์ € ๋ธŒ๋ ˆ์ดํฌํฌ์ธํŠธ์— ๊ฑธ๋ฆฌ๋Š”๊ฑฐ์˜€๊ตฐ์š” ์ €๋Š” applicationํ•จ์ˆ˜๋ณด๋‹ค ๋‹ค๋ฅธ๊ฒŒ ๋จผ์ € ์‹คํ–‰๋˜๋Š” ๊ฒฝ์šฐ๋ฅผ ์ง€๊ธˆ ์ฒ˜์Œ ๋ด์„œใ… ใ… ใ… ๋ชฐ๋ž๋„ค์š” ๊ฐ์‚ฌํ•ฉ๋‹ˆ๋‹ค

Mason [8:49 PM]
ํƒ€์ž…ํ”„๋กœํผํ‹ฐ๋Š” ์ผ๋ฐ˜ ํ”„๋กœํผํ‹ฐ๋ž‘ ์ดˆ๊ธฐํ™” ์‹œ์ ์ด ์•„์˜ˆ ๋‹ฌ๋ผ์„œ ๊ทธ๋Ÿด๊ฑฐ์—์š” static์€ ํ•ญ์ƒ ๊ธฐ๋ณธ๊ฐ’์ด ์žˆ์–ด์•ผ๋˜๋Š” ์ด์œ ๋กœ ์•Œ๊ณ  ์žˆ์–ด์š”
@JK ๊ถ๊ธˆํ•ฉ๋‹ˆ๋‹ค ํ”„๋กœ๊ทธ๋žจ ์‹คํ–‰์‹œ ๋ฉ”๋ชจ๋ฆฌ ํ• ๋‹น์€ ์Šคํƒ์ด ๋จผ์ € ํ• ๋‹น์ด๋˜๋‚˜์š”?

JK [8:52 PM]
์Šคํƒ์€ ํ•จ์ˆ˜๊ฐ€ ํ˜ธ์ถœ๋ ๋•Œ๋งˆ๋‹ค ์ž…๋‹ˆ๋‹ค. ๋จผ์ €๋ผ๋Š”๊ฑด ์ƒ๋Œ€์ ์ธ ์‹œ๊ฐ„์ฐจ์ด์ผ ๋ฟ์ด์ฃ .

JK [8:58 PM]
์ฐธ๊ณ ๋กœ static์€ ๊ธ€๋กœ๋ฒŒ ๋ณ€์ˆ˜ ๊ฐœ๋…์ด๋ผ ๋กœ๋”ฉ์‹œ์ ์— ๋จผ์ € ์ƒ์„ฑ๋˜๊ธฐ๋„ ํ•ฉ๋‹ˆ๋‹ค.

Mason [8:58 PM]
class์™€ struct์ƒ๊ด€์—†๋‚˜์š”?
ํด๋ž˜์Šคํƒ€๋‹™์•ˆ์— ์„ ์–ธ๋œ static๋„ ํž™์ด ์•„๋‹Œ ์Šคํƒ ๊ณต๊ฐ„์— ์˜ฌ๋ผ๊ฐ€๋‚˜์š”?(๋ณ„๋กœ ์ค‘์š”ํ•œ๊ฑด ์•„๋‹™๋‹ˆ๋‹ค...) (edited)

JK [9:08 PM]
์œ„์— static ์–˜๊ธฐํ•œ ๊ธ€๋กœ๋ฒŒ์€ ์Šคํƒ. ํž™๊ณผ ๋ณ„๊ฐœ์ธ ๊ธ€๋กœ๋ฒŒ ์˜์—ญ์ž…๋‹ˆ๋‹ค.

JK [9:14 PM]
@์•Œ๋ฆฐ rootVC๊ฐ€ AppDelegate.window ์— ๋“ค์–ด๊ฐ€๋Š” ์ธ์Šคํ„ด์Šค๋ผ์„œ ์ดˆ๊ธฐํ™” ์‹œ์ ์— ๋งŒ๋“ค์–ด์ง‘๋‹ˆ๋‹ค. ๊ทธ๋•Œ ๊ฐ™์ด ๋ฉ”๋ชจ๋ฆฌ์— ํ• ๋‹น๋˜๋Š”๊ฑฐ์ฃ .
๊ทธ๋ฆฌ๊ณ ๋‚˜์„œ ๋ฉ”๋ชจ๋ฆฌ ์ž‘์—…์ด ๋๋‚˜๋ฉด ์ฝœ๋ฐฑ์ด ํ˜ธ์ถœ๋˜๊ณ !!

Mason [9:17 PM]
๋˜ ๋ฐฐ์›Œ๊ฐ‘๋‹ˆ๋‹ค

๋ƒ…์Šคํ„ฐ [10:09 PM]
์™€์šฐ

์•Œ๋ฆฐ [2:05 PM]
@JK ์–ด์ œ ๋‹ต๋ณ€์ฃผ์‹ ๊ฑฐ์—๋Œ€ํ•ด์„œ ๊ถ๊ธˆํ•œ๊ฒŒ ์žˆ๋Š”๋ฐ์š”ใ…‹_ใ…‹ ์–ด์ œ ๋˜ ๋” ํ•˜๋‹ค๋ณด๋‹ˆ๊นŒ
์ง€๊ธˆ ์ œ ์•ฑ์˜ ๋ชจ๋“  ๋ทฐ์ปจ์ด ๋„ค๋น„๊ฒŒ์ด์…˜์ปจํŠธ๋กค๋Ÿฌ์— embed๋˜์–ด์žˆ์–ด์„œ,
์•ฑ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ์—์„œ  `let rootVC = self.window?.rootViewController` ์ด๋ ‡๊ฒŒ ์ ‘๊ทผํ•œ ๋ฃจํŠธ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ๋Š” MainViewController๊ฐ€ ์•„๋‹ˆ๋ผ UINavigationControllerํƒ€์ž…์ด๋”๋ผ๊ณ ์š”
๊ทผ๋ฐ ์–ด์ œ์˜ let favorites ๋ณ€์ˆ˜๋Š” MainViewController์˜ ํ”„๋กœํผํ‹ฐ์˜€๋Š”๋ฐ, ๊ทธ๋Ÿฌ๋ฉด ์–ด์ œ ๋ง์”€ํ•˜์‹  ์ดˆ๊ธฐํ™”์‹œ์ ์—์„œ๋Š” ๋ฃจํŠธ๋ทฐ์ธ UINavigationController๋ฟ๋งŒ์ด ์•„๋‹ˆ๋ผ ์™œ MainViewController๊นŒ์ง€ ๋ฉ”๋ชจ๋ฆฌ์— ํ• ๋‹น๋˜๋Š”๊ฑด๊ฐ€์š”?_?

์ œ ์ถ”์ธก์—” entry point๊ฐ€ ์•„๋ฌด๋ฆฌ ๋„ค๋น„๊ฒŒ์ด์…˜ ์ปจํŠธ๋กค๋Ÿฌ์—ฌ๋„ ์ฒซ ํ™”๋ฉด์—” MainViewController๊นŒ์ง€ ๋ณด์ด๋‹ˆ๊นŒ window๊ฐ€ ์ฒ˜์Œ์— ๋ณด์ด๋Š” ๋ชจ๋“  ํ™”๋ฉด์„ ๋‹ค ์ดˆ๊ธฐํ™”ํ•˜๋ ค๊ณ ํ•ด์„œ ๊ทธ๋Ÿฐ๊ฑฐ๊ฐ™๋‹ค๊ณ  ์ƒ๊ฐ์€ ํ•˜๋Š”๋ฐ..๊ถ๊ธˆํ•ด์„œ์š”!

๋ƒ…์Šคํ„ฐ [2:06 PM]
๋ฉ”์ธ๋ทฐ๊ฐ€์žˆ์–ด์•ผ ๋„ค๋น„๊ฒŒ์ด์…˜์ปจํŠธ๋กค๋Ÿฌ๋„ ์žˆ์–ด์„œ ๊ทธ๋Ÿฐ๊ฑฐ์•„๋‹๊นŒ์š” ๋ผ๋Š” ์ถ”์ธก์„ ๋‚จ๊ธฐ๊ณ  ์‚ฌ๋ผ์ง‘๋‹ˆ๋‹ค..

์•Œ๋ฆฐ [2:07 PM]
์•ˆ๋ผโ€ฆ

jake [2:07 PM]
๋นŒ๋“œ ์‹œ์ ์—์„œ ๋ชจ๋“  ํด๋ž˜์Šค๋ž‘ ์ŠคํŠธ๋ŸญํŠธ๋ฅผ ๊ฒ€์‚ฌํ• ๊ฑฐ์—์š”
๊ทธ๋Ÿฌ๋ฉด์„œ ํž™๋ฉ”๋ชจ๋ฆฌ๋‚˜ ์Šคํƒ์— ์Œ“์„๊ฒƒ๋“ค์ด ๊ตฌ๋ถ„๋˜์–ด์„œ ์ €์žฅํ•˜๊ณ  ์žˆ๋Š”๋ฐ
๊ทธ ๊ณผ์ •์—์„œ static๋ณ€์ˆ˜๊ฐ€ ๋”ฐ๋กœ ๊ด€๋ฆฌ๋˜๋Š”๊ฑฐ์ฃ 
๊ทธ๋Ÿฐ ๊ฒƒ๋“ค์ด ์ •์˜ ๋˜์–ด ์žˆ๊ธฐ ๋•Œ๋ฌธ์— ๋‚˜์ค‘์— ๋ฐ”๋กœ ์ฐธ์กฐํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋Š”๊ฑธ๋กœ ์•Œ๊ณ  ์žˆ์Šต๋‹ˆ๋‹ค

์•Œ๋ฆฐ [2:13 PM]
์•„ํ•˜ ๊ทธ๋Ÿผ `let favorites`๋ณ€์ˆ˜๊ฐ€ ๊ทธ๋ƒฅ ์ผ๋ฐ˜์ ์ธ ๋กœ์ปฌ๋ณ€์ˆ˜์˜€๋‹ค๋ฉด ์–ด์ œ์ฒ˜๋Ÿผ ๋™์ž‘ํ•˜์ง€ ์•Š์•˜์„ ์ˆ˜ ์žˆ๊ฒ ๋„ค์š”..? Favorites.shared()๋ผ๋Š” static์— ์ ‘๊ทผํ•ด์„œ ๊ทธ๋ ‡๊ฒŒ ๋™์ž‘ํ•œ๊ฑด๊ฐ€..

jake [2:15 PM]
main๋ง๊ณ  ๋‹ค๋ฅธ๋ฐ๋„ ์ฐ์–ด๋ณด์…จ๋‚˜์š”? ๋กœ๋ฒŒ ๋ณ€์ˆ˜์—๋„ ์ฐ์–ด๋ณด์„ธ์š”
ํด๋ž˜์Šค๊ฐ€ ๋งŒ๋“ค์–ด์งˆ๋•Œ ์ „๋ถ€ ์ ‘๊ทผํ•˜๊ณ 
๋งŒ๋“ค์–ด์ง„ ์ •๋ณด๋ฅผ ๊ฐ€์ง€๊ณ  application์ด ๋™์ž‘ํ•˜๋Š”๊ฒŒ ์•„๋‹๊ฐ€ ์‹ถ๋„ค์š”

Mason [2:21 PM]
์ฐพ์•˜๋‹ค..์˜ˆ์ „์— ๋ถ„๋ช…ํžˆ ์ œ์ด์ผ€์ด๊ฐ€ ๊ฐ•์˜๋•Œ ๋ณด์—ฌ์ฃผ์…จ์—ˆ๋Š”๋ฐโ€ฆ๋ผ์ฆˆ๋ฒ ๋ฆฌํŒŒ์ด ์Šฌ๋ผ์ด๋“œ์— ์žˆ์—ˆ๋„ค์š”!
Pasted image at 2018-08-22, 2:21 PM

GVAR์ €๊ธฐ๊ฐ€ ์–ด์ œ ๋ง์”€ํ•ด์ฃผ์‹  ๊ธ€๋กœ๋ฒŒ์˜์—ญ์ธ๋“ฏํ•ฉ๋‹ˆ๋‹ค
static๋ณ€์ˆ˜๋Š” ์ € ์˜์—ญ์— ์ €์žฅ๋˜๋Š”๊ฑฐ๊ฒ ์ฃ 
(์•„ ์ด๊ฑด ์œ—๋ถ„๋“ค ์งˆ๋ฌธ๊ณผ ๋ณ„๊ฐœ๋กœโ€ฆ ๊ณต์œ โ€ฆ) (edited)

2018.08.23

  • ๋ถ€์ŠคํŠธ์ฝ”์Šค ํŠน๊ฐ•์„ ๋‹ค๋…€์˜ด. ์‹ ์ž… ๊ฐœ๋ฐœ์ž๋กœ ์ทจ์—…ํ•ด์•ผํ• ๋•Œ ์ฑ™๊ฒจ์•ผ ํ•  ๊ฒƒ๋“ค์„ ์•Œ ์ˆ˜ ์žˆ์—ˆ๋‹ค.

2018.08.25

  • ์ฃผ๋ง์„ ํ™”๋ คํ•˜๊ฒŒ ์žฅ์‹ํ•œ ์ฝœ๋ ‰์…˜๋ทฐ ์…€์— ์ฝœ๋ ‰์…˜๋ทฐ ๋„ฃ๊ธฐ ์‚ฝ์งˆ..

  • FavoriteCollectionView์˜ cell ๋‚ด๋ถ€์— ๋˜ ๋‹ค๋ฅธ ์ฝœ๋ ‰์…˜๋ทฐ๋ฅผ ๋„ฃ์–ด์•ผํ•˜๋Š” ์ƒํ™ฉ(holidaysCollectionView)
  • holidaysCollectionView๋˜ํ•œ ๋ฉ”์ธ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์—ฐ๊ฒฐํ•˜๊ณ  delegate์™€ dataSource๋ฅผ ๋‹ด๋‹นํ•˜๋ คํ–ˆ์œผ๋‚˜ ๋ฐ˜๋ณต๋˜๋Š” ์š”์†Œ๋Š” outlet์œผ๋กœ ์—ฐ๊ฒฐํ• ์ˆ˜ ์—†๋‹ค๋Š” ์—๋Ÿฌ ๋ฐœ์ƒ
  • FavoriteCollectionView์˜ ์…€์ด ์žฌ์‚ฌ์šฉ๋˜๋ฉด์„œ ๋‚ด๋ถ€์˜ holidaysCollectionView๊ฐ€ ์—ฌ๋Ÿฌ๊ฐœ ์ƒ๊ธฐ๊ธฐ๋•Œ๋ฌธ
  • ๋”ฐ๋ผ์„œ holidaysCollectionView์˜ delegate์™€ dataSource๋Š” MainViewController๊ฐ€ ๋‹ด๋‹นํ•  ์ˆ˜ ์—†๊ณ  FavoriteCollectionView์˜ ์…€(favoriteCell)์ด ๋‹ด๋‹นํ•ด์•ผ ํ•˜๋Š” ์ƒํ™ฉ
  • ํ•˜์ง€๋งŒ favoriteCell์€ ๋ทฐ์ž„โ€ฆ
  • holidaysCollectionView์˜ delegate์™€ dataSource๋ฅผ ๋‹ด๋‹นํ•  ๋‹ค๋ฅธ ๋ชจ๋ธ๊ฐ์ฒด๋ฅผ ๋งŒ๋“ค๊ณ  favoriteCell๋‚ด๋ถ€์—์„œ ์ž์‹  ๋‚ด๋ถ€์—์žˆ๋Š” ์ฝœ๋ ‰์…˜๋ทฐ์˜ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ์™€ ๋ฐ์ดํ„ฐ์†Œ์Šค๋ฅผ ๋ถ€์—ฌํ•˜๋Š” ํ๋ฆ„์œผ๋กœ ๊ฐ€๊ธฐ๋กœ ๊ฒฐ์ •..!
  • ์ฐธ๊ณ ๋งํฌ-stackoverflow
  • โ€ฆ.ํ•˜์ง€๋งŒ ๋‚ ์งœ์ฝœ๋ ‰์…˜๋ทฐ๊ฐ€ ํ‘œ์‹œ๋˜์ง€์•Š์Œ!
  • ์œ„์—์„œ ํ๋ฆ„์„ ์ €๋ ‡๊ฒŒ ์ง€์ •ํ•˜๊ณ , ์•„๋ž˜์™€ ๊ฐ™์ด ์‹คํ–‰ํ–ˆ๋‹ค. ํ•˜์ง€๋งŒ ์ฝœ๋ ‰์…˜๋ทฐ์…€ ๋‚ด๋ถ€์˜ ์ฝœ๋ ‰์…˜๋ทฐ๊ฐ€ ํ‘œ์‹œ๋˜์ง€์•Š๋Š”๋‹ค..
  • FavoriteCellํด๋ž˜์Šค๋Š” ๋ทฐ์ด๊ธฐ๋•Œ๋ฌธ์— ์…€ ๋‚ด๋ถ€์— ๋“ค์–ด๊ฐ€๋Š” ์ฝœ๋ ‰์…˜ ๋ทฐ(holidaysCollectionView)์˜ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ์™€ ๋ฐ์ดํ„ฐ์†Œ์Šค ์—ญํ• ์„ ๋ถ„๋ฆฌํ•˜๋ ค๊ณ  ์‹œ๋„
  • ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ์™€ ๋ฐ์ดํ„ฐ์†Œ์Šค ์—ญํ• ์„ ํ•˜๋Š” HolidaysManager๊ฐ์ฒด ๋งŒ๋“ฆ
  • holidaysManager๋ฅผ MainViewController(์ตœ์ƒ์œ„๋ทฐ์ปจ)์—์„œ favoriteCell์„ ๋งŒ๋“ค๋•Œ setData()ํ•จ์ˆ˜์— ๋„˜๊ฒจ์ฃผ๊ณ , ํ•จ์ˆ˜๋‚ด๋ถ€์—์„œ ํ•˜์œ„ ์ฝœ๋ ‰์…˜๋ทฐ(holidaysCollectionView)์˜ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ๋ฅผ ์ง€์ •ํ•ด์ฃผ์—ˆ๋‹ค.
// MainViewController
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

    let martList = FavoriteList.shared().martList()
    let cell = favoritesCollectionView.dequeueReusableCell(withReuseIdentifier: MainViewController.favoriteCellID, for: indexPath) as! FavoriteCell
    let holidaysManager = HolidaysCollecionViewManager(dateData: martList[indexPath.row].holidays)
    cell.setData(branch: martList[indexPath.row], holidaysManager: holidaysManager)

// FavoriteCell
func setData<T: UICollectionViewDataSource & UICollectionViewDelegate & UICollectionViewDelegateFlowLayout>(branch: Branch, holidaysManager: T) {
    title.text = "\(branch.martType) \(branch.branchName)"
    // holidayDateCollectionView ์„ธํŒ…
    holidaysCollectionView.delegate = holidaysManager
    holidaysCollectionView.dataSource = holidaysManager
    holidaysCollectionView.reloadData()

}

// HolidayManager
class HolidaysCollecionViewManager: NSObject, UICollectionViewDataSource, UICollectionViewDelegate, UICollectionViewDelegateFlowLayout {

    var dateData: [String]

    init(dateData: [String]) {
        self.dateData = dateData
    }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return self.dateData.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "holidaysCell", for: indexPath) as! HolidaysCell
        cell.setData(text: dateData[indexPath.row])
        return cell
    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        return CGSize(width: collectionView.frame.width / 3, height: collectionView.frame.height/2.5)

    }

    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, minimumLineSpacingForSectionAt section: Int) -> CGFloat {
        return 5

    }

}

TIL_20180813 ~ 20180818

|

2018.08.13

  • segue๋กœ nextVC๋„์šฐ๊ธฐ์—์„œ nextVC์˜ didSet์—์„œ ์—๋Ÿฌ๊ฐ€ ๋‚˜์„œ ์ •๋ฆฌ
    • ์•„๋ž˜์ฝ”๋“œ์—์„œ ๋ณด๋ฉด SearchViewController์˜ prepare()๋ฉ”์†Œ๋“œ์—์„œ ์Šคํ† ๋ฆฌ๋ณด๋“œ segue์— ๋”ฐ๋ผ์„œ ๋™์ž‘
    • segue๊ฐ€ ์‹คํ–‰๋˜๋ฉด์„œ nextVC์˜ awakeFromNib() ์‹คํ–‰.
    • ์ด๋•Œ nextVC์˜ self๋Š” ์ธ์Šคํ„ด์Šคํ™”๋œ ์ƒํƒœ
    • ์ƒ์œ„๋ชจ๋“ˆ์—์„œ nextVC.branchData์˜ ๋ฐ์ดํ„ฐ ๊ฐ’์„ ๋„˜๊ฒจ์ฃผ๋ฉด์„œ didSet์‹คํ–‰์ด๋˜๋Š”๋ฐ
    • ์ด๋•Œ๊นŒ์ง€๋„ IBOutlet์˜ ํ”„๋กœํผํ‹ฐ๋Š” nil์ƒํƒœ
    • nextVC๊ฐ€ ์ธ์Šคํ„ด์Šคํ™”๋œ ์ƒํƒœ์—ฌ๋„ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์Šคํ† ๋ฆฌ๋ณด๋“œ๋กœ ์—ฐ๊ฒฐ๋œ IBOutlet๋“ค์€ ์ฐธ์กฐ๊ด€๊ณ„๊ฐ€ ๋ถˆ๋ช…ํ™•ํ•œ ์‹œ์ ์ด ์žˆ๋‹ค. ์ด๋•Œ๊ฐ€ ๋ฐ”๋กœ ๊ทธ ์‹œ์ ์ธ๋“ฏํ•˜๋‹ค.
    • viewDidLoad()๊ฐ€ ์‹คํ–‰๋˜๋Š” ์‹œ์ ์—๋Š” nil์ด์—ˆ๋˜ IBOutletํ”„๋กœํผํ‹ฐ๋“ค์ด ๋กœ๋“œ๊ฐ€ ์™„๋ฃŒ๋œ ์‹œ์ 
    • IBOutlet์„ ์„ธํŒ…ํ•˜๋Š” ๋™์ž‘์€ viewDidLoad์—์„œ ํ•˜๋ฉด ๋™์ž‘ํ•œ๋‹ค.

// SearchViewController.swift
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    guard segue.identifier == "showDetail" else { return }
    guard let nextVC = segue.destination as? DetailViewController else { return }
    if let indexPath = tableView.indexPathForSelectedRow {
        if isFiltering() {
            nextVC.branchData = filtered!.branches[indexPath.row]
        } else {
            nextVC.branchData = list!.branches[indexPath.row]
        }
    }
}
}

// DetailViewController.swift
    var branchData: Branch? {
        didSet {
            print("didSet")
        }
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        print(#function)
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        setNavigationItem()
        setTitle()
        setAddress()
        setHolidays()
        setPhoneNumber()
    }

2018.08.14

  • https://developers.naver.com/docs/map/ios/

  • ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์˜ ๋™์ž‘์„ xcode9์˜ main thread checker๊ฐ€ ์ฒดํฌํ•˜๋ฉด์„œ ๋‚˜ํƒ€๋‚˜๋Š” ์—๋Ÿฌ
  • ๋™์ž‘์€ ํ•˜์ง€๋งŒ ๋ฉ”์ธ์Šค๋ ˆ๋“œ์ฒด์ปค์—์„œ UI๋ฅผ ๋‹ด๋‹นํ•˜๋Š” ๋ถ€๋ถ„์€ ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ๋™์ž‘ํ•˜๋„๋ก ๊ตฌํ˜„ํ•˜๋ผ๊ณ  ์—๋Ÿฌ๋ฅผ ๋‚ด๊ฒŒ๋œ๋‹ค. (๋™์ž‘์€ ์ •์ƒ์ ์œผ๋กœ ํ•จ)
  • ์ฐธ๊ณ 
  • ์™ธ๋ถ€ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์—์„œ๋Š” ๋™์ž‘ํ•˜์ง€๋งŒ xcode9๊ธฐ์ค€์œผ๋กœ๋Š” ์ฒดํฌํ•ด์•ผํ•˜๋Š” exception์ด๋ผ ์ฒดํ‚น์€ ๋˜์ง€๋งŒ, ์™ธ๋ถ€๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ์ด๊ธฐ๋•Œ๋ฌธ์— ์–ด๋””์„œ ์—๋Ÿฌ๊ฐ€ ๋‚˜๋Š”์ง€ ์ฝ”๋“œ๋ผ์ธ์—์„œ ์ฐพ์ง€ ๋ชปํ•œ๋‹ค.
  • ์ด๋ฐฉ๋ฒ•์œผ๋กœ ์ฐพ์„ ์ˆ˜ ๋Š” ์žˆ์ง€๋งŒ ์ฐพ์•„๋„ ์–ด์…ˆ๋ธ”๋ฆฌ์ฝ”๋“œ์ชฝ๊นŒ์ง€ ๋‚ด๋ ค๊ฐ€์„œ ๋ธŒ๋ ˆ์ดํฌํฌ์ธํŠธ๊ฐ€ ๊ฑธ๋ ค์„œ ์–ด๋”˜์ง€ ์•Œ ์ˆ˜ ์—†์Œโ€ฆ
  • ๋Ÿฐํƒ€์ž„์‹œ ์™ธ๋ถ€ api์˜ ์Šค๋ ˆ๋“œ ์ฒดํ‚น์„ ํ•˜์ง€ ์•Š๋„๋ก ์„ค์ •ํ•˜๋ฉด ์—๋Ÿฌ๊ฐ€ ํ‘œ์‹œ๋˜์ง€ ์•Š๊ณ  ์ญ‰ ์‹คํ–‰
=================================================================
Main Thread Checker: UI API called on a background thread: -[UIApplication setNetworkActivityIndicatorVisible:]

2018.08.15

  • ๋ทฐ ์˜คํ† ๋ ˆ์ด์•„์›ƒ ์žก๊ธฐ
  • ์ฆ๊ฒจ์ฐพ๊ธฐ ๋ชจ๋ธ ๊ตฌํ˜„
  • JSONํŒŒ์ผ์ด ๋ณ€๊ฒฝ๋˜์–ด๋„ ๊ทธ๋Œ€๋กœ ์ฆ๊ฒจ์ฐพ๊ธฐ๊ฐ€ ์œ ์ง€๋˜๊ณ  ์—…๋ฐ์ดํŠธ๋˜๋Š”์ง€ ํ™•์ธ

2018.08.16

  • AppDelegate์˜ ์ฝœ๋ฐฑํ•จ์ˆ˜์—์„œ ์ฆ๊ฒจ์ฐพ๊ธฐ ๋ฐ์ดํ„ฐ๋ฅผ ์ €์žฅ / ๊ฐ€์ ธ์˜ฌ๋•Œ์˜ ์˜๋ฌธ์ 
      func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
          // loadedData๊ฐ€ ์—†๋Š”๊ฒฝ์šฐ favoriteList๋ฅผ ์ €์žฅํ•ด์ฃผ์ง€ ์•Š๊ณ  ๊ทธ๋ƒฅ ๋„˜์–ด๊ฐ€๋ฉด ํ•˜์œ„ ๋ชจ๋“ˆ๋“ค์—์„œ ์ ‘๊ทผํ•˜๋Š” FavoriteList.shared()๋กœ ๋ฐ›๋Š” ์ธ์Šคํ„ด์Šค๋Š” ๋ชจ๋‘ ๊ทธ๋ƒฅ Set<Int>()๋กœ init์ด ๋˜๋‹ˆ๊นŒ ์ƒ๊ด€์—†์Œ
          guard let loadedData = DataStorage<FavoriteList>.load() else { return true }
          FavoriteList.loadSavedData(loadedData) // Favorite๋ฆฌ์ŠคํŠธ๋ฅผ ์ €์žฅํ–ˆ๋˜ ์ธ์Šคํ„ด์Šค๋กœ ๋Œ€์ฒดํ•ด์คŒ
          return true
      }
    
// ์ฒซ ์‹œ์ž‘
application(_:didFinishLaunchingWithOptions:)
applicationDidBecomeActive
// ํ™ˆ๋ฒ„ํŠผ
applicationWillResignActive
applicationDidEnterBackground
// ์‹คํ–‰(๋ฐฑ๊ทธ๋ผ์šด๋“œ์˜€๋‹ค๊ฐ€ ๊ทธ๋Œ€๋กœ ๋‹ค์‹œ๋œฐ๋•Œ)
applicationWillEnterForeground
applicationDidBecomeActive

ํ™ˆ๋ฒ„ํŠผ ๋‘๋ฒˆ ๋ˆŒ๋Ÿฌ์„œ ์œ„๋กœ ์Šค์™€์ดํ”„ํ•˜์—ฌ ๋Œ๋•Œ ํ˜ธ์ถœ์ˆœ์„œ ํ…Œ์ŠคํŠธ

applicationWillResignActive
applicationDidEnterBackground
applicationWillTerminate

ํ…Œ์ŠคํŠธ์‹œ, ๋ฐฑ๊ทธ๋ผ์šด๋“œ ์ƒ๋Œ€๋กœ ๊ฐˆ๋•Œ ํ•ญ์ƒ ํ˜ธ์ถœ๋˜๋Š” ํ•จ์ˆ˜

applicationWillResignActive
applicationDidEnterBackground // ์˜ค๋žซ๋™์•ˆ active์ƒํƒœ๊ฐ€์•„๋‹๋•Œ
  • ์˜ˆ๋น„ / ์ง„์งœ state๋กœ ๋“ค์–ด๊ฐ€๋Š”๊ฑฐ ๊ผญ ๋‘๊ฐœ์”ฉ ํ˜ธ์ถœ๋˜๋Š”๋ฐ ์–ด๋–ป๊ฒŒ ๊ตฌ๋ถ„ํ•˜๊ณ  ํ•จ์ˆ˜๋ฅผ ๊ตฌํ˜„ํ•ด์•ผํ• ๊นŒ?
  • ๋ชจ๋‘ ๊ตฌํ˜„ํ•˜๋Š”๊ฒŒ ์ œ์ผ ์ข‹์ง€๋งŒ, ๋˜‘๊ฐ™์€ ๋™์ž‘์„ ๋ฐ˜๋ณตํ•˜๊ฒŒ ํ•˜๊ธฐ ๋ณด๋‹ค๋Š” ํ•ด๋‹น ์ฝœ๋ฐฑ๋“ค์ด ๋ถˆ๋ฆฌ๋Š” ์‹œ๊ฐ„์ฐจ๋™์•ˆ ๋‚ด๊ฐ€ ์ €์žฅํ•  ์ฆ๊ฒจ์ฐพ๊ธฐ ๋ฐ์ดํ„ฐ๊ฐ€ ๋ณ€๊ฒฝ์ด ๋๋Š”์ง€ flag๋ฅผ ๋‘๊ณ  flag์— ๋”ฐ๋ผ์„œ ๋™์ž‘ํ•˜๊ฒŒ ํ•˜๋Š”๊ฒŒ ์ข€ ๋” ๋‚˜์€ ๋ฐฉ๋ฒ•
  • ์•ฑ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ์ฝœ๋ฐฑํ•จ์ˆ˜ ์ค‘ resignActive๋‚˜ applicationWillTerminate๊ฐ™์€ ํ•จ์ˆ˜์—์„œ ๋น„๋™๊ธฐ์ž‘์—…์„ ํ•˜๋ฉด ํ•ด๋‹น ์ž‘์—…์ด ๋๋‚ ๋–„๊นŒ์ง€๋Š” ์œ ์ง€๋œ๋‹ค๊ณ  ํ•œ๋‹ค. ๋ณดํ†ต์€ 1๋ถ„๋‚ด์™ธ๋กœ ์•Œ๋ ค์ ธ์žˆ์ง€๋งŒ ์‹œ๊ฐ„์ด ๋” ํ•„์š”ํ•˜๋‹ค๋ฉด await์ฒ˜๋ฆฌ๋ฅผ ํ•ด์•ผ ํ•  ๊ฒƒ

2018.08.17

  • ํ…Œ์ด๋ธ”๋ทฐ ์…€์— ์žˆ๋˜ ๋ณ„ ์•„์ด์ฝ˜์„ ๋ฒ„ํŠผ์œผ๋กœ ๋ฐ”๊พธ๊ณ  state๋ณ€๊ฒฝ๋ ๋•Œ๋งˆ๋‹ค๋กœ ํšŒ์ƒ‰๋ณ„ - ๋…ธ๋ž€์ƒ‰ ๋ณ„๋กœ ๋ฐ”๊พธ๋‹ˆ๊นŒ async๋กœ ์ž‘์—…ํ•  ํ•„์š”๊ฐ€ ์—†์–ด์ง
  • ํ…Œ์ด๋ธ”๋ทฐ ์…€์˜ ๋ฐ์ดํ„ฐ๋ฅผ detailํ™”๋ฉด์—์„œ ๋ฐ”๊พธ๊ณ  ํ…Œ์ด๋ธ”๋ทฐ๋กœ ํ™”๋ฉด์ด ๋„˜์–ด๊ฐ€๋„ ํ•ด๋‹น ์…€์€ ์—…๋ฐ์ดํŠธ๋˜์ง€ ์•Š๊ณ  ํ•ด๋‹น ์…€์ด ํ™”๋ฉด์—์„œ ์‚ฌ๋ผ์กŒ๋‹ค๊ฐ€ ๋‚˜ํƒ€๋‚˜๊ฑฐ๋‚˜ search๋™์ž‘์„ ์‹คํ–‰ํ•ด์„œ ํ…Œ์ด๋ธ”๋ทฐ๊ฐ€ reload๋ ๋•Œ๋งŒ ์…€์ด ์—…๋ฐ์ดํŠธ๋จ
    • ์…€์—์„œ reuse๋ ๋•Œ ๋ฒ„ํŠผ ์ƒํƒœ๋ฅผ updateํ•  ์ˆ˜ ์—†์„๊นŒ ๊ณ ๋ฏผํ–ˆ๋Š”๋ฐ,
    • ์ด๋Ÿฐ ๊ฒฝ์šฐ๋Š” ํ…Œ์ด๋ธ”๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์—์„œ reload๋ฅผ ๋ฐ˜๋“œ์‹œ ํ•ด์ค˜์•ผํ•จ!
  • xib๋กœ ์‚ฌ์ด๋“œ๋ฐ” ์—ฐ๊ฒฐํ•จ!!!!!!!!!!!!
    • ์ฝœ๋ ‰์…˜๋ทฐ๋ฅผ ์‚ฌ์šฉํ•˜๋ ค๊ณ ํ–ˆ๋‹ค๊ฐ€ ๊ทธ๋Œ€๋กœ reuseํ•˜๋ฉด ์•ˆ๋ ๊ฑฐ๊ฐ™์•„์„œ.
    • ๊ทธ๋ฆฌ๊ณ  ์Šฌ๋ผ์ด๋“œ ๋ฉ”๋‰ด์— ๋“ค์–ด๊ฐ€๋Š” ๋ฉ”๋‰ด ์ˆ˜๊ฐ€ ๊ทธ๋ฆฌ ๋งŽ์ง€ ์•Š์•„์„œ
    • ๋ฒ„ํŠผ๊ณผ ์Šคํƒ๋ทฐ๋กœ ๊ตฌํ˜„ํ•˜๋ฉด ์˜คํžˆ๋ ค๋” ๋‚ด๊ฐ€ ์›ํ•˜๋Š” ์ฝ”๋“œ์™€ ๋ทฐ๋ฅผ ๋งŒ๋“ค ์ˆ˜ ์žˆ์„๊ฑฐ๊ฐ™์•„์„œ ๊ตฌํ˜„ํ–ˆ๊ณ , ์ผ๋ฐ˜์ ์ธ ๋ทฐ ์ปจํŠธ๋กค๋Ÿฌ ์œ„์— ๋„์šฐ๋Š” ๋ทฐ๊ฐ€ ์•„๋‹ˆ๋ผ ์‚ฌ์ด์ฆˆ๊ฐ€ ๋‹ค๋ฅด๊ธฐ๋•Œ๋ฌธ์— xib๋กœ ํ–ˆ๋‹ค.
  • ์ปค์Šคํ…€ ๋ธ๋ฆฌ๊ฒŒ์ดํŠธ ๋งŒ๋“ฆ: MainViewController
  • ์Šฌ๋ผ์ด๋“œ ๋ฉ”๋‰ด๋ฅผ ๋‹ซ๋Š” ๋™์ž‘์„ ํ•˜๋Š” ๋ฉ”์†Œ๋“œ๋Š” ์–ด๋””์„œ ๊ตฌํ˜„ํ•ด์•ผํ• ๊นŒ?
    • (์Šฌ๋ผ์ด๋“œ ๋ฉ”๋‰ด๋ฅผ ๋‹ซ๋Š” ๋™์ž‘์„ ์œ„ํ•œ ์˜ต์ €๋ฒ„๋Š” ์–ด๋”” ๊ตฌํ˜„๋˜์–ด์•ผํ• ๊นŒ)
    • SlideMenu์—์„œ ๋‹ซ๊ธฐ ๋ฒ„ํŠผ์„ ๋ˆ„๋ฅด๋ฉด noti POST
    • SlideLauncher์—์„œ ๋ฐ›์•„์„œ dismiss๋ฅผ ๋ฐ”๋กœ ํ•ด๋ฒ„๋ ค์•ผํ•˜๋‚˜
    • delegate์ธ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ๋ฐ›์•„์„œ dismiss๋ฅผ ํ•ด์ค˜์•ผํ•˜๋‚˜..?

2018.08.18

  • ์ด๋ฏธ์ง€์™€ ํ…์ŠคํŠธ ํ•จ๊ป˜์žˆ๋Š” ๋ฒ„ํŠผ ๋งŒ๋“ค๊ธฐ
  • ์‚ฌ์ด๋“œ๋ฐ”๋ž‘ ๊ฒน์น˜๋Š” statusBar ํ™”๋ฉด์ฒ˜๋ฆฌ
  • ๊ฒฐ๊ตญ ๋„ค๋น„๊ฒŒ์ด์…˜์— embedํ•˜๊ธฐ๋กœโ€ฆ.

์Šค์œ„ํ”„ํŠธ ํด๋กœ์ €(Closure)

|

ํด๋กœ์ €์˜ ๊ฐ’ ํš๋“ Capture

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

Capture์˜ ๋ฌธ์ œ

  • ํด๋กœ์ € ๋‚ด๋ถ€์—์„œ ์ฐธ์กฐ๋ฅผ ํš๋“ํ•œ ๊ฐ’์€(ํด๋กœ์ €๊ฐ€ ์บก์ณํ•œ ๊ฐ’) ํด๋กœ์ € ๋‚ด๋ถ€์—์„œ ๊ณ„์† ์‚ด์•„์žˆ๋‹ค. (์ค‘์ฒฉํ•จ์ˆ˜ ๋‚ด๋ถ€์˜ ์ง€์—ญ๋ณ€์ˆ˜์ธ ๊ฒฝ์šฐ์—๋„ ํด๋กœ์ €๊ฐ€ ์บก์ณํ–ˆ๋‹ค๋ฉด ํด๋กœ์ € ๋‚ด๋ถ€์—์„œ ๊ณ„์† ์—†์–ด์ง€์ง€ ์•Š๊ณ  ์žˆ์Œ)
  • ๋”ฐ๋ผ์„œ ์บก์ณ๋œ ๊ฐ’์€ ์–ธ์ œ ํ˜ธ์ถœ์ด ๋˜๋”๋ผ๋„ ํด๋กœ์ € ๊ฐ๊ฐ ์ž์‹ ๋งŒ์˜ ์ฐธ์กฐ๋ฅผ ๋ฏธ๋ฆฌ ํš๋“ํ–ˆ๊ธฐ๋•Œ๋ฌธ์— ๊ณ„์†ํ•ด์„œ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ์œผ๋ฉฐ, ์ด๋Š” ํด๋กœ์ €์™€ ์ธ์Šคํ„ด์Šค ์‚ฌ์ด์˜ ๊ฐ•ํ•œ ์ฐธ์กฐ ์ˆœํ™˜ ๋ฌธ์ œ ๊ฐ€ ๋ฐœ์ƒ๋  ์ˆ˜ ์žˆ๋‹ค.

ํด๋กœ์ €๋Š” ์ฐธ์กฐํƒ€์ž…

  • let increment: (()->Int) = makeIncrement(for:2)
  • ์œ„์™€๊ฐ™์ด ํ•จ์ˆ˜์™€ ํด๋กœ์ €๋ฅผ ๋ณ€์ˆ˜์— ํ• ๋‹น ํ•˜๋Š” ๊ฒƒ์€ ์ƒ์ˆ˜๋‚˜ ๋ณ€์ˆ˜์— ์ฐธ์กฐ๋ฅผ ์„ค์ •ํ•˜๋Š”๊ฒƒ์ž„
  • ๋งŒ์•ฝ ํด๋กœ์ €์˜ ์ฐธ์กฐ๋ฅผ ๋‹ค๋ฅธ์ƒ์ˆ˜์— ํ• ๋‹นํ•ด์ค€๋‹ค๋ฉด ์ด๋Š” ๋‘ ์ƒ์ˆ˜๊ฐ€ ๋ชจ๋‘ ๊ฐ™์€ ํด๋กœ์ €๋ฅผ ๊ฐ€๋ฆฌํ‚จ๋‹ค๋Š”๋œป์ž„

ํƒˆ์ถœํด๋กœ์ € @escaping

  • ํ•จ์ˆ˜์˜ ์ธ์ž๋กœ ์ „๋‹ฌ๋œ ํด๋กœ์ €๊ฐ€ ํ•จ์ˆ˜ ์ข…๋ฃŒ ํ›„์— ํ˜ธ์ถœ๋ ๋•Œ ํด๋กœ์ €๊ฐ€ ํ•จ์ˆ˜๋ฅผ ํƒˆ์ถœ(escape)ํ•œ๋‹ค๊ณ  ํ‘œํ˜„ํ•จ
  • @escapingํ‚ค์›Œ๋“œ ์‚ฌ์šฉ
  • ๋น„๋™๊ธฐ์ž‘์—…์œผ๋กœ ํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋˜๊ณ  ๋‚œ ํ›„ ์ž‘์—…์ด ๋๋‚˜๊ณ  ํ˜ธ์ถœํ•  ํ•„์š”๊ฐ€ ์žˆ๋Š” ํด๋กœ์ €๋ฅผ ํƒˆ์ถœํด๋กœ์ €๋กœ ์‚ฌ์šฉํ•จ์œผ๋กœ์จ ํ•จ์ˆ˜ ์‹คํ–‰์˜ ์ˆœ์„œ๋ฅผ ๋ณด์žฅํ•ด์ค„ ์ˆ˜ ์žˆ๋‹ค.
  • ํƒˆ์ถœํด๋กœ์ €์ž„์ด ๋ช…ํ™•ํ•œ๋ฐ @escapingํ‚ค์›Œ๋“œ๋ฅผ ๋ช…์‹œํ•˜์ง€ ์•Š์œผ๋ฉด ์ปดํŒŒ์ผ ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•จ
  • ๋˜ํ•œ, ํƒˆ์ถœํด๋กœ์ €์—์„œ selfํ‚ค์›Œ๋“œ ํ‘œ์‹œ๋Š” ํ•„์ˆ˜์ž„ ```swift

typealias VoidvoidClosure = () -> Void

let firstClosure: VoidvoidClosure = { print(โ€œClosure Aโ€) }

let secondClosure: VoidvoidClosure = { print(โ€œClosure Bโ€) }

func returnOneClosure(first: @escaping VoidvoidClosure, second: @escaping VoidvoidClosure, shouldReturnFirstClosure: Bool) -> VoidvoidClosure { // ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์€ ํด๋กœ์ €๋ฅผ ๋‹ค์‹œ ๋ฆฌํ„ดํ•˜๊ธฐ๋•Œ๋ฌธ์— ํ•จ์ˆ˜ ๋ฐ–์œผ๋กœ ํƒˆ์ถœํ•˜๋Š” ํƒˆ์ถœ ํด๋กœ์ €์—ฌ์•ผํ•จ return shouldReturnFirstClosure ? first : second }

let returnedClosure = returnOneClosure(first: firstClosure, second: secondClosure, shouldReturnFirstClosure: true)

returnedClosure() // returnOneClosureํ•จ์ˆ˜์˜ ์ฒซ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ firstClosure๊ฐ€ ๋ฆฌํ„ด๋˜์–ด ์‹คํ–‰. Closure A ์ถœ๋ ฅ

var closures: [VoidvoidClosure] = []

// ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ์ „๋‹ฌ๋ฐ›์€ ํด๋กœ์ €๊ฐ€ ํ•จ์ˆ˜ ์™ธ๋ถ€์˜ ๋ณ€์ˆ˜์— ์ €์žฅ๋˜๋ฏ€๋กœ ํƒˆ์ถœํด๋กœ์ € func appendClosure(closure: @escaping VoidvoidClosure) { closures.append(closure) }


## withoutActuallyEscaping
> [๊ณต์‹๋ฌธ์„œ
](https://developer.apple.com/documentation/swift/2827967-withoutactuallyescaping)

- ์‹ค์ œ๋กœ๋Š” ํƒˆ์ถœํ•˜์ง€ ์•Š๋Š”๋ฐ ๋‹ค๋ฅธ ํ•จ์ˆ˜์—์„œ ํƒˆ์ถœ ํด๋กœ์ €๋ฅผ ์š”๊ตฌํ•˜๋Š” ์ƒํ™ฉ์— ํ•ด๋‹น
```swift
// withoutActuallyEscaping
func hasElements(in array: [Int], match predicate: (Int) -> Bool) -> Bool  {
    return (array.lazy.filter{ predicate($0) }.isEmpty == false)
} //Error: Closure use of non-escaping parameter 'predicate' may allow it to escape

func hasElements(in array: [Int], match predicate: (Int) -> Bool) -> Bool  {
    return withoutActuallyEscaping(predicate, do: { escapePredicate in
         return (array.lazy.filter{ escapePredicate($0) }.isEmpty == false)
    })
}
  • withoutActuallyEscaping์˜ ์ฒซ๋ฒˆ์งธ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ํƒˆ์ถœํด๋กœ์ €์ธ ์ฒ™ ํ•ด์•ผํ•˜๋Š” ๋น„ํƒˆ์ถœํด๋กœ์ € ์ „๋‹ฌ
  • withoutActuallyEscaping(_:do:)์—์„œ doํŒŒ๋ผ๋ฏธํ„ฐ๋Š” ์ด ๋น„ํƒˆ์ถœํด๋กœ์ €๋ฅผ ๋˜ ๋งค๊ฐœ๋ณ€์ˆ˜๋กœ ์ „๋‹ฌ๋ฐ›์•„ ์‹ค์ œ๋กœ ์ž‘์—…์„ ์‹คํ–‰ํ•  ํƒˆ์ถœํด๋กœ์ €๋ฅผ ์ „๋‹ฌํ•จ

TIL_20180805 ~ 20180812

|

2018.08.05

์ฃผ๋ง

  • RxSwift!!!!!1-3์ฑ•ํ„ฐ ๊ณต๋ถ€ ๋ณต์Šต
  • Letโ€™Swift ์ตœ์™„๋ณต RxSwift

  • ์งˆ๋ฌธ๊ฑฐ๋ฆฌ
    • scrollview์— subview๋กœ ์ด๋ฏธ์ง€๋ฅผ ์ถ”๊ฐ€ํ• ๋•Œ๋„ scrollview์˜ frame.origin๊ณผ ๋˜‘๊ฐ™์ด ์ถ”๊ฐ€ํ•ด์ค˜์•ผํ•˜๋Š”๊ฑด๊ฐ€? ์˜ˆ๋ฅผ๋“ค๋ฉด origin.y๊ฐ€ 0์œผ๋กœ ์„ค์ •๋˜๋ฉด ์Šคํฌ๋กค๋ทฐ ์˜ frame์œ„์น˜์— ๋”ฐ๋ผ์„œ ์œ„์น˜๋˜๋Š”์ง€
  • ์„œ๋ฒ„๊ฐ€ ๋ฌธ๋‹ซ๊ณ ๋‚˜์„œ ์š”์ฒญํ•˜๋ฉด json์œผ๋กœ ํŒŒ์‹ฑ๋˜๊ฒŒํ–ˆ๋Š”๋ฐ๋ฐ timeout์œผ๋กœ ์—๋Ÿฌ๋‚˜๊ณ  dataTask.resume()์š”์ฒญ ๋ณด๋ƒˆ๋‹ค๊ฐ€ ์•ฑ ๋กœ์ง์ด ๋”์ด์ƒ ์ง„ํ–‰๋˜์ง€ ์•Š๋Š”๊ฑธ๋กœ ๋ณด์ด๋‹ค๊ฐ€ ์ผ์ •์‹œ๊ฐ„ ์ง€๋‚˜๊ณ ๋‚˜์„œ error๋ธ”๋Ÿญ์œผ๋กœ ํƒ
  • ๋น„๋™๊ธฐ๋กœ ์š”์ฒญ์„ ์ญ‰ ๋ณด๋‚ด๋†”์„œ timeout๊ธฐ์ค€ ์‹œ๊ฐ„ ์ง€๋‚˜๊ณ  error๋ธ”๋Ÿญ ํƒ„๋“ฏ
  • error๋ธ”๋Ÿญ์—์„œ ์งœ๋†“์€๋Œ€๋กœ ๋กœ์ปฌ์˜ jsonํŒŒ์ผ๋กœ ํ…Œ์ด๋ธ”๋ทฐ์…€์˜ ์ •๋ณด ๋ฐ›์•„์™€์„œ ํ‘œ์‹œํ•˜๋Š” ์ค‘ ๋งˆ์ง€๋ง‰ ์นดํ…Œ๊ณ ๋ฆฌ๊นŒ์ง€ json์œผ๋กœ ํ‘œ์‹œํ•˜๋˜์ค‘(ํ™•์‹ค์น˜์•Š์Œ) ์•ฑ ์ฃฝ์–ด๋ฒ„๋ฆผ
  • ํƒ€์ž„์•„์›ƒ์‹œ๊ฐ„๋™์•ˆ ๊ณ„์† ์š”์ฒญ์„ ๋ณด๋‚ด๊ณ ์žˆ์—ˆ์„๊ฒƒ์œผ๋กœ ์ถ”์ •.
2018-08-02 00:27:16.479396+0900 StoreApp[20099:888781] Task <887E6A12-0A54-4B07-B1F6-6DF0ED0857EF>.<1> finished with error - code: -1001
2018-08-02 00:27:16.493938+0900 StoreApp[20099:888781] Task <D1A56284-7F25-4C01-93AE-90353BC268E2>.<2> finished with error - code: -1001
2018-08-02 00:27:33.895061+0900 StoreApp[20099:888781] Task <28FBBC7F-9930-4104-800C-978099688827>.<3> finished with error - code: -1001
2018-08-02 00:27:33.932263+0900 StoreApp[20099:890156] Task <887E6A12-0A54-4B07-B1F6-6DF0ED0857EF>.<1> HTTP load failed (error code: -999 [1:89])
Network error: Error Domain=NSURLErrorDomain Code=-1001 "The request timed out." UserInfo={NSUnderlyingError=0x60400025de80 {Error Domain=kCFErrorDomainCFNetwork Code=-1001 "(null)" UserInfo={_kCFStreamErrorCodeKey=-2102, _kCFStreamErrorDomainKey=4}}, NSErrorFailingURLStringKey=http://crong.codesquad.kr:8080/woowa/main, NSErrorFailingURLKey=http://crong.codesquad.kr:8080/woowa/main, _kCFStreamErrorDomainKey=4, _kCFStreamErrorCodeKey=-2102, NSLocalizedDescription=The request timed out.}

2018-08-02 00:27:34.709532+0900 StoreApp[20099:890156] Task <D1A56284-7F25-4C01-93AE-90353BC268E2>.<2> HTTP load failed (error code: -999 [1:89])
2018-08-02 00:27:34.713188+0900 StoreApp[20099:890156] Task <28FBBC7F-9930-4104-800C-978099688827>.<3> HTTP load failed (error code: -999 [1:89])
DataTask error: response

2018-08-02 00:27:47.118190+0900 StoreApp[20099:888727] *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3698.54.4/UITableView.m:2012
2018-08-02 00:27:47.128271+0900 StoreApp[20099:888727] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0.  The number of rows contained in an existing section after the update (8) must be equal to the number of rows contained in that section before the update (8), plus or minus the number of rows inserted or deleted from that section (8 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
*** First throw call stack:
(
	0   CoreFoundation                      0x000000010605b1e6 __exceptionPreprocess + 294
	1   libobjc.A.dylib                     0x0000000102168031 objc_exception_throw + 48
	2   CoreFoundation                      0x0000000106060472 +[NSException raise:format:arguments:] + 98
	3   Foundation                          0x0000000101c0b652 -[NSAssertionHandler handleFailureInMethod:object:file:lineNumber:description:] + 193
	4   UIKit                               0x000000010323ad9b -[UITableView _endCellAnimationsWithContext:] + 19031
	5   UIKit                               0x0000000103254787 -[UITableView endUpdates] + 75
	6   StoreApp                            0x00000001017babff _T08StoreApp0A14ViewControllerC010resetTableC033_5C3AD717C85DC9604A7179854EE8731CLLySay10Foundation9IndexPathVG10indexPaths_tFyycfU_ + 1391
	7   StoreApp                            0x00000001017be031 _T08StoreApp0A14ViewControllerC010resetTableC033_5C3AD717C85DC9604A7179854EE8731CLLySay10Foundation9IndexPathVG10indexPaths_tFyycfU_TA + 17
	8   StoreApp                            0x00000001017bac5d _T0Ig_IyB_TR + 45
	9   libdispatch.dylib                   0x000000010787b7ec _dispatch_client_callout + 8
	10  libdispatch.dylib                   0x0000000107888642 _dispatch_sync_thread_bound_invoke + 386
	11  libdispatch.dylib                   0x000000010787b7ec _dispatch_client_callout + 8
	12  libdispatch.dylib                   0x00000001078868cf _dispatch_main_queue_callback_4CF + 628
	13  CoreFoundation                      0x000000010601dc99 __CFRUNLOOP_IS_SERVICING_THE_MAIN_DISPATCH_QUEUE__ + 9
	14  CoreFoundation                      0x0000000105fe1ea6 __CFRunLoopRun + 2342
	15  CoreFoundation                      0x0000000105fe130b CFRunLoopRunSpecific + 635
	16  GraphicsServices                    0x0000000109d8aa73 GSEventRunModal + 62
	17  UIKit                               0x0000000103119057 UIApplicationMain + 159
	18  StoreApp                            0x00000001017bedd7 main + 55
	19  libdyld.dylib                       0x00000001078f8955 start + 1
	20  ???                                 0x0000000000000001 0x0 + 1
)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)

2018.08.06

  • ์ด๊ฑฐ ์งˆ๋ฌธํ•˜๊ธฐ
    • ์งˆ๋ฌธ๊ฑฐ๋ฆฌ
      1. Create a session configuration
      2. Create a session (with delegate)
      3. Create Task object with URL
      4. Send request with closure
      5. Wait for response (background)
      6. Wait and receive for data
      7. Finish or Error by closure

session() - 1,2,3 task๋งŒ๋“ค๊ณ  sessionํ•จ์ˆ˜ ์ข…๋ฃŒ task.resume() - 4,5?? viewDidLoad์ข…๋ฃŒ sessionํ•จ์ˆ˜์˜ taskํด๋กœ์ €์‹คํ–‰- ๋‹ค๋ฅธ thread์—์„œ..-6,7? (mainthread์—์„œ๋Š” viewdidLoadํ•จ์ˆ˜๊ฐ€ ์ข…๋ฃŒ๋์œผ๋ฏ€๋กœ ์•„๋ฌด ์ผ๋„ ์ผ์–ด๋‚˜์ง€์•Š๋Š”์ค‘) ํด๋กœ์ €์˜ response๋ฐ›๊ณ  ViewController์˜ storeItems ๊ฐ์ฒด์— ๊ฐ’์ด ํ• ๋‹น๋˜๋Š” ๋ธ”๋Ÿญ์—์„œ handler()์‹คํ–‰ ์ด ์ƒํƒœ์—์„œ viewdidLoad๋๋‚˜๋ฉด ๋นˆ ํ…Œ์ด๋ธ”๋ทฐ๋กœ ์ด๋ฏธ ๊ทธ๋ ค์กŒ๊ณ ๊ธฐ๋‹ค๋ฆฌ๋Š”์ค‘์ธ๊ฑด๊ฐ€?

  • viewDidLoad๊ฐ€๋๋‚˜๋ฉด storeItems๊ฐ€ ์—†๋Š” ์ƒํƒœ์—์„œ ํ…Œ์ด๋ธ”๋ทฐ ๊ทธ๋ฆผ
  • ์„ธ์…˜์œผ๋กœ๋ถ€ํ„ฐ storeItems๋ฅผ ๋ฐ›์Œ

  • ๋„ค๋น„๊ฒŒ์ด์…˜ ์ปจํŠธ๋กค๋Ÿฌ์— embed๋œ ์ƒํƒœ์—์„œ segue๋ฅผ ์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ๋งŒ๋“ค๊ณ  ์—ฐ๊ฒฐํ•ด์ฃผ๋ฉด ์ฝ”๋“œ๋กœ perform segue๋ฅผ ์•ˆํ•ด๋„ ๋ฌด์กฐ๊ฑด ํ•œ๋ฒˆ ๋œฌ๋‹ค!
  • segue๋ฅผ ์Šคํ† ๋ฆฌ๋ณด๋“œ์—์„œ ๋งŒ๋“ค๊ณ  performsegueํ•˜๋Š” ๊ฒฝ์šฐ๋Š” ํ•ด๋‹นํ•˜๋Š” segue์˜ identifier๊ฐ’์„ ๊ฐ€์ง€๊ณ  prepareํ• ๋•Œ ๋™์ž‘์„ ๊ตฌ๋ถ„ํ• ๋•Œ์— ์‚ฌ์šฉํ•˜๋Š”๊ฒƒ์ž„
  • ์กฐ๊ฑด์—๋”ฐ๋ผ์„œ segue๋ฅผ ์‹คํ–‰ํ•˜๊ฑฐ๋‚˜ ์‹คํ–‰ํ•˜์ง€ ์•Š์œผ๋ ค๊ณ  ํ•œ๋‹ค๋ฉด segue๋Š” ์ฝ”๋“œ๋กœ ๋งŒ๋“ค์–ด์„œ ์‹คํ–‰ํ•ด์•ผํ•œ๋‹ค.

2018.08.07

  • ํ…Œ์ด๋ธ”๋ทฐ ๋ฐ์ดํ„ฐ์™€ ๋ทฐ ๋กœ๋“œ์ค‘์˜ ์—๋Ÿฌ ์ฒ˜๋ฆฌ ์งˆ๋ฌธ
    • ๋น„๋™๊ธฐ์™€ ๋™๊ธฐ์—๋”ฐ๋ฅธ ์—๋Ÿฌ ์›์ธ ๊ตฌ๋ถ„
  • ์Šคํ† ์–ด์•ฑ Step8 PR๋ณด๋ƒ„
  • statusbar ์Šคํƒ€์ผ ๋ณ€๊ฒฝ appdelegate์—์„œํ•˜๋Š” ๋ฐฉ๋ฒ•
  • ์—์…‹ ์นดํƒˆ๋กœ๊ทธ์— color์—์…‹ ์ถ”๊ฐ€ํ•˜์—ฌ ์‚ฌ์šฉ. ํ”„๋กœ์ ํŠธ ๋‚ด์—์„œ ์ž์ฃผ ์“ฐ๋Š” ์ƒ‰๊น”์€ UIColor(named: "์—์…‹์ด๋ฆ„")์œผ๋กœ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค. ์งฑํŽธํ•จ! (์ฐธ๊ณ ๋งํฌ)
  • UITableView reloadSections๊ณผ IndexSet

๋น„๋™๊ธฐ

DataSetter์˜ tryDownload()ํ•จ์ˆ˜ ์ถ”๊ฐ€ํ›„ ์—๋Ÿฌ

์—๋Ÿฌ ์ƒํ™ฉ 1.

// ํ…Œ์ด๋ธ”๋ทฐ๊ฐ€ ๋œจ๊ธฐ๋„์ „์— ์—๋Ÿฌ
private func resetTableView(indexPaths: [IndexPath]) {
	 DispatchQueue.main.sync { [weak self] in
		 self?.tableView.beginUpdates()
		 self?.tableView.insertRows(at: indexPaths, with: .automatic)
		 self?.tableView.endUpdates()
	 }
 }
  • ๊ด€๋ จ์—๋Ÿฌ Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
  • ๋ฉ”์ธ ์Šค๋ ˆ๋“œ์—์„œ ๋™๊ธฐ๋กœ ์ž‘์—…์„ ์ฒ˜๋ฆฌํ•˜๊ธฐ๋•Œ๋ฌธ์— ๋ฐ๋“œ๋ฝ ๊ฑธ๋ฆผ
  • ์›๋ž˜ DataSetter๊ฐ™์€ ๊ฐ์ฒด์—์„œ ๋ฐ”๋กœ URLSession.shared.dataTask๋ฅผ ์‚ฌ์šฉํ•˜๊ธฐ๋•Œ๋ฌธ์— ํ•ด๋‹น ์ฝ”๋“œ์— ์žˆ๋Š” ํด๋กœ์ €๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ๊ณณ์ด main์ด ์•„๋‹Œ ๋‹ค๋ฅธ์Šค๋ ˆ๋“œ์˜€๊ธฐ๋•Œ๋ฌธ์—

์—๋Ÿฌ ์ƒํ™ฉ 2.

// ํ…Œ์ด๋ธ”๋ทฐ๊ฐ€ ๋œจ์ง€๋งŒ ์ด๋ฏธ์ง€๋Š” ๋œจ์ง€ ์•Š๊ณ  UIApplicationMain
private func resetTableView(indexPaths: [IndexPath]) {
		DispatchQueue.main.async { [weak self] in
				self?.tableView.beginUpdates()
				self?.tableView.insertRows(at: indexPaths, with: .automatic)
				self?.tableView.endUpdates()
		}
}
  • ๊ด€๋ จ ์—๋Ÿฌ
  • ์„น์…˜์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์‹œ์ ์ด ๋ชจ๋ธ ์—…๋ฐ์ดํŠธ ์‹œ์ ๊ณผ ๋งž์ง€ ์•Š์Œ (async)
    *** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKit_Sim/UIKit-3698.54.4/UITableView.m:2012
    2018-08-06 20:44:29.940777+0900 StoreApp[70331:4708122] *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of rows in section 0.  The number of rows contained in an existing section after the update (8) must be equal to the number of rows contained in that section before the update (8), plus or minus the number of rows inserted or deleted from that section (8 inserted, 0 deleted) and plus or minus the number of rows moved into or out of that section (0 moved in, 0 moved out).'
    

ํ•ด๊ฒฐ !

// ํ…Œ์ด๋ธ”๋ทฐ๊ฐ€ ๋œจ๊ณ  ์—๋Ÿฌ๋„ ์•ˆ๋‚จ
private func resetTableView() {
		DispatchQueue.main.async { [unowned self] in
				self.tableView.reloadData()  // ์ดํ›„์— reloadSections๋กœ ๋ฐ”๊ฟˆ
		}
}
  • ์ƒˆ๋กญ๊ฒŒ ์ถ”๊ฐ€๋˜์–ด์„œ ๋ฉ”์ธ์Šค๋ ˆ๋“œ์—์„œ ๋™์ž‘ํ•˜๋Š” tryDownload()๋•Œ๋ฌธ์— ๊ธฐ์กด์˜ ์—๋Ÿฌ์ƒํ™ฉ1 ์ฝ”๋“œ๋ฅผ ์‚ฌ์šฉํ•  ์ˆ˜ ์—†๊ฒŒ๋จ
  • ๋”ฐ๋ผ์„œ ํ•œ๋ฒˆ์— ๋ชจ๋“  ํ…Œ์ด๋ธ”๋ทฐ๋ฅผ ์ „์ฒด ๋‹ค reloadํ•ด๋ฒ„๋ฆฌ๋Š” ๋ฉ”์†Œ๋“œ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๋™์ž‘์ด ๋˜๋Š”์ง€ ํ™•์ธํ•จ

storeItems.Swift


    func set(with category: Category) {
        DataSetter.tryDownload(url: category) { items in
            self.update(key: items.keys.first!, value: items.values.first!)
            if let firstKey = items.firstKey {
                let indexPaths = Array(0..<self.storeItem[firstKey]!.count).map {IndexPath(row: $0, section: firstKey.sectionNumber)}
                NotificationCenter.default.post(name: .sectionSetComplete,
                                                object: self,
                                                userInfo: [Keyword.sectionPath : firstKey])//indexPaths])
            }
        }
//        DataSetter.set(with: category) { items in
//            self.update(key: items.keys.first!, value: items.values.first!)
//            if let firstKey = items.firstKey {
//                let indexPaths = Array(0..<self.storeItem[firstKey]!.count).map {IndexPath(row: $0, section: firstKey.sectionNumber)}
//                NotificationCenter.default.post(name: .sectionSetComplete,
//                                                object: self,
//                                                userInfo: [Keyword.sectionPath : indexPaths])
//            }
//        }
    }
  • insertRows๊ฐ€ ์•„๋‹Œ reloadSection์œผ๋กœ ๋ฐ”๊พธ๋ฉด์„œ category๋งŒ ๋„˜๊ฒจ์ฃผ๋ฉด ๋จ

RootViewController

class StoreViewController: UIViewController {
    @IBOutlet weak var tableView: UITableView!

    let rowHeightForCell: CGFloat = 100
    let rowHeightForHeader: CGFloat = 60

    var storeItems = StoreItems()

    override func viewDidLoad() {
        super.viewDidLoad()
        #if DEBUG
        self.deleteCache()
        #endif
        NotificationCenter.default.addObserver(self, selector: #selector(dataReload), name: .reachabilityChanged, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(setComplete(notification:)),name: .sectionSetComplete,object: nil)
        tableView.delegate = self
        tableView.dataSource = self
        tableView.rowHeight = rowHeightForCell
        StoreItems.categories.forEach { (category) in
            self.storeItems.set(with: category)
        }
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
    }

    @objc func dataReload() {
        if NetworkManager.shared.reachable {
            StoreItems.categories.forEach { (category) in
                self.storeItems.set(with: category)
            }
        } else {
            print("RootView - dataReload. Not reachable")
        }
    }

    private func resetTableView(indexPaths: Category) {
        DispatchQueue.main.async { [weak self] in
//            self?.tableView.reloadData()
            self?.tableView.reloadSections(IndexSet(0..<(self?.storeItems.storeItem.keys.count)!), with: .automatic)
        }
//        DispatchQueue.main.sync { [weak self] in
//            self?.tableView.beginUpdates()
//            self?.tableView.insertRows(at: indexPaths, with: .automatic)
//            self?.tableView.endUpdates()
//        }
    }

    @objc func setComplete(notification: Notification) {
        guard let userInfo = notification.userInfo else { return }
        guard let section = userInfo[Keyword.sectionPath] else { return }
//        guard let sectionNumber = section as? [IndexPath] else { return }
        guard let category = section as? Category else { return }
        self.resetTableView(indexPaths: category)
    }


2018.08.07



#if DEBUG
// self.deleteCache()
#endif


    // DEBUG
    private func deleteCache() {
        let cacheURL = ImageSetter.fileManager.urls(for: .cachesDirectory, in: .userDomainMask).first!
        do {
            let fileNames = try ImageSetter.fileManager.contentsOfDirectory(atPath: cacheURL.path)
            for file in fileNames {
                let imageSavingPath = cacheURL.appendingPathComponent(file)
                if (file.hasSuffix(".jpg")) {
                    try ImageSetter.fileManager.removeItem(atPath: imageSavingPath.path)
                }
                let files = try ImageSetter.fileManager.contentsOfDirectory(atPath: cacheURL.path)
            }
        } catch {
            print("Could not clear temp folder: \(error)")
        }
    }

  • NSKeyValueOperator ์ด๊ฒŒ๋ญ์ง€โ€ฆ
  • value(forKey:)
  • NSKeyValueCoding
    • A mechanism by which you can access the properties of an object indirectly by name or keyโ€ฆโ€ฆโ€ฆโ€ฆโ€ฆ..what?
  • JKํ”ผ๋“œ๋ฐฑ: ViewController ๊ฐ€ .reachabilityChanged ์ƒํƒœ๋ฅผ ์˜ต์ €๋น™ ํ•ด์•ผ ํ•˜๋Š”๊ฑธ๊นŒ์š”? ์ƒํƒœ ๋ณ€ํ™”๋ฅผ ๊ฐ์‹œํ•  ๊ฒŒ ์•„๋‹ˆ๋ผ ๊ทธ๋ƒฅ ๋ฐ์ดํ„ฐ ๋ชจ๋ธ์ด ๋ฐ”๋€Œ์—ˆ๋Š”์ง€๋งŒ ๊ฐ์‹œํ•˜๋ฉด ๋˜๋Š”๊ฑฐ ์•„๋‹๊นŒ์š”?
    • ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ: ์„น์…˜๋ณ„ ๋ชจ๋ธ StoreItems.set()ํ˜ธ์ถœ - setํ•˜๋Š” datasetter.trydownloadํ•จ์ˆ˜๊ฐ€ ๋น„๋™๊ธฐ๋ผ์„œ noti๋ฅผ ๋„ฃ์Œ
    • ๊ฒฐ๊ตญ ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ๊ฐ€ ๋ฐ์ดํ„ฐ๋ฅผ set()ํ•˜๋ผ๊ณ  ์‹œํ‚ค๊ณ  ๋ฐ์ดํ„ฐ๊ฐ€ ์…‹์„ ์™„๋ฃŒํ–ˆ๋‹ค๊ณ  ์•Œ๋ ค์ฃผ๋Š”๊ฑฐ์ง€, ๋ฐ์ดํ„ฐ๊ฐ€ ๋„คํŠธ์›Œํฌ ์ƒํ™ฉ์—๋”ฐ๋ผ ์•Œ์•„์„œ ๋‹ค์šด๋กœ๋“œ๋˜๋Š”๊ฒŒ ์•„๋‹ˆ๊ธฐ๋•Œ๋ฌธ์— reachabilityChanged ๋…ธํ‹ฐํ”ผ์ผ€์ด์…˜ ์˜ต์ €๋ฒ„๋ฅผ ์ง€์šฐ๋ฉด ํŠธ๋ž™ํ‚น์ด์•ˆ๋จโ€ฆ
    • JK: ViewController๊ฐ€ ๋„คํŠธ์›Œํฌ ์ƒํƒœ์— ๋”ฐ๋ผ ๋ชจ๋ธ์„ ๋‹ค๋ฅด๊ฒŒ ์ ‘๊ทผํ•˜๊ธฐ ๋ณด๋‹ค๋Š” ๋„คํŠธ์›Œํฌ ์ƒํƒœ๋ฅผ ๊ด€๋ฆฌํ•˜๋Š” ๊ณ„์ธต์ด ์–ด๋””์—์„œ ๋™์ž‘ํ• ์ง€ ๊ณ ๋ฏผํ•ด๋ณด๋Š” ๊ฒŒ ์ข‹์Šต๋‹ˆ๋‹ค. ViewController๋Š” ์ƒํƒœ๋ฅผ ๋ชจ๋ฅด๊ณ , ๋ชจ๋ธ์—์„œ ๊ฐ’์ด ์˜ฌ๋•Œ๋งˆ๋‹ค ๋ทฐ์— ๋ฐ˜์˜ํ•˜๋„๋ก ๋‹จ์ˆœํ•˜๊ฒŒ ์ž‘์„ฑํ•˜๋Š” ๊ฒŒ ์ข‹์Šต๋‹ˆ๋‹ค. VC โ€“> Network Manager โ€“> ์ƒํƒœํ™•์ธํ›„ Request ๋˜๋Š” ์ €์žฅ๋œ ๋ฐ์ดํ„ฐ ์ฒ˜๋ฆฌ โ€“> ๋ชจ๋ธ ๋ณ€๊ฒฝ โ€“> ๋…ธํ‹ฐ โ€“> VC ํ™”๋ฉด ๋ณ€๊ฒฝ ํ๋ฆ„์„ ์ƒ์ƒํ•ด๋ดค์Šต๋‹ˆ๋‹ค.
    • ViewController๊ฐ€ ์–ด์จŒ๋“  Controller์—ญํ• ์„ ํ•˜๋Š”๊ฑฐ๋‹ˆ๊นŒ ์ง€๊ธˆ ํ๋ฆ„์ฒ˜๋Ÿผ ๋ทฐ์— ํ•„์š”ํ•œ ๋ชจ๋ธ(StoreItems๊ฐ์ฒด)์„ ์„ธํŒ…ํ•˜๋Š” ๋™์ž‘์„ ํ˜ธ์ถœํ•˜๋Š”๊ฒŒ ์–ด์ƒ‰ํ•˜์ง„ ์•Š์€ ๊ฒƒ ๊ฐ™์€๋ฐ, ์—ฐ๊ฒฐ์„ฑ์„ ํ™•์ธํ•˜๋Š” ๊ฐ์ฒด๊ฐ€ ์žˆ์œผ๋‹ˆ NetworkManager๊ฐ€ ์ƒํ™ฉ์—๋”ฐ๋ผ ๋ชจ๋ธ์„ ์—…๋ฐ์ดํŠธํ•˜๋Š” ์—ญํ• ์„ ํ•˜๋Š”๊ฒŒ ๋งž๋‚˜์š”?
    • viewDidLoad์—์„œ ์ฒ˜์Œ set - DataSetter์—์„œ ๋„คํŠธ์›Œํฌ ์ƒํ™ฉ์—๋”ฐ๋ผ ๋ชจ๋ธ ์„ธํŒ… - noti๋กœ ์™„๋ฃŒ๋˜๋ฉด viewํ‘œ์‹œ reloadSections
    • (์™€์ดํŒŒ์ด ์ƒํƒœ๋ผ๊ณ  ์ƒํƒœ๋ฐ”๊ฐ€ ํ‘œ์‹œ๋˜์–ด๋„ detailhash๊ฐ’์€ nil์ด๋ผ(๋งจ์ฒ˜์Œ์— reachable์ด false์˜€๊ธฐ๋•Œ๋ฌธ์—) ์ƒํ’ˆ์ƒ์„ธํŽ˜์ด์ง€ํ™”๋ฉด์ด ํ‘œ์‹œ ์•ˆ๋˜๋Š” ๋ฌธ์ œ)

    func notifyListener(_ flags: SCNetworkReachabilityFlags) { guard previousFlags != flags else { return } previousFlags = flags

       listener?(networkReachabilityStatusForFlags(flags))    }
    

2018.08.09

  • JKํ”ผ๋“œ๋ฐฑ์ •๋ฆฌ
  • RxSwiftโ€ฆ
  • KVO์ •๋ฆฌ/์งˆ๋ฌธ
  • NSKeyValueCoding ์•„๋ž˜ ๋‚ด์šฉ ํฌ์ŠคํŒ…ํ•˜๊ธฐ
      var statusBarView: UIView? {
          return value(forKey: "statusBar") as? UIView
      }
    
  • NSKeyValueCoding ๋ฉ”์ปค๋‹ˆ์ฆ˜์œผ๋กœ ์ธํ•ด ๊ฐ์ฒด์˜ ์†์„ฑ์— ์ ‘๊ทผํ•˜๋Š” ๋ฉ”์ปค๋‹ˆ์ฆ˜
  • ๊ฐ์ฒด ์†์„ฑ์ด ๋”•์…”๋„ˆ๋ฆฌ์— ์ €์žฅ๋˜์–ด์žˆ๋‹ค๊ณ  ๊ฐ€์ •ํ•˜๊ณ , key๋ฅผ ์ฃผ๋ฉด value๋ฅผ ์ฃผ๋Š” ๋ฐฉ์‹
  • (Typically, by convention, the key representing a property is the name of the property itself as it appears in code.)
  • value(forKey:) ๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ฐ์ฒด์˜ ์†์„ฑ์˜ ์ด๋ฆ„์ด๋‚˜ ํ‚ค๊ฐ’์œผ๋กœ ์ฐพ์•„์„œ ์ฐธ์กฐํ•  ์ˆ˜ ์žˆ๋Š”๋ฐ, privateํ•œ ์†์„ฑ๊นŒ์ง€ ์ ‘๊ทผ์ด ๊ฐ€๋Šฅํ•˜๋‹ค.
  • ๊ด€๋ จ๋˜์–ด Stackoverflow์˜ ๋‹ต๋ณ€์—์„œ๋Š” ์ด ๋ฐฉ๋ฒ•์ด privateํ•œ ์†์„ฑ๊นŒ์ง€ ์ ‘๊ทผํ•ด์„œ ์“ฐ๋Š”๊ฑฐ๊ธฐ๋•Œ๋ฌธ์— ์•ˆ์ข‹๋‹ค๊ณ  ํ–ˆ๋Š”๋ฐ, ๋งค์ปค๋‹ˆ์ฆ˜์— ์˜ํ•ด์„œ privateํ•œ ์†์„ฑ์— ์ ‘๊ทผํ•ด์„œ ๋ฐ”๊ฟ”๋ฒ„๋ฆฌ๋Š”๊ฑฐ๊ธฐ๋•Œ๋ฌธ์— ๋ณ„๋กœ ๊ถŒ์žฅ๋˜๋Š” ๋ฐฉ๋ฒ•์€ ์•„๋‹Œ๋“ฏ.
  • ์˜ˆ์‹œ๋กœ statusBar๋Š” ๋ทฐ์ปจํŠธ๋กค๋Ÿฌ์—์„œ ์ ‘๊ทผํ•ด์„œ ๋ฐ”๊พธ๋Š”๊ฒŒ ๊ถŒ์žฅ๋˜๊ณ  ์žˆ๊ณ  ์˜ˆ์ „์—๋Š” statusBar์— ๋‹ค๋ฅธ๊ณณ์—์„œ ์ ‘๊ทผํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์žˆ์œผ๋ฉด ์• ํ”Œ์ด rejectํ•˜๊ธฐ๋„ ํ–ˆ๋‹ค๊ณ  ํ•œ๋‹ค.
  • ๋˜ ์ž๋ฃŒ๋ฅผ ์ฐพ์•„๋ณผ๋•Œ info.plist์˜ key-value๋ชฉ๋ก์ฒ˜๋Ÿผ ์ฐธ๊ณ  ์ž๋ฃŒ๊ฐ€ ์žˆ์„ ์ค„ ์•Œ์•˜๋Š”๋ฐ ์ฐพ๊ณ ์ฐพ์•„๋„ ์—†๋Š” ์ด์œ ๊ฐ€ privateํ•œ ์†์„ฑ์˜ ์ด๋ฆ„๋“ค์„๋‹ค ์ด key๋กœ์“ฐ๋ผ๊ณ  ์•Œ๋ ค์ค„ ์ˆ˜ ์—†์œผ๋‹ˆ๊นŒ(์“ฐ๋ผ๊ณ  ๊ณต๊ฐœํ•˜๋Š”๊ฑฐ ์ž์ฒด๊ฐ€ ์ด์ƒํ•จ) ๊ทธ๋Ÿฐ๋“ฏ.
  • ์ปดํŒŒ์ผํƒ€์ž„์ด ์•„๋‹Œ ๋Ÿฐํƒ€์ž„์‹œ์— ์ ‘๊ทผํ•˜๋Š” ๊ฐ์ฒด๋ฅผ ์ง€์ •ํ•œ๋‹ค.
    • value(forKey:)์— ๋“ค์–ด๊ฐ€๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ ๋Ÿฐํƒ€์ž„์‹œ์— ๋ณ€๊ฒฝ๋  ์ˆ˜๋„ ์žˆ๋‹ค๋Š” ๋œป.
    • (๋ญ..์–ต์ง€์Šค๋Ÿฌ์šด ์ƒํ™ฉ์ผ ์ˆ˜ ์žˆ์ง€๋งŒ A button์„ ๋ˆ„๋ฅด๋ฉด โ€œstatusBarโ€๊ฐ€ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋„˜์–ด๊ฐ€๊ฑฐ๋‚˜, B button์„ ๋ˆ„๋ฅด๋ฉด โ€œnavigationBarโ€๊ฐ€ ๋„˜์–ด๊ฐ„๋‹ค๊ฑฐ๋‚˜โ€ฆ)
  • ๊ฐ์ฒด๋‚˜ ์†์„ฑ์„ ๋‚ด๊ฐ€ ์ •ํ•œ key๋กœ ์ ‘๊ทผํ•˜๋„๋ก key๋ฅผ ์„ธํŒ…ํ•  ์ˆ˜ ์žˆ๋‹ค. setValue(\_:forKey:)

2018.08.10

  • ๋งˆํŠธ์•ฑ ๊ฐœ๋ฐœํ•ญ๋ชฉ ์ •ํ•˜๊ธฐ
  • ์ฃผ๋ง ๊ณ„ํš์„ธ์šฐ๊ธฐ: ์ž์†Œ์„œ, ๋ธ”๋กœ๊ทธ์™€ ๊นƒํ—™์ •๋ฆฌ, ๊ธฐ์ดˆ๋ฉด์ ‘์งˆ๋ฌธ์ค€๋น„๋“ค

2018.08.11

2018.08.12

  • BranchTableViewCell์˜ setCell() starbutton์„ ์„ธํŒ…ํ•˜๋Š”๋ฐ ์ฒ˜์Œ ํ•œ๋ฒˆ ๋–ด์„๋•Œ ์„ธํŒ…์ด ๋˜์ง„์•Š๊ณ  ์…€์ด ํ™”๋ฉด์—์„œ ๋ฒ—์–ด๋‚ฌ๋‹ค๊ฐ€ ๋‹ค์‹œ ๋‚˜ํƒ€๋‚ ๋•Œ๋งŒ ์„ธํŒ…์ด๋จ. ์‹ฌ์ง€์–ด ์—„์ฒญ ๋Š๋ฆฌ๊ณ  ๋š๋š๋Š๊น€โ€ฆ. ๋ฒ„ํŠผ ์ด๋ฏธ์ง€ ์„ธํŒ…ํ•˜๋Š”๊ฑด ๊ฐ„๋‹จํ•œ ์ž‘์—…์ด๋ผ ์˜ค๋ž˜ ๊ฑธ๋ฆด ๊ฒƒ ๊ฐ™์ง€ ์•Š์•„์„œ ๋ญ๊ฐ€ ๋ฌธ์ œ์ง€ ํ•˜๊ณ  ๊ณ ๋ฏผํ•˜๋‹ค๊ฐ€ GCD๋กœ main.async๋กœ ์ž‘์—…ํ•˜๊ฒŒ ๋Œ๋ฆฌ๋‹ˆ๊นŒ ๋นจ๋ผ์ง..!