변수 이름은 lowerCamelCase를 사용해주세요.
var categories: [String]
var person: Person
var isShowing: Bool함수
- 함수 이름에는
lowerCamelCase를 사용해주세요. - 함수는 일반적으로 동사원형으로 시작해주세요.
- Event-Handling 함수의 경우 (조동사 + 동사원형)으로 시작해주세요. 주어는 유추 가능하다면, 생략 가능합니다.
will은 특정 행위가 일어나기 직전을 의미합니다.did는 특정 행위가 일어난 직후를 의미합니다.
private func didFinishSession() {
// ...
}
private func willFinishSession() {
// ...
}
private func didChangeSchedule() {
// ...
}데이터를 가져오는 함수의 경우, get 사용을 지양하고 request, fetch을 적절하게 사용해주세요.
request: 에러가 발생하거나, 실패할 수 있는 비동기 작업에 사용합니다. 예를 들어, http 통신을 통해 값을 요청하는 경우가 이에 해당합니다.fetch: 요청이 실패하지 않고 결과를 바로 반환할 때 사용합니다. 예를 들어, data를 찾고자 하는 모든 행위를 할 때가 이에 해당합니다.
func reqeustData(for user: User) -> Data?
func fetchData(for user: User) -> Data- 열거형의 이름은
UpperCamelCase를 사용해주세요. - 열거형의 각 case에는
lowerCamelCase를 사용해주세요.
enum Result {
case .success
case .failure
}- 프로토콜에는 무조건 Swift 주석 형식을 사용해주세요.
/// DB내 사용자 이름과 ID로 나이를 조회합니다.
/// - Parameter ID: user ID
/// - Parameter name: user fullname
/// - Returns: user age
func readData(ID: Int, name: String) -> Int {
var age: Int
// code to read data...
return age
}- 연관된 코드가 있다면
MARK를 사용하여 코드영역을 구분지어 주세요.
struct HomeView { ... }
// MARK: - (S)HomeTopView
struct HomeTopView { ... }- 아직 개발이 완료되지 않은 코드가 있다면
TODO나FIXME를 사용하여 체크해주세요
// TODO: 리팩토링- 인덴트는 저희 프로젝트에서 스페이스바 2개로 통일하겠습니다.(탭1 = 스페이스바2)
func sayHiLeeo(isHappy: Bool) {
if isHappy {
print("Hi Leeo!")
}
}- 콜론(
:)을 사용할 땐 콜론의 오른쪽으로 한 칸의 여백을 생성합니다. (빈 딕셔너리는 제외)
let monfi: [String: String] = ["승재": "근웅"]- 글자수가 100이 넘어가면, 파라미터 기준으로 줄바꿈을 합니다.
func initializeDay(
locationName: String,
weather: Int,
temperature: Double
) async throws {
// ...code
}
try await initializeDay(
locationName: "ㅋㅋ",
weather: "어쩌고",
temperature: 0.5
)- 인자가 한 개일 경우에만
$0을 허용하고, 복잡한 로직 또는 가독성이 떨어질 경우 명시적으로element in같은 이름을 사용합니다.
let names = ["A", "B", "C"].map { $0.lowercased() }- struct로 작성된 뷰의 이름은
UpperCamelCase로 작성해주세요.
struct HomeView { ... }@ViewBuilder로 작성된 컴포넌트의 이름은lowerCamelCase로 작성해주세요. (해당 컴포넌트가 어떤것으로 작성되었는지 구분하기 위함)
@ViewBuilder
private func favoriteButton() -> some View {
Button {
isFavorite.toggle()
} label: {
...
}
}-
뷰 자체는
struct로 정의 하되, 필요시에는 컴포넌트 단위로@ViewBuilder사용을 허용합니다. -
@ViewBuilder를 사용하는 조건은 아래와 같습니다.- 뷰가 아닌 컴포넌트로 판단 될 시(ex: 버튼, 상단 배너, 도움말…)
- 한
struct내에서 같은 컴포넌트를 재활용 할 시
struct ItemView: View { var body: some View { VStack { item(name: "아이템1") item(name: "아이템2") } } @ViewBuilder private func item(name: String) -> some View { Text(name) } }
- 하나의 뷰 내에서 중첩된 컨테이너가 3개 초과 시(선택)
struct ItemView: View { var body: some View { VStack { // 중첩 1 HStack { // 중첩 2 item(name: "아이템1") item(name: "아이템2") } } } @ViewBuilder private func item(name: String) -> some View { Text(name) .background { // 중첩 3 ZStack { // 중첩 4 Circle() .background(.red) } } } }
- 하나의 파일 이내에서 struct를 통한 뷰를 나눌때는
// MARK: - (S)를 사용합니다. - @ViewBuilder를 통해 컴포넌트를 만들때는
// MARK: (F)를 사용합니다.
// MARK: - (S)ItemView
struct ItemView: View {
var body: some View {
VStack { // 중첩 1
HStack { // 중첩 2
item(name: "아이템1")
item(name: "아이템2")
}
}
}
// MARK: (F)item
@ViewBuilder
private func item(name: String) -> some View {
Text(name)
.background { // 중첩 3
ZStack { // 중첩 4
Circle()
.background(.red)
}
}
}
}- 하나의 뷰 struct 내에서 레이아웃 컨테이너는 최대 2개까지만 사용하는것을 권장합니다.
struct ItemView: View {
var body: some View {
VStack {
HStack {
item(name: "아이템1")
item(name: "아이템2")
} // : HStack
} // : VStack
}
}- 여백의 경우에는
Spacer()의 사용을 최대한 지양하고,frame()사용을 권장합니다.
// Bad ❌
HStack {
Spacer()
Text("맨 오른쪽에 배치해보겠습니다.")
}
// Good ✅
Text("맨 오른쪽에 배치해보겠습니다.")
.frame(maxWidth: .infinity, alignment: .trailing)- 위 아래 요소간의 배치에 여백을 줘야하는 경우, 특별한 경우가 아니면 아래 요소의 여백으로 배치합니다.
(
HStack의 경우에는 오른쪽)
VStack {
item(name: "아이템1")
// .padding(.bottom, 10) ❌
item(name: "아이템2")
.padding(.top, 10)
}- 또한, 일정한 간격으로 배치해야 하는 경우에는 각 컨테이너의
spacing을 활용해주세요.
VStack(spacing: 10) {
item(name: "아이템1")
item(name: "아이템2")
item(name: "아이템3")
item(name: "아이템4")
}- 뷰의 전체에 같은 여백을 줘야하는 경우에는 제일 상위 뷰에서
padding을 작성해주세요.
VStack {
item(name: "아이템1")
item(name: "아이템2")
item(name: "아이템3")
item(name: "아이템4")
}.padding(.horizontal, 24)- 수평/수직 여백끼리 같은 경우 두개의
padding모디파이어를 사용해주시고 값이 다를때는EdgeInsets()사용을 허용합니다.
VStack {
item(name: "아이템1")
item(name: "아이템2")
item(name: "아이템3")
item(name: "아이템4")
}
.padding(.horizontal, 24)
.padding(.vertical, 10)- 뷰 초기화 시 매개변수가 필요할때는 생성자를 사용하지 않고 기본
internal을 사용합니다. - 아래 ChildView처럼, 해당 파일 내에서 쓰는 하위 뷰일 경우에는
struct앞에private을 붙여줍니다.
struct ParentView: View {
var body: some View {
VStack {
ChildView(name: "자식 뷰")
}
}
}
private struct ChildView: View {
(Internal)let name: String
var body: some View {
Text(name)
}
}