iOS SwiftLint 적용하며 수정한 것들

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


SwiftLint

Vertical Whitespace Violation: Limit vertical whitespace to a single empty line. Currently 2. (vertical_whitespace) 2946 (999+, 9)

코드 사이 한줄씩만 띄도록 수정

Colon Violation: Colons should be next to the identifier when specifying a type and next to the key in dictionary literals. (colon)

타입 정의나 딕셔너리에서 :을 사용할때 앞은 붙이고 뒤는 한칸 스페이스를 넣어야한다.

let a: Int?
let b: [String: Int]

Unused Closure Parameter Violation: Unused parameter “timer” in a closure should be replaced with _. (unused_closure_parameter)

사용하지 않는 클로저 파아미터들은 _ 와일드카드 식별자로 변경

Opening Brace Spacing Violation: Opening braces should be preceded by a single space and on the same line as the declaration. (opening_brace) (741, 9)

함수 등에서 앞의 대괄호를 열때 {, 앞 쪽 공백이 한칸 들어가야 한다.

func setA() { }

Control Statement Violation: if, for, guard, switch, while, and catch statements shouldn’t unnecessarily wrap their conditionals or arguments in parentheses. (control_statement) (757, 8)

if 구문등의 조건 부분을 소괄호로 묶지 않아도 된다.

if (a > b) { }  // 변경 전
if a > b { }  // 변경 후

Comma Spacing Violation: There should be no space before and one after any comma. (comma)

콤마 ,를 사용한 경우, 그 앞은 붙고 그 뒤는 한칸 공백이 있어야 함

Statement Position Violation: Else and catch should be on the same line, one space after the previous declaration. (statement_position)

else 구문은 이전 괄호와 동일한 줄에 표시하는 것을 권장

if {

} else {

}

Returning Whitespace Violation: Return arrow and return type should be separated by a single space or on a separate line. (return_arrow_whitespace) (441, 8)

반환타입을 주는 화살표 ->와 반환 타입 사이 공백이 한칸씩 필요

func setA() -> Int { }

Redundant Optional Initialization Violation: Initializing an optional variable with nil is redundant. (redundant_optional_initialization)

옵셔널 변수라면 최초에 자동으로 nil로 초기화 되기 때문에 명시해주지 않아도 된다.

var frame: CGRect? = nil  // 적용 전
var dimFrame: CGRect?  // 적용 후

UIKit와 SwiftUI 무엇이 다를까?

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
참고 블로그는 아래와 같습니다.


SwiftUI?

  • 스위프트 언어로 모든 플랫폼에서 앱에 대한 UI와 동작을 선언해주는 프레임워크 > 선언형 프로그래밍
    • 선언형 프로그래밍: 무엇을 수행하는가에 집중을 한 프로그래밍 기법 > 코드 가독성과 재사용성을 높임
  • 접근성 및 지역화 등 다양한 기능을 자동으로 지원해줌 (다크모드, 유동적 글자 크기 조정 등)
  • UIKit, AppKit, WatchKit 프레임워크 객체와 통합해 플랫폼 별 더 많은 기능을 활용할 수 있음
  • Xcode12, iOS13 이상부터 지원 가능
  • 뷰 프로토콜을 채택하고 바디를 구현해주어 뷰를 사용하게함
  • 공간의 개념으로 뷰를 만들면 중앙부터 차지하게됨 (상대적이 아님)

SwiftUI 장점?

  • 한번의 개발로 모든 플랫폼에서 동작이 가능한 앱 구현이 가능
  • 생명주기 관리 필요가 없음
  • 스토리보드를 통한 MVC 아키텍쳐 패턴의 작업 시 데이터의 변화 상태를 바로 볼 수 없는 등의 단점을 해결
  • 코드 작성과 동시에 디자인 인터페이스가 생성되고 렌더링이 됨
  • .Modifier(.)로 체이닝을 통해 스타일링에 대해 구현이 가능
  • 유지보수 시 코드 가독성이 좋고 편리
  • 기존에는 앱 내의 데이터가 변경된다면,사용자 인터페이스가 데이터의 최신상태를 항상 유지하도록 로직을 처리하여야 했으나 swiftUI는 앱의 데이터 모델과 컴포넌트, 로직을 바인딩하는 방법으로 이러한 단점을 해결
  • 데이터 모델은 앱의 다른 부분에서 구독할 수 있는 데이터 변수를 게시하게 되고, 데이터가 변경이 이루어 졌을때, 구독자에게 알림을 전달.이로인해 데이터의 변경사항을이 있을 때마다 컴포넌트를 수정할 필요없이 그냥 놔둬도 swiftUI가 자동으로 반영함. 결국 데이터의 변화가 앱의 동작과 생김새를 주도하게 되는 것

SwiftUI 단점?

  • 아직 UIKit을 전부 대체하지 못함
    • Mapkit이나 Webkitview 등은 아직까지는UIKit을 사용해야 함
  • 낮은 버전에 대해 지원이 되지 않아 Deployment Target이 한정적
  • 나온지 얼마 되지 않아 아직 버그 및 문제가 많음di
  • 라이브러리들의 부실한 지원

SwiftUI와 UIKit?

  • SwiftUI는 UIKit의 대체는 아니다. 이유는 SwiftUI의 많은 기능들이 UIKit 상에서 작동한다.
  • UIKit은 이벤트 중심 프레임워크이고 SwiftUI는 상태 중심 프레임워크
  • UIKit 위에서 빌드된다는 말로 코드가 내부에서 UIKit에 있는 컴포넌트 소스로 변환해 컴파일 한다는 의미
  • 동시에 사용하려면 UIHostingController를 사용!
  • UIKit의 경우 view들이 UIView 클래스를 상속받는데, SwiftUI는 구조체이면서 view protocol만 준수하면 됨

UIKit -> SwiftUI로 변화된 UI 요소

  • UITableView: List
  • UICollectionView: No SwiftUI equivalent
  • UILabel: Text
  • UITextField: TextField
  • UITextField with isSecureTextEntry set to true: SecureField
  • UITextView: No SwiftUI equivalent
  • UISwitch: Toggle
  • UISlider: Slider
  • UIButton: Button
  • UINavigationController: NavigationView
  • UIAlertController with style .alert: Alert
  • UIAlertController with style .actionSheet: ActionSheet
  • UIStackView with horizontal axis: HStack
  • UIStackView with vertical axis: VStack
  • UIImageView: Image
  • UISegmentedControl: SegmentedControl
  • UIStepper: Stepper
  • UIDatePicker: DatePicker
  • NSAttributedString: Incompatible with SwiftUI; use Text instead.

SwiftUI Property Wrappers?

  • @State: 상태변화를 감지하도록 사용
    • 일반적으로 struct는 값 타입이여서 struct내의 값을 변경할 수 없다.
    • SwiftUI는 @State 를 제공해 struct내의 값을 변경할 수 있게 해준다.
    • SwiftUI의 view는 struct이고, 이는 언제든 소멸되거나 재생성된다.
    • 그렇기 때문에 @State 를 사용해 지속적으로 변형 가능한 변수를 만드는 것이다.
    • 단, @State 는 String, Int, Bool과 같은 간단한 타입에만 사용되는 것이 좋다.
    • 일반적으로 @State 변수는 private으로 선언되고, 다른 view와 공유되지 않는다.
    • 다른 view와 값을 공유하고 싶다면, @ObservedObject@EnvironmentObject 를 사용하면 된다.
import SwiftUI

struct ContentView: View {
    @State var userName: String = ""
    var body: some View {
        VStack {
            TextField("Enter your ID", text: $userName)  // $를 통해 state propery를 호출
                .border(Color(UIColor.separator))
            // userName값이 변하면 userName을 참조하는 컴포넌트가 새로 렌더링 되어 값을 표현함
            Text("Welcome, \(userName)!")

        }
        .textFieldStyle(RoundedBorderTextFieldStyle())
        .padding()
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
  • @Binding: 정의된 @State 변수를 사용하고 해당 값을 넘겨받을거란 의미로 다른 부분에서 변경이 일어나도 자동 연결 변경됨
    • @Binding 은 부모 view의 @State 와 같은 값을 양방향으로 연결되도록 해준다.
    • 즉 자신의 뷰가 아닌 부모 뷰에서 값을 가져오고 싶을때 사용하는 키워드 > 뷰 끼리 양방향으로 연결해서 서로 값을 공유할 수 있도록 해주는 키워드
    • 아래 코드에서 userName은 message를 바인딩 시켜줘서 값을 변경해준다.
import SwiftUI

struct ContentTextView: View {
    @Binding var message: String

    var body: some View {
        Text(message)
            .padding(10)
            .border(Color.orange, width: 1.5)
    }
}

struct ContentView: View {
    @State var userName: String = ""
    var body: some View {
        VStack {
            TextField("Enter your ID", text: $userName)
                .border(Color(UIColor.separator))
            ContentTextView(message: $userName)
        }
        .textFieldStyle(RoundedBorderTextFieldStyle())
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

iOS Build service could not create build operation unknown error while handling message unknownsession 에러가 나온다면?

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


Build service could not create build operation unknown error while handling message unknownsession

엑스코드 열자마자 빌드를 눌러서.. 아직 파일 인덱싱이 끝나지 않았는지를 확인해보자.

참고한 stackoverflow

iOS iOS13 Deprecated statusBarFrame, keyWindow 수정하기

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


StatusBar Height 구하기

기존 iOS13 이전에는 statusbar의 높이를 UIApplication.shared.statusBarFrame.height를 통해 구할 수 있었습니다.

그러나 iOS13부터는 이 방식이 deprecated 되어 아래 문구를 띄워주게 됩니다.

이제 window scene의 statusbarManager를 사용하라는 의미입니다.
이는 아래 방식으로 고쳐 사용하면 됩니다.

Before

UIApplication.shared.statusBarFrame.height

After

view.window?.windowScene?.statusBarManager?.statusBarFrame.height ?? 0

옵셔널은 상황에 맞게 처리해주시면 됩니다.

keyWindow

keyWindow란 윈도우가 여러개 존재할 때, 가장 앞쪽에 배치된 윈도우를 의미합니다.
터치 이벤트같은 경우 해당 이벤트들은 이벤트가 발생한 윈도우에 직접 전달이 됩니다.

그런데 관련 좌표값이 없는 이벤트 같은 경우에는 키 윈도우로 전달이 됩니다.

이러한 좌표값이 없는 이벤트는 시스템이 생성한 윈도우에서 생성된 이벤트를 의미합니다.

예로들어, 가상 키보드 창은 시스템이 생성한 윈도우입니다.
키보드 창에서 글자를 입력할 때 발생하는 이벤트들은 앱의 키 윈도우로 전달이 됩니다.
하나의 시점에는 오직 한개의 윈도우만이 키 윈도우가 될 수 있으며, 키 윈도우는 isKeyWindow 속성을 통해 결정 할 수 있습니다.

이러한 keyWindow는 iOS13에서 deprecated 되었습니다.

이제 keyWindow를 window로 사용해야 합니다.

Before

UIApplication.shared.keyWindow

After

UIApplication.shared.window.first { $0.isKeyWindow }

만약 윈도우의 bottomConstraint를 설정하고 싶다면 어떻게 해야할까요?

let bottomConstraint = UIApplication.shared.windows.filter { $0.isKeyWindow }.first?.safeAreaInseta.bottom ?? 0

git tag 사용해보기

|

개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.


Git Tag

  • 커밋을 참조하기 쉽도록 알기 쉬운 이름을 붙이는 것
  • 한 번 붙인 태그는 브랜치처름 위치가 이동하지 않고 고정되어 있음

Tag 사용방법

1. 일반적인 태그 달아보기

현재 HEAD에 tag 설정

git tag <tag name>

2. 특정 커밋 버전에 태그 달아보기

git tag <tag name> <commit version>

tag 원격 저장소에 push

git push origin <tag name>  // tag name에 해당하는 것만 push
git push origin --tags  // 모든 tag push

tag 삭제

git tag -d <tag name>
git push origin :<tag name>

등록된 tag 이름 확인

git tag