ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 200921 - TIL
    TIL/2021 2020. 9. 22. 02:12

    Swift 문법

     

     

    Collection에는 Foundation Collection과 Swift Collection이 있는데 Swift Collection에 대해서만 공부했다.

    • Array
    • Array의 CRUD
    • Dictionary
    • Dictionary의 CRUD
    • Set
    • Set의 CRUD

    간단하다고 생각했는데 지금까지 배운 개념과 섞이니까 이해하는데 고전했다. 공부하며 실수하거나 이해가 힘들었던 부분은

    list = [0, 1, 2 ,3 ,4 ,5 ,6]
    
    list[0...2] = 2						error!!
    list[0...2] = [2]
    
    

    Type을 맞춰줘야 한다 그냥 2라고 적으면 에러가 발생했다.

     

     

    딕셔너리에서 옵셔널 체이닝을 사용하는 경우

    import UIKit
    
    // 딕셔너리 자체가 옵셔널이라면
    let optionalDict: [String: String]? = ["A": "Apple", "S": "Samsung", "L": "LG"]
    // 앞에 옵셔널 체이닝을
    optionalDict?["A"]
    
    
    // 옵셔널로 명시하지 않았는데
    let dict: [String: String] = ["A": "Apple", "S": "Samsung", "L": "LG"]
    // 옵셔널 체이닝을 사용해야한다. dict["Z"] 는 nil을 반환하기 때문에 딕셔너리의 접근은 옵셔널이다.
    dict["S"]?.count
    
    // 딕셔너리의 값이 옵셔널이면?
    let optDict: [String: String?] = ["A": "Apple", "S": "Samsung", "L": "LG"]
    // 뒤에 옵셔널 체이닝을 사용하는 중첩해서 사용해야한다.
    optDict["A"]??.count
    
    // 값도 옵셔널, 딕셔너리도 옵셔널이면?
    let doubleOptDict: [String: String?]? = ["A": "Apple", "S": "Samsung", "L": "LG"]
    // 앞에도 해주고 뒤에도 두번 해준다!!
    doubleOptDict?["A"]??.count
    

    잘 확인해봐야한다!!

     

     

    Collection을 반복문에 사용할 때 for문으로 반복하는 것과 .forEach 메서드를 사용해서 하는 방법의 차이가 있다.

    let arr = [1, 2, 3]
    
    // return이 반복문을 종료시킨다. 그래서 1만 출력
    func useForIn() {
        for num in arr {
            print(num)
            return
        }
    }
    
    // return이 반복을 종료시키는게 아니다. 클로저를 종료시킬뿐 그래서 1, 2, 3이 출력된다.
    func useForEach() {
        arr.forEach { (num) in
            print(num)
            return
        }
    }
    
    useForIn()							//1
    useForEach()						//1 2 3

    스코프의 개념을 잘 생각해 봐야 한다.

     

     

     

     

     

    iOS

     

    • 출력을 할 때 label과 textView의 차이점
    • stackView의 한계 가로로만 정렬되거나 세로로만 정렬이 된다. 만약 혼합해서 하고 싶다면 스택 뷰를 중첩
    • Table View 추가하는 방법

    Table View를 추가하는 방법은 이해가 안 되는 부분이 아주 많다.

     

     

     

    데이터 관리 화면 만들기

    이름과 나이를 적고 추가를 누르면 배열에 저장이 된다,

     

    이름/나이 버튼을 누르면 정렬이 된다. 버튼을 끄면 내림차순으로 정렬이 된다.
    삭제도 가능하다.

     

     

    아직 모든 부분을 구현할 수는 없었다. 공부한 내용을 이용해서 코드를 구성한 부분은

     

    정렬 메서드 만들기

    // [[String: String]] 배열과 딕셔너리 값에 접근할 key 그리고 오름차순이나 내림차순을 결정할 Bool 을 파라미터로 받아
        // 정렬된 [[String: String]]를 반환해주는 함수
        // age를 비교할때 문자열로 저장이 되어서 10보다 9가 큰 문제가 발생
        // 비교메서드에 numeric 옵션을 추가
        
        func sortList(list: [[String: String]], key: String, isAscending: Bool) -> [[String: String]] {
            if isAscending == true {
                return list.sorted {
                    guard let lhs = $0[key], let rhs = $1[key] else { return false }
                    return lhs.compare(rhs, options: [.numeric]) == .orderedAscending
                }
            } else {
                return list.sorted {
                    guard let lhs = $0[key], let rhs = $1[key] else { return false}
                    return lhs.compare(rhs, options: [.numeric]) == .orderedDescending
                }
            }
        }

    나이도 문자열로 받아서 정렬을 할 때 9가 10보다 큰 결과가 나왔다. 이를 문자열 옵션을 이용하여 해결했다.

    switch로 구현하면 더 깔끔해 보일 거 같다는 생각이 든다.

    if else를 안 쓰고 isAscending 파라미터를 이용해 바로 return 값을 반환하고 싶었는데 문자열 옵션을 사용하면서 오름차순 내림차순을 분기하는 방법이 생각이 나지 않았다.

     

     

    세그먼트 컨트롤을 바꿀때마다 이름/나이에 맞게 정렬하기

    @IBAction func typeChanged(_ sender: UISegmentedControl) {
            switch sender.selectedSegmentIndex {
            case 0 where changeSort.isOn == true:
                list = sortList(list: list, key: "name", isAscending: true)
            case 0 where changeSort.isOn == false:
                list = sortList(list: list, key: "name", isAscending: false)
            case 1 where changeSort.isOn == true:
                list = sortList(list: list, key: "age", isAscending: true)
            case 1 where changeSort.isOn == false:
                list = sortList(list: list, key: "age", isAscending: false)
            default:
                break
            }
            
            listTableView.reloadData()
        }

    세그먼트컨트롤을 바꾸거나 옆에 버튼을 눌러도 정렬이 되게 구현하기 위해서 switch문 case에 조건을 추가했다.

    선택된 세그먼트 인덱스가 0(이름) 이면서 버튼이 On이라면 이름을 오름차순으로 정렬하라.

    이런 식으로 4개의 분기를 만들어서 구현했다.

    이때 Table View의 배열이 정렬이 돼야 하는데 정렬은 위에 정렬 메서드를 활용했다.

     

     

    버튼을 켜고 끌 때마다 오름/내림차순으로 정렬하기

    @IBAction func sortChanged(_ sender: Any) {
            switch changeSort.isOn {
            case true where sortTypeSegment.selectedSegmentIndex == 0:
                list = sortList(list: list, key: "name", isAscending: true)
            case false where sortTypeSegment.selectedSegmentIndex == 0:
                list = sortList(list: list, key: "name", isAscending: false)
            case true where sortTypeSegment.selectedSegmentIndex == 1:
                list = sortList(list: list, key: "age", isAscending: true)
            case false where sortTypeSegment.selectedSegmentIndex == 1:
                list = sortList(list: list, key: "age", isAscending: false)
            default:
                break
            }
            
            listTableView.reloadData()
            
        }

    세그먼트 컨트롤 때와 4가지로 분기를 시켰다.

     

     

    이 부분을 제외하고 나머지 부분은 아직 혼자 연습이 많이 부족하다. 그리고 구현에만 신경을 써서 코드의 가독성이나 알고리즘이 좋은지 나쁜지 잘 모르겠다. 더 깔끔하게 구현하는 방법이 있을 거 같다.

    내일 기능을 더 추가를 해보며 다시 만들어 봐야겠다.

    728x90

    'TIL > 2021' 카테고리의 다른 글

    200925 - TIL  (0) 2020.09.26
    200923 - TIL  (0) 2020.09.24
    200920 - TIL  (1) 2020.09.21
    201919 - TIL  (0) 2020.09.20
    200918 - TIL  (1) 2020.09.19
Designed by Tistory.