ย ย ย ย ย
๐ท ๐ท ๐ท
- ํจ์ : lowerCamelCase ์ฌ์ฉํ๊ณ ๋์ฌ๋ก ์์
- ๋ณ์, ์์ : lowerCamelCase ์ฌ์ฉ
- ํด๋์ค : UpperCamelCase ์ฌ์ฉ
- ViewController โ
VC
- TableViewCell โ
TVC
- CollectionViewCell โ
CVC
- ์ด ์ธ์ ์ถ์ฝํ์ ์ฌ์ฉํ์ง ์์ต๋๋ค.
-
viewDidLoad()
์์๋ย ํจ์ํธ์ถ๋ง ์ฌ์ฉํฉ๋๋ค. -
ํจ์๋ย
extension
์ ์ ์ํ๊ณ ์ ๋ฆฌํฉ๋๋ค.-
extension
์ ๋ชฉ์ ์ ๋ฐ๋ผ ๋ถ๋ฅํฉ๋๋ค. -
์์๋ ๋ค์๊ณผ ๊ฐ์ต๋๋ค.
final class A { private let dldld: String private var sds: Bool { } } // MARK: - Initialize extension A { init() { } func viewDidLoad() { } } // MARK: - Public functions extension A { } // MARK: - Private functions extension A { } // MARK: - ์ด๋ ํจ์๊ฐ ๋ชจ์ฌ์์ต๋๋ค extension A { }
-
- API Design Guide์ ์ค๋ช ๋ Swift ๋ช ๋ช ๊ท์น์ ์ฌ์ฉํฉ๋๋ค.
- ๋ชจ๋ ๋ค์ด๋ฐ์ ๊ทธ ๋ด์ฉ์ ์ถฉ์คํ ์ค๋ช ํด์ผ ํฉ๋๋ค. ์ด๋ฆ์ ์ง๊ธฐ ์ด๋ ค์ด ๊ฒฝ์ฐ ์ญํ ์ ๋ ๋ถ๋ฆฌํด ๋ณด์ธ์.
- Swift Type ์ด๋์ ๋ผ์ด์ง ๋๋ ํ๋กํ ์ฝ์ UpperCamelCase์ ์ฌ์ฉํฉ๋๋ค.
- ๊ทธ ์ธ์๋ lowerCamelCase๋ฅผ ์ฌ์ฉํฉ๋๋ค.
๋ธ๋ฆฌ๊ฒ์ดํธ ๋ฉ์๋๋ฅผ ๋ง๋ค ๋ ์ด๋ฆ์ด ์๋ ์ฒซ ๋ฒ์งธ ๋งค๊ฐ๋ณ์๋ ๋ธ๋ฆฌ๊ฒ์ดํธ ์ด๋ฆ์ด์ด์ผ ํฉ๋๋ค.
Preferred:
func namePickerView(_ namePickerView: NamePickerView, didSelected name: String)
func namePickerView(_ namePcikerView: NamePckerview, didChanged value: String)
Not - Preferred:
func didSelectName(namePicker: NamePickerViewController, name: String)
func namePickerShouldReload() -> Bool
- ํ ์ค์ ์ต๋ 120์๋ฅผ ๋์ง ์๋๋ก ํฉ๋๋ค.
- Xcode์์ย Preferences -> Text Editing -> Display -> Page guide at column์ 120๋ก ์ค์ ํด์ ์ฌ์ฉํด์ฃผ์ธ์.
- ๋์ด์ ์์์ด ์ผ์ด๋์ง ์๋ class๋ย
final
์ ๋ช ์ํฉ๋๋ค.
final class AnyViewController: BaseViewController {
...
}
- class ๋ด๋ถ์์๋ง ์ฐ์ด๋ ๋ณ์๋ย
private
์ ๋ช ์ํฉ๋๋ค. fileprivate
๋ ํ์ํ ๊ฒฝ์ฐ๊ฐ ์๋๋ฉด ํผํ๊ณ ,ยprivate
์ ์ฌ์ฉํฉ๋๋ค.
fianl class ChannelViewController {
private var count = 0
...
}
- Indent๋ 2์นธ์ผ๋ก ์ง์ ํฉ๋๋ค.
- Xcode์์ย Preferences -> Text Editing -> Display -> Line wrappingย ๋ถ๋ถ์ 2 spaces๋ก ์ค์ ํด์ ์ฌ์ฉํด์ฃผ์ธ์.
ํ extension๋น ํ๋์ ํ๋กํ ์ฝ ๋๋ ํด๋์ค๋ฅผ ์ฑํํ๊ณ ์์ํ๋๋ก ํฉ๋๋ค.
class MyViewController:UIViewController {
// class stuff here
}
// MARK: - UITableViewDataSource
extension MyViewController:UITableViewDataSource {
// table view data source methods
}
// MARK: - UIScrollViewDelegate
extension MyViewController:UIScrollViewDelegate {
// scroll view delegate methods
}
Not preferred:
class MyViewController: UIViewController, UITableViewDataSource, UIScrollViewDelegate {
ํ์ ์๋ import๋ ์ ๊ฑฐํฉ๋๋ค. Swift Foundation๋ ์์ฑํ์ง ์์๋ ๋๋ค๋ฉด ์์ฑํ์ง ์์ต๋๋ค.
์ฃผ์์ ์ฌ์ฉํด๋ ์ข์ต๋๋ค, ๋ค๋ง ๋๊ฐ์ง ์กฐ๊ฑด์ด ์์ต๋๋ค.
- summary, quick help ๋ฑ์ ์ฌ์ฉํ์ง ์์ต๋๋ค.
- ์ฃผ์์ ๋ ์ง์ ์์ฑ์๋ฅผ ์ ์ต๋๋ค.
- ์์ฑํ ์ฝ๋๊ฐ ํ์คํ ๋ฆฌ๊ฐ ๋์ด์ผ ํ๋ค๋ฉด,
// NOTE: -
์ฃผ์์ ์ฌ์ฉํฉ๋๋ค. - ๊ธฐํ ๋ด์ ๋ค์ ์์ฑํ ์ฝ๋๋
// TODO: -
์ฃผ์์ ์ฌ์ฉํฉ๋๋ค.
- ์์ฑํ ์ฝ๋๊ฐ ํ์คํ ๋ฆฌ๊ฐ ๋์ด์ผ ํ๋ค๋ฉด,
๋ก์ง์ ์ฃผ์์ด ํ์ํ๋ค๋ฉด ์ฝ๋๋ง์ผ๋ก๋ ์ค๋ช ์ด ์ด๋ ต๋ค๋ ๋ฐฉ์ฆ์ ๋๋ค. ์ด๋ฐ ๊ฒฝ์ฐ๋ ๋ก์ง์ ํ๋ฒ ๋๋์ ๋ณด๋ ๊ฒ์ ์ถ์ฒ๋๋ ค์.
-
๋ชจ๋ ์ํฌํธ๋
์ํ๋ฒณ ์
์ผ๋ก ์ ๋ ฌํฉ๋๋ค. -
๋ด์ฅ ํ๋ ์์ํฌ๋ฅผ ๋จผ์ ์ํฌํธํ๊ณ , ๋น ์ค๋ก ๊ตฌ๋ถํ์ฌ ์๋ํํฐ ํ๋ ์์ํฌ๋ฅผ ์ํฌํธํฉ๋๋ค.
import UIKit import SwiftyColor import SwiftyImage import Then import URLNavigator
-
Action ํจ์์ ๋ค์ด๋ฐ์ '์ฃผ์ด + ๋์ฌ + ๋ชฉ์ ์ด' ํํ๋ฅผ ์ฌ์ฉํฉ๋๋ค.
- Tap(๋๋ ๋ค ๋)*์ย
.touchUpInside
์ ๋์ํ๊ณ , - *Press(๋๋ฆ)*๋ย
.touchDown
์ ๋์ํฉ๋๋ค. - will~์ ํน์ ํ์๊ฐ ์ผ์ด๋๊ธฐ ์ง์ ์ด๊ณ ,ย did~๋ ํน์ ํ์๊ฐ ์ผ์ด๋ ์งํ์ ๋๋ค.
- should~๋ ์ผ๋ฐ์ ์ผ๋กย
Bool
์ ๋ฐํํ๋ ํจ์์ ์ฌ์ฉ๋ฉ๋๋ค.
func didClickOnBackbutton() { // ... }
- Tap(๋๋ ๋ค ๋)*์ย
- ~์ธ์ง ์๋์ง์ธ ๊ฒฝ์ฐ
is
ex)isFirstResponder
isMuted
- is + ๋ช ์ฌ, is + ํ์ฉ์ฌ - ~ํด์ผ๋ง ํ๋ ๊ฒฝ์ฐ
should
ex)shouldHideOffline
shouldShowDivider
- ์กฐ๋์ฌ + ๋์ฌ ์ํ - ~ํ ์ ์๋์ง์ ๊ฒฝ์ฐ
can
ex)canBecomeFirstResponder
-
์์๋ฅผ ์ ์ํ ๋์๋ย
enum
๋ฅผ ๋ง๋ค์ด ๋น์ทํ ์์๋ผ๋ฆฌ ๋ชจ์๋ก๋๋ค.์ฌ์ฌ์ฉ์ฑ๊ณผ ์ ์ง๋ณด์ ์ธก๋ฉด์์ ํฐ ํฅ์์ ๊ฐ์ ธ์ต๋๋ค.ย
struct
ย ๋์ ยenum
์ ์ฌ์ฉํ๋ ์ด์ ๋, ์์ฑ์๊ฐ ์ ๊ณต๋์ง ์๋ ์๋ฃํ์ ์ฌ์ฉํ๊ธฐ ์ํด์์ ๋๋ค. -
CGFloatLiteral์ ์ฌ์ฉํด์ ์ฝ๋๋ฅผ ๋จ์ํ์ํต๋๋ค.
final class ProfileViewController: UIViewController { private enum Metric { static let profileImageViewLeft = 10.f static let profileImageViewRight = 10.f static let nameLabelTopBottom = 8.f static let bioLabelTop = 6.f } private enum Font { static let nameLabel = UIFont.boldSystemFont(ofSize: 14) static let bioLabel = UIFont.boldSystemFont(ofSize: 12) } }
Swift๋ ๊ฐ์ฒด์ ํ๋กํผํฐ์ ์ ๊ทผํ๊ฑฐ๋ ๋ฉ์๋ ํธ์ถํ ํ์๊ฐ ์๋ ๊ฒฝ์ฐ์ย self๋ฅผ ์ฌ์ฉํ์ง ์์๋ ๋ฉ๋๋ค.
์ปดํ์ผ๋ฌ์ ์ํด ์๊ตฌ๋ ๋์๋ง self๋ฅผ ์ฌ์ฉํฉ๋๋ค.(@escaping ํด๋ก์ ๋ ์ด๊ธฐํ์์ ์ธ์๊ฐ ํ๋กํผํฐ์ ์ ๋งค๋ชจํธํ ๋).
๊ฐ๊ฒฐํจ์ ์ํด ์ฝ๊ธฐ ์ ์ฉ์ธ ๊ฒฝ์ฐ get์ ์๋ตํฉ๋๋ค.
ํ๋์ ํ๋ผ๋ฏธํฐ
func reticulateSplines(with spline: [Double]) -> Bool {
// reticulate code goes here
}
ํ๋ ์ด์์ ํ๋ผ๋ฏธํฐ๋ฅผ ๊ฐ์ง ๋ฉ์๋
func reticulateSplines(
with spline: [Double],
adjustmentFactor: Double,
translateConstant: Int,
comment: String
) -> Bool {
// reticulate code goes here
}
ํ๋ผ๋ฏธํฐ๊ฐ ํ ๊ฐ์ผ ๋:
let success = reticulateSplines(with: splines)
let success = reticulateSplines(
spline: splines,
adjustmentFactor: 1.3,
translateConstant: 2,
comment: "normalize the display"
)
ํ๋ผ๋ฏธํฐ๊ฐ ์ฌ๋ฌ๊ฐ์ธ ๊ฒฝ์ฐ
๋น ๋ฐฐ์ด๊ณผ ๋น ๋์ ๋๋ฆฌ์ ๊ฒฝ์ฐ Type Annotation์ ์ฌ์ฉํฉ๋๋ค.
Preferred:
var names: [String] = []
var lookup: [String: Int] = [:]
Not Preferred:
var names = [String]()
var lookup = [String: Int]()
weak๋ฅผ ์ฌ์ฉํ์ฌ ์ํ ์ฐธ์กฐ๋ฅผ ๋ฐฉ์งํฉ๋๋ค.
์ผํญ ์ฐ์ฐ์**(? : )**๋ ๋ช ํ์ฑ ๋๋ ์ฝ๋์ ๊น๋์ฑ์ ๋์ผ ๋ ์ฌ์ฉํฉ๋๋ค.
ํ๋์ ์กฐ๊ฑด์ ๊ณ์ฐํ๋ ๊ฒ์ ๋ณดํต ์ฌ์ฉ๋๊ณ ,
๋ณต์์ ์กฐ๊ฑด์ ๊ณ์ฐํ๋ ๊ฒ์ ์ผ๋ฐ์ ์ผ๋ก if ๋ฌธ์ผ๋ก ์ดํดํ๊ฑฐ๋ ์ธ์คํด์ค ๋ณ์๋ก ๋ฆฌํฉํฐ๋ง ํฉ๋๋ค.
์กฐ๊ฑด๋ฌธ ์ฃผ๋ณ์ ๊ดํธ๋ ํ์ํ์ง ์์ผ๋ฏ๋ก ์๋ตํฉ๋๋ค.
Preferred:
if name == "Hello" {
print("World")
}
Not preferred:
if (name == "Hello") {
print("World")
}
๐ท ๐ท ๐ท
๊ธฐ๋ณธ์ ์ผ๋ก Git Flow ์ ๋ต์ ์ด์ฉํ๋ค. ์์ ์์ ์ ์ ํ๋์ด์ผ ํ ์์ ์ ๋ค์๊ณผ ๊ฐ๋ค.
1. Issue๋ฅผ ์์ฑํ๋ค.
2. feature Branch๋ฅผ ์์ฑํ๋ค.
3. Add - Commit - Push - Pull Request ์ ๊ณผ์ ์ ๊ฑฐ์น๋ค.
4. Pull Request๊ฐ ์์ฑ๋๋ฉด ์์ฑ์ ์ด์ธ์ ๋ค๋ฅธ ํ์์ด Code Review๋ฅผ ํ๋ค.
5. Code Review๊ฐ ์๋ฃ๋๋ฉด Pull Request ์์ฑ์๊ฐ develop Branch๋ก merge ํ๋ค.
6. ์ข
๋ฃ๋ Issue์ Pull Request์ Label๊ณผ Project๋ฅผ ๊ด๋ฆฌํ๋ค.
ํ์ ์ ์ค์ํด์ผ ํ ๊ท์น์ ๋ค์๊ณผ ๊ฐ๋ค.
1. develop์์์ ์์
์ ์์น์ ์ผ๋ก ๊ธ์งํ๋ค. ๋จ, README ์์ฑ์ develop Branch์์ ์ํํ๋ค.
2. ์์ ์ด ๋ด๋นํ ๋ถ๋ถ ์ด์ธ์ ๋ค๋ฅธ ํ์์ด ๋ด๋นํ ๋ถ๋ถ์ ์์ ํ ๋์๋ Slack์ ํตํด ๋ณ๊ฒฝ ์ฌํญ์ ์ ๋ฌํ๋ค.
3. ๋ณธ์ธ์ Pull Request๋ ๋ณธ์ธ์ด Mergeํ๋ค.
4. ๋น ๋ฅธ ํ์
์๋๋ฅผ ์ํด Pull Request๊ฐ ์ฌ๋ผ์จ ์ดํ 24์๊ฐ ๋ด์ Code Review๋ฅผ ์ํํ๋ค.
5. Commit, Push, Merge, Pull Request ๋ฑ ๋ชจ๋ ์์
์ ์ฑ์ด ์ ์์ ์ผ๋ก ์คํ๋๋ ์ง ํ์ธ ํ ์ํํ๋ค.
6. README ์์ ์ ์ํ Commit ๋๋ฐฐ๋ ๊ธ์งํ๋ค. ๋ฏธ๋ฆฌ๋ณด๊ธฐ๋ Preview๋ฅผ ํตํด ํ์ธํ๋ค.
ํ์ ์ ์ค์ํด์ผ ํ ๊ท์น์ ๋ค์๊ณผ ๊ฐ๋ค.
Branch๋ฅผ ์์ฑํ๊ธฐ ์ Issue๋ฅผ ๋จผ์ ์์ฑํ๋ค.
Issue ์์ฑ ํ ์์ฑ๋๋ ๋ฒํธ์ Issue์ ๊ฐ๋ตํ ์ค๋ช
๋ฑ์ ์กฐํฉํ์ฌ Branch์ ์ด๋ฆ์ ๊ฒฐ์ ํ๋ค.ย <Prefix>/<Issue_Number>-<Description>
ย ์ ์์์ ๋ฐ๋ฅธ๋ค.
main
ย : ๊ฐ๋ฐ์ด ์๋ฃ๋ ์ฐ์ถ๋ฌผ์ด ์ ์ฅ๋ ๊ณต๊ฐdevelop
ย : feature ๋ธ๋์น์์ ๊ตฌํ๋ ๊ธฐ๋ฅ๋ค์ด merge๋ ๋ธ๋์นfeature
ย : ๊ธฐ๋ฅ์ ๊ฐ๋ฐํ๋ ๋ธ๋์น, ์ด์๋ณ/์์ ๋ณ๋ก ๋ธ๋์น๋ฅผ ์์ฑํ์ฌ ๊ธฐ๋ฅ์ ๊ฐ๋ฐํ๋คrelease
ย : ๋ฆด๋ฆฌ์ฆ๋ฅผ ์ค๋นํ๋ ๋ธ๋์น, ๋ฆด๋ฆฌ์ฆ ์ง์ QA ๊ธฐ๊ฐ์ ์ฌ์ฉํ๋คbug
: ๋ฒ๊ทธ๋ฅผ ์์ ํ๋ ๋ธ๋์นhotfix
ย : ์ ๋ง ๊ธํ๊ฒ, ๋ฐ๋ชจ๋ฐ์ด ์ง์ ์ ์๋ฌ๊ฐ ๋ ๊ฒฝ์ฐ ์ฌ์ฉํ๋ ๋ธ๋ ์น
feature/#17-description์๋ฌธ์๋ก๋ง์ฐ๊ธฐ
- [HOTFIX] : issue๋, QA์์ ๊ธํ ๋ฒ๊ทธ ์์ ์ ์ฌ์ฉ
- [FIX] : ๋ฒ๊ทธ, ์ค๋ฅ ํด๊ฒฐ
- [ADD] : Feat ์ด์ธ์ ๋ถ์์ ์ธ ์ฝ๋ ์ถ๊ฐ, ๋ผ์ด๋ธ๋ฌ๋ฆฌ ์ถ๊ฐ, ์๋ก์ด ํ์ผ ์์ฑ ์
- [FEAT] : ์๋ก์ด ๊ธฐ๋ฅ ๊ตฌํ
- [DEL] : ์ธ๋ชจ์๋ ์ฝ๋ ์ญ์
- [DOCS] : README๋ WIKI ๋ฑ์ ๋ฌธ์ ๊ฐ์
- [MOD] : storyboard ํ์ผ,UI ์์ ํ ๊ฒฝ์ฐ
- [CHORE] : ์ฝ๋ ์์ , ๋ด๋ถ ํ์ผ ์์
- [CORRECT] : ์ฃผ๋ก ๋ฌธ๋ฒ์ ์ค๋ฅ๋ ํ์ ์ ๋ณ๊ฒฝ, ์ด๋ฆ ๋ณ๊ฒฝ ๋ฑ์ ์ฌ์ฉํฉ๋๋ค.
- [MOVE] : ํ๋ก์ ํธ ๋ด ํ์ผ์ด๋ ์ฝ๋์ ์ด๋
- [RENAME] : ํ์ผ ์ด๋ฆ ๋ณ๊ฒฝ์ด ์์ ๋ ์ฌ์ฉํฉ๋๋ค.
- [IMPROVE] : ํฅ์์ด ์์ ๋ ์ฌ์ฉํฉ๋๋ค.
- [REFACTOR] : ์ ๋ฉด ์์ ์ด ์์ ๋ ์ฌ์ฉํฉ๋๋ค
- [MERGE]: ๋ค๋ฅธ๋ธ๋ ์น๋ฅผ merge ํ ๋ ์ฌ์ฉํฉ๋๋ค.
์์
[FEAT] ๋ ์ด์์ ๊ตฌํ(#17)
Reviewee
- ๋ฆฌ๋ทฐ๋ฅผ ํฉ๋ฆฌ์ , ์ค๋ฆฝ์ ์ผ๋ก ๋ฐ์๋ค์ฌ์ผ ํจ (๋ฌด์กฐ๊ฑด ์ซ์ด, ์ข์๋ ๊ณค๋)
- ๋ฐ์์ด ์ด๋ ค์ฐ๋ฉด ์ ์ด๋ ค์ด์ง, ํฉ๋ฆฌ์ ์ธ ์ด์ ๋ฅผ ๋์ผ ํจ
- ํผ๋๋ฐฑ์ ๋ฐ์ ํด๋ ๋๊ณ ์ํด๋๋จ but.์ฑ ์์ ๊ฒฐ์ ํ ์ฌ๋์ด ์ง๋ค.
- ๋ฐ์ํ์ง ์๋ ๊ฒ์ ๋ํ๊ฒ์ ํฉ๋นํ ์ด์ ๊ฐ ๋ฐ๋์ ์กด์ฌํ์ฌ์ผ ํจ.
Reviewer
- ์จํํ ๋์์คโค๏ธ๐ค
- ์ ํจํ ๋ฆฌ๋ทฐ๊ฐ ๋ ์ ์๋๋ก ์ผ๋์ ๋๊ณ ๋ฆฌ๋ทฐ
- ์ ํจํ ๋ฆฌ๋ทฐ๋?
- ๋ ์นด๋ก์ด(?) ์ง๋ฌธ - ์คํ์ ๋ํ ํ์ธ, ์์ฑ์์ ์๋ ํ์ธ
- ์ค๋ฅ ์ง์
- ์คํ, ๋ถ์ ์ ํ ๋ค์ด๋ฐ
- ์คํ์ ๋ํ ์๋ชป๋ ์ดํด (ํด๋น ์คํ์ ๋ํ Domain Knowledge ํ์)
- ๋ค๋ฅธ ๋ชจ๋๋ก์ ์ํฅ์ฑ ์ง์
- ๋ณด๋ค ๋์ ์ฑ๋ฅ, ๊ตฌ์กฐ์ ๋์ ์ ์
- ์๋ฃ ๊ตฌ์กฐ, ์ฒ๋ฆฌ ๋ฐฉ์ (๋๊ธฐ/๋น๋๊ธฐ ๋ฑ) ๋ณ๋์ ํด ์ ์
- ๋๋ฃจ๋ญ์ ํ๊ฒ ๋ณด๋ค๋ ์ฝ๋ example์ ์ฃผ๋ ๊ฒ์ด ์ข์
- ์ ํจํ ๋ฆฌ๋ทฐ๋?