이 글은 https://sarunw.com/posts/xcode-shortcuts-for-swiftui/ 를 번역해서 작성한 글입니다.

SwiftUI로 개발할 때, 유용한 Xcode 단축키에 대해서 소개해드리겠습니다.

Preview 새로고침

SwiftUI로 개발할 때 편한 기능 중에 하나인 Preivew 기능이 종종 멈출 때가 있습니다.

이럴 때, resume버튼을 눌러줘야만 다시 Priview기능이 동작합니다.

계속해서 resume버튼을 누르는 것은 꽤나 불편한 일입니다. 그래서 단축키를 알아두면 편하게 Preview 기능을 이용할 수 있습니다.

command + option + p
Editor menu > Canvas > Refresh Canvas

Indent 적용

SwiftUI에서는 UIKit으로 개발할 때에 비해서 Indnet(들여쓰기)가 많습니다.

간혹 오타가 한번 생기거나, 자동완성을 잘못 사용했을 때 Indent가 잘못 되는 경우가 있습니다.

하나한 Indent를 수정해주는 것 보다, 단축

키를 사용하면 한번에 Indent를 설정해줄 수 있습니다.

control + i
Editor menu > Structure > Re-Indent

코드 이동하기

SwiftUI에서는 적용해주는 함수(?)의 순서가 중요합니다.

적용순서를 바꾸는것은 동작이나 모습의 변화를 의미합니다.

아래는 그 예시입니다.

Text("SwiftUI")
    .padding()
    .background(Color.yellow)

Text("SwiftUI")
    .background(Color.yellow)
    .padding()

이렇게 SwiftUI에서는 적용 순서가 중요하기 때문에, 한 줄의 코드를 위로, 아래로 옮기는 일이 다분합니다.

command + option + [/]
Editor menu > Structure > Move Line Up

한 줄만 위 아래로 옮기는 것이 아닌, 여러줄을 선택해서 한번에 옮길 수도 있습니다.

간단하게 여러 줄을 선택해서 위의 단축키를 누르면 동일한 방법으로 여러줄의 코드를 이동할 수 있습니다.

SF Symbol

[Apple Developer

There’s never been a better time to develop for Apple platforms.

developer.apple.com](https://developer.apple.com/sf-symbols/)

SF Symbols is a library of iconography designed to integrate seamlessly with San Francisco, the system font for Apple platform

사용

SF Symbols에서 제공하는 이미지를 사용하면 systemName으로 이미지을 불러올 수 있다.

UIImage(systemName: "bicycle.circle")

호환성

하지만 버전별로 지원하는 이미지가 다르므로, 버전별로 대응이 필요하다.

예를 들어서 `bicycle.circle`의 사용 가능 버전은 아래와 같다.

SF Symbols 프로그램에서  검색

극복

원하는 이미지를 검색해서 선택한 뒤, 아래와 같이 템플릿 내보내기버튼을 클릭한다.

이렇게 생긴 JSON포멧에서 distanceduration만 파싱하려고 한다.

다른 변수들은 모두 필요가 없기 때문에, 저 둘의 상위 변수들에만 접근해서 추출하면 된다.

애플에서 소개된 방법으로는 최상위에서부터 depth를 하나씩 들어가면서 Container를 만들며 접근할 수 있다.

그런데, 상위 변수가 배열 형식일 경우에는 추가적으로 배열의 원소에 접근하는 작업이 필요하다.

검색을 해보면, nested array data, nested array, nested json과 같은 키워드로 결과가 나오는데

그 방법들을 모두 종합해서 가장 간단한 방법으로 구현 해 보았다.

아래 코드에서 보면 featuresContainer에 한번 접근 한 뒤에, 그 내부에서 featureContainer에 접근하는 것을 볼 수 있다.

struct MyORResponse: Decodable {
    let distance: Double?
    let duration: Double?

    init(from decoder: Decoder) throws {
        // 최상위 컨테이너에 접근한다.
        let rootContainer = try decoder.container(keyedBy: RootContainerKeys.self)

        // root > features
        var featuresContainer = try rootContainer.nestedUnkeyedContainer(forKey: .features)

        // root > features > feature
        let featureContainer = try featuresContainer.nestedContainer(keyedBy: FeatureKeys.self)

        // root > features > feature > properties
        let propertiesContainer = try featureContainer.nestedContainer(keyedBy: PropertiesKeys.self.self, forKey: .properties)

        // root > features > feature > properties > summary
        let summaryContainer = try propertiesContainer.nestedContainer(keyedBy: CodingKeys.self, forKey: .summary)


        // root > features > feature > properties > summary > duration, distance
        self.duration = try summaryContainer.decode(Double.self, forKey: .duration)
        self.distance = try summaryContainer.decode(Double.self, forKey: .distance)
    }

    private enum CodingKeys: String, CodingKey {
        case distance
        case duration
    }

    private enum RootContainerKeys: CodingKey {
        case features
    }

    private enum FeatureKeys: CodingKey {
        case properties
    }

    private enum PropertiesKeys: CodingKey {
        case summary
    }
}

위와 같이 모델을 작성한 경우에

let jsonData = """
{
    ...
}
""".data(using: .utf8)!

let result = try JSONDecoder().decode(MYORResponse.self, from: jsonData)

let distance = result.distance
let duration = result.duration

이렇게 디코딩된 객체에서 단번에 접근할 수 있다.

11 / 24 (수) 일단 만들면서 해결한 이슈들부터 기록한 뒤, 나중에 완성된 글을 작성할 예정이다.

따릉이 API

API 명세서.

Response 명세는 아래와 같이 나와있다.

하지만 해당 값들이 어떤 타입인지 전혀 나와있지 않다..

출력을 해 보면 아래와 같이 응답이 온다.

응답 결과

응답 결과를 보고 대강 예상해서 모델을 만들어봤을 때는, 아래와 같이 Cnt변수Int 타입으로 만들었다.

이렇게 모델을 만들어 응답 결과를 디코딩 했더니

🥲 외않돼지.. 🥲

열심히 구글링을 하던중에 아래 글을 보게 되었고, 어떤 상황에서 Decoding오류가 발생하는지 알게 되었다.

https://jiseobkim.github.io/swift/2018/07/21/swift-Alamofire와-Codable.html

[Swift - Alamofire와 Codable

나만의 공간

jiseobkim.github.io](https://jiseobkim.github.io/swift/2018/07/21/swift-Alamofire와-Codable.html)

그래서 의심가는것들을 하나씩 바꿔보았고, 원인을 찾을 수 있었다.

Cnt변수들이 모두 String타입이였던 것이다...! 그런데 또, list_total_count변수는 Int타입니다...

완성된 모델

왜.. 이런식으로 변수타입을 설정했는지는 전혀 모르겠지만,, 아무튼 여러 삽질끝에 해결하게 되었다.

`RantalStationInfo`의 Cnt변수들은 왜 `String`으로 설정했고, `list_total_count`변수는 `Int`타입으로 설정했는지 아시는분은 댓글로 꼭 알려주시면 감사하겠습니다,,

'iOS' 카테고리의 다른 글

[Swift] API Response 파싱 / Codable / Nested Array JSON  (0) 2021.11.29

+ Recent posts