Skip to content

Latest commit

ย 

History

History
650 lines (461 loc) ยท 15.2 KB

README.md

File metadata and controls

650 lines (461 loc) ยท 15.2 KB

์˜ค์šด์™„

๋ชฉ์ฐจ


๋ฆฌํŽ™ํ† ๋ง (2024.12 ~ ์ง„ํ–‰ ์ค‘)

2.0.0 (2024.12.21 ~ 2025.1.11)

Realm -> Swift Data ๋ณ€๊ฒฝ

๐Ÿ‹๐Ÿป ํ”„๋กœ์ ํŠธ ์†Œ๊ฐœ

ย ย ย ย ย ย ย ย 

 ์‚ฌ์ง„, ์ธ๋ฐ”๋”” ์ •๋ณด, ์šด๋™ ๋ฃจํ‹ด์œผ๋กœ ๋ชธ์˜ ๋ณ€ํ™”๋ฅผ ์‰ฝ๊ฒŒ ๊ด€์ฐฐํ•  ์ˆ˜ ์žˆ๋Š” ํ—ฌ์Šค ๊ธฐ๋ก ์•ฑ

๐Ÿ”— ์•ฑ ๋‹ค์šด๋กœ๋“œ ๋งํฌ

ํ”„๋กœ์ ํŠธ ๊ธฐ๊ฐ„

2023.03 ~ 2023.08 (์ง„ํ–‰์ค‘)

๐Ÿ“ฑ App Version

๋‚ ์งœ ๋ฒ„์ „
23.07.28 v1.0.0

๐Ÿ“ฑ ์ฃผ์š” ํ™”๋ฉด ๋ฐ ๊ธฐ๋Šฅ

๐Ÿ”– ์˜จ๋ณด๋”ฉ ํ”Œ๋กœ์šฐ - ์•ฑ์— ๋Œ€ํ•œ ์ „๋ฐ˜์ ์ธ ์„ค๋ช… ํ›„, ์˜จ๋ณด๋”ฉ์„ ๋„˜์–ด๊ฐ€๋ฉด ๋‹ค์‹œ ๋‚˜ํƒ€๋‚˜์ง€ ์•Š์•„์š”.

๐Ÿ“ˆ ๋ชธ๋ฌด๊ฒŒ, ์ฒด์ง€๋ฐฉ๋Ÿ‰, ๊ณจ๊ฒฉ๊ทผ๋Ÿ‰ ์ž…๋ ฅ ๋ฐ ๋ถ„์„ ํ”Œ๋กœ์šฐ - ๋‚ ๋งˆ๋‹ค ์ž…๋ ฅํ•œ ์‹ ์ฒด ์ •๋ณด๋ฅผ ์ฐจํŠธ๋กœ ํ•œ ๋ˆˆ์— ๋น„๊ตํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿ“ธ ์˜ค์šด์™„ ์‚ฌ์ง„ ์ดฌ์˜ ๋ฐ ์ €์žฅ ํ”Œ๋กœ์šฐ - ๋‚ ๋งˆ๋‹ค ์‚ฌ์ง„์„ ์ฐ๊ณ  ์ €์žฅํ•ด ๋ชธ์˜ ๋ณ€ํ™”๋ฅผ ํ•œ ๋ˆˆ์— ๋น„๊ตํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐ŸŽž๏ธ ๊ฐค๋Ÿฌ๋ฆฌ์—์„œ ์‚ฌ์ง„ ๊ฐ€์ ธ์˜ค๊ธฐ ๋ฐ ์ €์žฅ ํ”Œ๋กœ์šฐ - ๊ฐค๋Ÿฌ๋ฆฌ(์ „์ฒด ๊ถŒํ•œ, ์„ ํƒ ๊ถŒํ•œ)์—์„œ ๊ฐ€์ ธ์™€ ๋ชธ์˜ ๋ณ€ํ™”๋ฅผ ํ•œ ๋ˆˆ์— ๋น„๊ตํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿ’ช ์šด๋™ ๋ฃจํ‹ด ๋งŒ๋“ค๊ธฐ ํ”Œ๋กœ์šฐ - ๋‚˜๋งŒ์˜ ๋ฃจํ‹ด์„ ๋งŒ๋“ค๊ณ  ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿ‹๏ธ ์šด๋™ํ•˜๊ธฐ ํ”Œ๋กœ์šฐ - ๋‚ ๋งˆ๋‹ค ๋ฃจํ‹ด์„ ๊ฐ€์ ธ์™€ ์šด๋™์„ ํ•˜๊ฑฐ๋‚˜ ์ฆ‰์„์—์„œ ๋ฃจํ‹ด์„ ๋งŒ๋“ค์–ด ์šด๋™์„ ํ•˜๊ณ  ํ™•์ธํ•  ์ˆ˜ ์žˆ์–ด์š”.

๐Ÿ—บ ์•„ํ‚คํ…์ณ

MVVM(์ž‘์„ฑ์ค‘)

๐Ÿ—‚ ํŒŒ์ผ ๋””๋ ‰ํ† ๋ฆฌ ๊ตฌ์กฐ

โ”€โ”€โ”€ WorkoutDone
โ”‚   โ”œโ”€โ”€ ๐Ÿ“ Resources
โ”‚   โ”‚   โ”œโ”€โ”€ ๐Ÿ“ Fonts
โ”‚   โ”‚   โ”œโ”€โ”€ Assets.xcassets
โ”‚   โ”‚   โ”œโ”€โ”€ LaunchScreen
โ”‚   โ”‚   โ”œโ”€โ”€ AppDelegate.swift
โ”‚   โ”‚   โ”œโ”€โ”€ SceneDelegate.swift
โ”‚   โ”‚   โ””โ”€โ”€ Info.plist
โ”‚   โ”‚
โ”‚   โ”œโ”€โ”€ ๐Ÿ“ Sources
โ”‚   โ”‚   โ”œโ”€โ”€ ๐Ÿ“ Presenter
โ”‚   โ”‚   โ”‚   โ””โ”€โ”€ ๐Ÿ“ Scene
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ ๐Ÿ“ ViewController
โ”‚   โ”‚   โ”‚       โ”œโ”€โ”€ ๐Ÿ“ ViewModel
โ”‚   โ”‚   โ”‚       โ””โ”€โ”€ ๐Ÿ“ Cells
โ”‚   โ”‚   โ”‚  
โ”‚   โ”‚   โ”œโ”€โ”€ ๐Ÿ“ Model
โ”‚   โ”‚   โ”œโ”€โ”€ ๐Ÿ“ Classes
โ”‚   โ”‚   โ””โ”€โ”€ ๐Ÿ“ Extensions
โ”‚   โ”‚
โ”‚   โ””โ”€โ”€ ๐Ÿ“ Utils
โ””โ”€โ”€ ๐Ÿ“ WorkoutDoneTests

๐Ÿ“ ์ฝ”๋“œ ์ปจ๋ฒค์…˜

๐ŸŽ ๋„ค์ด๋ฐ

๐Ÿ’งํด๋ž˜์Šค, ๊ตฌ์กฐ์ฒด

  • UpperCamelCase ์‚ฌ์šฉ
// - example

struct MyTicketResponseDTO {
}

class UserInfo {
}

๐Ÿ’งํ•จ์ˆ˜

  • lowerCamelCase ์‚ฌ์šฉํ•˜๊ณ  ๋™์‚ฌ๋กœ ์‹œ์ž‘
// - example

private func setDataBind() {
}

๐Ÿ’ง๋ทฐ ์ „ํ™˜

  • pop, push, present, dismiss
  • ๋™์‚ฌ + To + ๋ชฉ์ ์ง€ ๋ทฐ (๋‹ค์Œ์— ๋ณด์ผ ๋ทฐ)
  • dismiss๋Š” dismiss + ํ˜„์žฌ ๋ทฐ
// - example pop, push, present

popToFirstViewController()
pushToFirstViewController()
presentToFirstViewController()

dismissFirstViewController()

๐Ÿ’งregister

  • register + ๋ชฉ์ ์–ด
// - example

registerXib()
registerCell()

๐Ÿ’ง์„œ๋ฒ„ ํ†ต์‹ 

  • ์„œ๋น„์Šคํ•จ์ˆ˜๋ช… + WithAPI
// - example

fetchListWithAPI()

requestListWithAPI()

fetch๋Š” ๋ฌด์กฐ๊ฑด ์„ฑ๊ณต

request๋Š” ์‹คํŒจํ•  ์ˆ˜๋„ ์žˆ๋Š” ์š”์ฒญ

๐Ÿ’ง์• ๋‹ˆ๋ฉ”์ด์…˜

  • ๋™์‚ฌ์›ํ˜• + ๋ชฉ์ ์–ด + WithAnimation
showButtonsWithAnimation()

๐Ÿ’ง๋ธ๋ฆฌ๊ฒŒ์ดํŠธ

delegate ๋ฉ”์„œ๋“œ๋Š” ํ”„๋กœํ† ์ฝœ๋ช…์œผ๋กœ ๋„ค์ž„์ŠคํŽ˜์ด์Šค๋ฅผ ๊ตฌ๋ถ„

์ข‹์€ ์˜ˆ:

protocol UserCellDelegate {
  func userCellDidSetProfileImage(_ cell: UserCell)
  func userCell(_ cell: UserCell, didTapFollowButtonWith user: User)
}

protocol UITableViewDelegate {
	func tableview( ....) 
	func tableview...
}

protocol JunhoViewDelegate {
	func junhoViewTouched()
	func junhoViewScrolled()
}

Delegate ์•ž์ชฝ์— ์žˆ๋Š” ๋‹จ์–ด๋ฅผ ์ค‘์‹ฌ์œผ๋กœ ๋ฉ”์„œ๋“œ ๋„ค์ด๋ฐํ•˜๊ธฐ

๋‚˜์œ ์˜ˆ:

protocol UserCellDelegate {
	// userCellDidSetProfileImage() ๊ฐ€ ์˜ณ์Œ
  func didSetProfileImage()
  func followPressed(user: User)

  // `UserCell`์ด๋ผ๋Š” ํด๋ž˜์Šค๊ฐ€ ์กด์žฌํ•  ๊ฒฝ์šฐ ์ปดํŒŒ์ผ ์—๋Ÿฌ ๋ฐœ์ƒ  (userCell ๋กœ ํ•ด์ฃผ์ž)
  func UserCell(_ cell: UserCell, didTapFollowButtonWith user: User)
}

ํ•จ์ˆ˜ ์ด๋ฆ„ ์•ž์—๋Š” ๋˜๋„๋ก์ด๋ฉด get ์„ ๋ถ™์ด์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

๐Ÿ’ง๋ณ€์ˆ˜, ์ƒ์ˆ˜

  • lowerCamelCase ์‚ฌ์šฉ
let userName: String

๐Ÿ’ง์—ด๊ฑฐํ˜•

  • ๊ฐ case ์—๋Š” lowerCamelCase ์‚ฌ์šฉ
enum UserType {
	case viewDeveloper
	case serverDeveloper
}

๐Ÿ’ง์•ฝ์–ด

์•ฝ์–ด๋กœ ์‹œ์ž‘ํ•˜๋Š” ๊ฒฝ์šฐ ์†Œ๋ฌธ์ž๋กœ ํ‘œ๊ธฐ, ๊ทธ ์™ธ์—๋Š” ํ•ญ์ƒ ๋Œ€๋ฌธ์ž

// ์ข‹์€ ์˜ˆ:
let userID: Int?
let html: String?
let websiteURL: URL?
let urlString: String?
// ๋‚˜์œ ์˜ˆ:
let userId: Int?
let HTML: String?
let websiteUrl: NSURL?
let URLString: String?

๐Ÿ’ง๊ธฐํƒ€ ๋„ค์ด๋ฐ

setUI() : @IBOutlet ์†์„ฑ ์„ค์ •
setLayout() : ๋ ˆ์ด์•„์›ƒ ๊ด€๋ จ ์ฝ”๋“œ
setDataBind() : ๋ฐฐ์—ด ํ•ญ๋ชฉ ์„ธํŒ…. ์ปฌ๋ ‰์…˜๋ทฐ ์—์„œ ๋ฆฌ์ŠคํŠธ ์ดˆ๊ธฐ ์„ธํŒ…ํ• ๋•Œ
setAddTarget() : addtarget ๋ชจ์Œ
setDelegate() : delegate, datasource ๋ชจ์Œ
setCollectionView() : ์ปฌ๋ ‰์…˜๋ทฐ ๊ด€๋ จ ์„ธํŒ…
setTableView() : ํ…Œ์ด๋ธ”๋ทฐ ๊ด€๋ จ ์„ธํŒ…
initCell() : ์…€ ๋ฐ์ดํ„ฐ ์ดˆ๊ธฐํ™”
registerXib() : ์…€ xib ๋“ฑ๋ก.
setNotification() : NotificationCenter addObserver ๋ชจ์Œ

ํ—ท๊ฐˆ๋ฆฐ๋‹ค? set์„ ์“ฐ์„ธ์š” ^^
๐ŸŽ ์ฝ”๋“œ ๋ ˆ์ด์•„์›ƒ

๐Ÿ’ง๋“ค์—ฌ์“ฐ๊ธฐ ๋ฐ ๋„์–ด์“ฐ๊ธฐ

  • ๋“ค์—ฌ์“ฐ๊ธฐ์—๋Š” ํƒญ(tab) ๋Œ€์‹  4๊ฐœ์˜ space๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

  • ์ฝœ๋ก (:)์„ ์“ธ ๋•Œ์—๋Š” ์ฝœ๋ก ์˜ ์˜ค๋ฅธ์ชฝ์—๋งŒ ๊ณต๋ฐฑ์„ ๋‘ก๋‹ˆ๋‹ค.

    let names: [String: String]?

    let name: String

  • ์—ฐ์‚ฐ์ž ์˜ค๋ฒ„๋กœ๋”ฉ ํ•จ์ˆ˜ ์ •์˜์—์„œ๋Š” ์—ฐ์‚ฐ์ž์™€ ๊ด„ํ˜ธ ์‚ฌ์ด์— ํ•œ ์นธ ๋„์–ด์”๋‹ˆ๋‹ค.

    func ** (lhs: Int, rhs: Int)

๐Ÿ’ง์ค„๋ฐ”๊ฟˆ

  • ํ•จ์ˆ˜๋ฅผ ํ˜ธ์ถœํ•˜๋Š” ์ฝ”๋“œ๊ฐ€ ์ตœ๋Œ€ ๊ธธ์ด๋ฅผ ์ดˆ๊ณผํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์„ ๊ธฐ์ค€์œผ๋กœ ์ค„๋ฐ”๊ฟˆํ•ฉ๋‹ˆ๋‹ค. ํŒŒ๋ผ๋ฏธํ„ฐ๊ฐ€ 3๊ฐœ ์ด์ƒ์ด๋ฉด ์ค„๋ฐ”๊ฟˆํ•˜๋„๋ก!!

    ๋‹จ, ํŒŒ๋ผ๋ฏธํ„ฐ์— ํด๋กœ์ €๊ฐ€ 2๊ฐœ ์ด์ƒ ์กด์žฌํ•˜๋Š” ๊ฒฝ์šฐ์—๋Š” ๋ฌด์กฐ๊ฑด ๋‚ด๋ ค์“ฐ๊ธฐํ•ฉ๋‹ˆ๋‹ค.

    UIView.animate(
      withDuration: 0.25,
      animations: {
        // doSomething()
      },
      completion: { finished in
        // doSomething()
      }
    )
  • if let ๊ตฌ๋ฌธ์ด ๊ธธ ๊ฒฝ์šฐ์—๋Š” ์ค„๋ฐ”๊ฟˆํ•˜๊ณ  ํ•œ ์นธ ๋“ค์—ฌ์”๋‹ˆ๋‹ค.

    if let user = self.veryLongFunctionNameWhichReturnsOptionalUser(),
      let name = user.veryLongFunctionNameWhichReturnsOptionalName(),
      user.gender == .female {
      // ...
    }
  • guard let ๊ตฌ๋ฌธ์ด ๊ธธ ๊ฒฝ์šฐ์—๋Š” ์ค„๋ฐ”๊ฟˆํ•˜๊ณ  ํ•œ ์นธ ๋“ค์—ฌ์”๋‹ˆ๋‹ค. else๋Š” ๋งˆ์ง€๋ง‰ ์ค„์— ๋ถ™์—ฌ์“ฐ๊ธฐ

    guard let user = self.veryLongFunctionNameWhichReturnsOptionalUser(),
      let name = user.veryLongFunctionNameWhichReturnsOptionalName(),
      user.gender == .female else { return }
    
    guard let self = self 
    else { return } (X)
    
    guard let self = self else { return } (O)
  • else ๊ตฌ๋ฌธ์ด ๊ธธ ์‹œ ์ค„๋ฐ”๊ฟˆ

๐Ÿ’ง๋นˆ ์ค„

  • ํด๋ž˜์Šค ์„ ์–ธ ๋‹ค์Œ์— , extension ๋‹ค์Œ์— ํ•œ ์ค„ ๋„์–ด์ฃผ๊ธฐ

  • ๋นˆ ์ค„์—๋Š” ๊ณต๋ฐฑ์ด ํฌํ•จ๋˜์ง€ ์•Š๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ( ๋„์–ด์“ฐ๊ธฐ ์“ธ๋ฐ์—†์ด ๋„ฃ์ง€ ๋ง๊ธฐ )

  • ๋ชจ๋“  ํŒŒ์ผ์€ ๋นˆ ์ค„๋กœ ๋๋‚˜๋„๋ก ํ•ฉ๋‹ˆ๋‹ค. ( ๋์— ์—”ํ„ฐ ํ•˜๋‚˜ ๋„ฃ๊ธฐ)

  • MARK ๊ตฌ๋ฌธ ์œ„์™€ ์•„๋ž˜์—๋Š” ๊ณต๋ฐฑ์ด ํ•„์š”ํ•ฉ๋‹ˆ๋‹ค.

    // MARK: Layout
    
    override func layoutSubviews() {
      // doSomething()
    }
    
    // MARK: Actions
    
    override func menuButtonDidTap() {
      // doSomething()
    }

๐Ÿ’ง์ž„ํฌํŠธ

๋ชจ๋“ˆ ์ž„ํฌํŠธ๋Š” ์•ŒํŒŒ๋ฒณ ์ˆœ์œผ๋กœ ์ •๋ ฌํ•ฉ๋‹ˆ๋‹ค. ๋‚ด์žฅ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ๋จผ์ € ์ž„ํฌํŠธํ•˜๊ณ , ๋นˆ ์ค„๋กœ ๊ตฌ๋ถ„ํ•˜์—ฌ ์„œ๋“œํŒŒํ‹ฐ ํ”„๋ ˆ์ž„์›Œํฌ๋ฅผ ์ž„ํฌํŠธํ•ฉ๋‹ˆ๋‹ค.

import UIKit

import Moya
import SnapKit
import SwiftyColor
import Then
import UIKit

import SwiftyColor
import SwiftyImage
import JunhoKit
import Then
import URLNavigator
๐ŸŽ ํด๋กœ์ €
  • ํŒŒ๋ผ๋ฏธํ„ฐ์™€ ๋ฆฌํ„ด ํƒ€์ž…์ด ์—†๋Š” Closure ์ •์˜์‹œ์—๋Š” () -> Void๋ฅผ ์‚ฌ์šฉํ•ฉ๋‹ˆ๋‹ค.

    ์ข‹์€ ์˜ˆ:

    let completionBlock: (() -> Void)?
    

    ๋‚˜์œ ์˜ˆ:

    let completionBlock: (() -> ())? let completionBlock: ((Void) -> (Void))?

  • Closure ์ •์˜์‹œ ํŒŒ๋ผ๋ฏธํ„ฐ์—๋Š” ๊ด„ํ˜ธ๋ฅผ ์‚ฌ์šฉํ•˜์ง€ ์•Š์Šต๋‹ˆ๋‹ค.

    ์ข‹์€ ์˜ˆ:

    { operation, responseObject in
      // doSomething()
    }

    ๋‚˜์œ ์˜ˆ:

    { (operation, responseObject) in
      // doSomething()
    }
  • Closure ์ •์˜์‹œ ๊ฐ€๋Šฅํ•œ ๊ฒฝ์šฐ ํƒ€์ž… ์ •์˜๋ฅผ ์ƒ๋žตํ•ฉ๋‹ˆ๋‹ค.

    ์ข‹์€ ์˜ˆ:

    ...,
    completion: { finished in
      // doSomething()
    }

    ๋‚˜์œ ์˜ˆ:

    ...,
    completion: { (finished: Bool) -> Void in
      // doSomething()
    }
    
    completion: { data -> Void in
      // doSomething()
    } (X)
  • Closure ํ˜ธ์ถœ์‹œ ๋˜๋‹ค๋ฅธ ์œ ์ผํ•œ Closure๋ฅผ ๋งˆ์ง€๋ง‰ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›๋Š” ๊ฒฝ์šฐ, ํŒŒ๋ผ๋ฏธํ„ฐ ์ด๋ฆ„์„ ์ƒ๋žตํ•ฉ๋‹ˆ๋‹ค.

    ์ข‹์€ ์˜ˆ:

    UIView.animate(withDuration: 0.5) {
      // doSomething()
    }

    ๋‚˜์œ ์˜ˆ:

    UIView.animate(withDuration: 0.5, animations: { () -> Void in
      // doSomething()
    })
๐ŸŽ ์ฃผ์„

์ฝ”๋“œ๋Š” ๊ฐ€๋Šฅํ•˜๋ฉด ์ž์ฒด์ ์œผ๋กœ ๋ฌธ์„œ๊ฐ€ ๋˜์–ด์•ผ ํ•˜๋ฏ€๋กœ, ์ฝ”๋“œ์™€ ํ•จ๊ป˜ ์žˆ๋Š” ์ธ๋ผ์ธ(inline) ์ฃผ์„์€ ํ”ผํ•œ๋‹ค.

๐Ÿ’งMARK ์ฃผ์„

class ViewController: UIViewController {
    // MARK: - Property
    // MARK: - UI Property
    // MARK: - Life Cycle
    // MARK: - Setting
    // MARK: - Action Helper
    // MARK: - @objc Methods
    // MARK: - Custom Method
}

// MARK: - Extensions

๐Ÿ’งํ€ตํ—ฌํ”„ ์ฃผ์„

์ปค์Šคํ…€ ๋ฉ”์„œ๋“œ, ํ”„๋กœํ† ์ฝœ, ํด๋ž˜์Šค์˜ ๊ฒฝ์šฐ์— ํ€ตํ—ฌํ”„ ์ฃผ์„ ๋‹ฌ๊ธฐ

/// (์„œ๋จธ๋ฆฌ ๋ถ€๋ถ„)
/// (๋””์Šคํฌ๋ฆฝ์…˜ ๋ถ€๋ถ„)
class MyClass {
    let myProperty: Int

    init(myProperty: Int) {
        self.myProperty = myProperty
    }
}

/**summary
(์„œ๋จธ๋ฆฌ ๋ถ€๋ถ„)
> (๋””์Šคํฌ๋ฆฝ์…˜ ๋ถ€๋ถ„)

- parameters:
    - property: ํ”„๋กœํผํ‹ฐ
- throws: ์˜ค๋ฅ˜๊ฐ€ ๋ฐœ์ƒํ•˜๋ฉด customError์˜ ํ•œ ์ผ€์ด์Šค๋ฅผ throw
- returns: "\\(name)๋Š” ~" String
*/
func printProperty(property: Int) {
        print(property)
    }
  • ์ฐธ๊ณ  :
๐ŸŽ ํ”„๋กœ๊ทธ๋ž˜๋ฐ ๊ถŒ์žฅ์‚ฌํ•ญ

๐Ÿ’งType Annotation ์‚ฌ์šฉ

์ข‹์€ ์˜ˆ:

let name: String = "์ฒ ์ˆ˜"
let height: Float = "10.0"

๋‚˜์œ ์˜ˆ:

let name = "์ฒ ์ˆ˜"
let height = "10.0"

๐Ÿ’งUICollectionViewDelegate, UICollectionViewDatsource ๋“ฑ ์‹œ์Šคํ…œ ํ”„๋กœํ† ์ฝœ

ํ”„๋กœํ† ์ฝœ์„ ์ ์šฉํ•  ๋•Œ์—๋Š” extension์„ ๋งŒ๋“ค์–ด์„œ ๊ด€๋ จ๋œ ๋ฉ”์„œ๋“œ๋ฅผ ๋ชจ์•„๋‘ก๋‹ˆ๋‹ค.

์ข‹์€ ์˜ˆ:

final class MyViewController: UIViewController {
  // ...
}

// MARK: - UITableViewDataSource

extension MyViewController: UITableViewDataSource {
  // ...
}

// MARK: - UITableViewDelegate

extension MyViewController: UITableViewDelegate {
  // ...
}

๋‚˜์œ ์˜ˆ:

final class MyViewController: UIViewController, UITableViewDataSource, UITableViewDelegate {
  // ...
}

// ํ”„๋กœํ† ์ฝœ ์—ฌ๋Ÿฌ๊ฐœ๋ฅผ ํ•œ๊ณณ์— ๋ชฐ์•„์„œ ๋•Œ๋ ค๋„ฃ์ง€ ๋ง์ž!
๐ŸŽ ๊ธฐํƒ€๊ทœ์น™
  • self ๋Š” ์ตœ๋Œ€ํ•œ ์‚ฌ์šฉ์„ ์ง€์–‘ โ†’ **์•Œ์ž˜๋”ฑ๊น”์„ผ selfโ€ฆ**

  • viewDidLoad() ์—์„œ๋Š” ํ•จ์ˆ˜ํ˜ธ์ถœ๋งŒ

  • delegate ์ง€์ •, UI๊ด€๋ จ ์„ค์ • ๋“ฑ๋“ฑ ๋ชจ๋‘ ํ•จ์ˆ˜์™€ ์—ญํ• ์— ๋”ฐ๋ผ์„œ extension ์œผ๋กœ ๋นผ๊ธฐ

  • ํ•„์š”์—†๋Š” ์ฃผ์„ ๋ฐ Mark ๊ตฌ๋ฌธ๋“ค ์ œ๊ฑฐ

  • deinit{} ๋ชจ๋“  ๋ทฐ์ปจ์—์„œ ํ™œ์„ฑํ™”

  • guard let ์œผ๋กœ unwrapping ํ•  ์‹œ, nil ๊ฐ€๋Šฅ์„ฑ์ด ๋†’์€ ๊ฒฝ์šฐ์—๋Š” else{} ์•ˆ์— print() ํ•ด์„œ ๋””๋ฒ„๊น…ํ•˜๊ธฐ ์‰ฝ๊ฒŒ ๋งŒ๋“ค๊ธฐ

  • return ์‚ฌ์šฉ์‹œ ๋‘ ์ค„ ์ด์ƒ ์ฝ”๋“œ๊ฐ€ ์žˆ์„ ์‹œ, ํ•œ ์ค„ ๋„๊ณ  return ์‚ฌ์šฉ

    func fetchFalse() -> Bool {
    		return false
    } (O)
    
    func isDataValid(data: Data?) -> Bool {
    		guard let data else { return false }
    		
    		return true
    } (O)
    
    func isDataValid(data: Data?) -> Bool {
    		guard let data else {
    				return false 
    		}
    		return true
    } (X)
  • ๊ฐ•์ œ ์–ธ๋ž˜ํ•‘ ๊ธˆ์ง€ (!)


๐Ÿ“š ๊ฐ€์šฉ ๋ผ์ด๋ธŒ๋Ÿฌ๋ฆฌ

RxSwift
- https://github.com/ReactiveX/RxSwift

Realm
- https://github.com/realm/realm-swift

SnapKit
- https://github.com/SnapKit/SnapKit

Then
- https://github.com/devxoul/Then

DeviceKit
- https://github.com/devicekit/DeviceKit

๐Ÿง‘๐Ÿปโ€๐Ÿ’ป ์ฐธ์—ฌ์ž

๋ฅ˜์ฐฝํœ˜
(@ryuchanghwi)
๋ด‰ํ˜œ๋ฏธ
(@hyemi)