๋ฐ๋ณต๋๋ ๋ฐ์ดํธ ์ ์ฐ์ธ๊ณผ์ ์ค๋ ๊ณผ ์ง๋ฆฟํจ์ ๋์ฐพ์์ค ์ฐ๋ฆฌ ๋๋ง์ ๋ถ๊ฝ, SPARKLE
๋ฐ์ต๋ฒ | ๊น์ฌ๋ | ๋ฅ์ฐฝํ | ํ์ ์ |
---|---|---|---|
์์
์ข
๋ฅ_์ด์๋๋ฒ_(๋ด์ด๋ฆ)
feat_{issuenumber}_park
refactor_{issuenumber}_ryu
fix_{issuenumber}_hong
๐ค `feat`
UI์์ ์ด๋ ๊ธฐ๋ฅ์์ ์ ํฌํจํ ์ ๊ท ๊ตฌํ ๊ด๋ จ๋ ์์ ์์ ๋ธ๋์น ๋ถ๊ธฐ
๐ค `refactor`
๊ธฐ๋ฅ์ ๋ณ๊ฒฝ ์์ด ์ฑ์ ๊ตฌ์กฐ ๊ฐ์ ์ด๋, ์ฝ๋ ๊ฐ์ ์์ ์์ ๋ธ๋์น ๋ถ๊ธฐ
๐ค `fix`
bug์์ ๊ณผ ๊ด๋ จ๋ ์์ ์งํ์ ๋ธ๋์น ๋ถ๊ธฐ
๐จ[FIX] : ๋ฒ๊ทธ, ์ค๋ฅ ํด๊ฒฐ
โ[ADD] : Feat ์ด์ธ์ ๋ถ์์ ์ธ ์ฝ๋ ์ถ๊ฐ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ๊ฐ, ์๋ก์ด ํ์ผ ์์ฑ ์
โจ[FEAT] : ์๋ก์ด ๊ธฐ๋ฅ ๊ตฌํ
โ
[CHORE] : ์ฝ๋ ์์ , ๋ด๋ถ ํ์ผ ์์
โฐ๏ธ[DEL] : ์ธ๋ชจ์๋ ํ์ผ,์ฝ๋ ์ญ์
โป๏ธ[REFACTOR] : ์ ๋ฉด ์์ ์ด ์์ ๋ ์ฌ์ฉํฉ๋๋ค
๐[MERGE]: ๋ค๋ฅธ๋ธ๋ ์น๋ฅผ merge ํ ๋ ์ฌ์ฉํฉ๋๋ค.
๐ ๋ค์ด๋ฐ
- 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 + ๋ชฉ์ ์ด
// - 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) ์ฃผ์์ ํผํ๋ค.
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)
}
- ์ฐธ๊ณ :
๐ ํ๋ก๊ทธ๋๋ฐ ๊ถ์ฅ์ฌํญ
์ข์ ์:
let name: String = "์ฒ ์"
let height: Float = "10.0"
๋์ ์:
let name = "์ฒ ์"
let height = "10.0"
ํ๋กํ ์ฝ์ ์ ์ฉํ ๋์๋ 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)
์ฝ์ด ์ง์
โ TVC๋ณด๋ค๋ TableViewCell
- set_ ํํ๋ก ์์ฑ
โ setUI, setData
setLayout()
,setStyle()
,setDelegate()
class ViewController: UIViewController { // MARK: - Property // MARK: - UI Property // MARK: - Life Cycle // MARK: - Setting // MARK: - Action Helper // MARK: - Custom Method } // MARK: - UITableView Delegate
- ๋งํฌ ์ฃผ์ ๋ฏธ์ฌ์ฉ์ ์ญ์
ํ๋กํผํฐ ์์ฑ์ ๋ ์ด์์ ์์๋๋ก์ง๋ง, collectionView, tableView๋ ์ต์๋จ์ ์ ์์๋ค
private let tableView: UITableView = { let view = UITableView() // ... return view }() private let view = UIView() private let view2 = UIView()
๋ทฐ์ ์๋ช ์ฃผ๊ธฐ๋ฅผ ๋ด๋นํ๋ ํจ์ ์์๋, ์ง์ ์ ์ธ ๊ตฌํ ๋ณด๋ค๋ ํจ์ ํธ์ถ๋ง ์งํ
~~override viewDidLoad() { super.viewDidLoad() self.view.addsubView(uniView) }~~
override viewDidLoad() { super.viewDidLoad() self.addUniView() } private func addUniView() { super.viewDidLoad() self.view.addsubView(uniView) }

SPM์ ์ด์ฉ
Kingfisher //์ด๋ฏธ์ง์ฒ๋ฆฌ
Alamofire // ๋คํธ์ํฌ
Snapkit //๋ ์ด์์
Then //์ฝ๋ ๊ฐ๊ฒฐํ
Sentry //error tracking
kakao-ios-sdk //socialLogin
firebase-auth //socialLogin