2017년 7월 16일 일요일

Swift4에서 변경된 String형식에 대한 데모입니다.

    @IBAction func btn8(_ sender: Any) {
        //swift4에서 String은 컬렉션이다. 배열이나 시퀀스처럼 다룰 수 있다.
        let swift3String = "Swift 3"
        var filteredSwift3String = ""
        //문자열에서 각각의 문자를 보내면 문자열로 변환해서 처리하는 복잡한 과정
        for character in swift3String.characters {
            let string = String(character)
            let number = Int(string)
            
            if number == nil {
                filteredSwift3String.append(character)
            }
        }
        print("filteredSwift3String: \(filteredSwift3String)")
        
        //Swift4에서는 아래와 같이 처리가 가능하다.
        let swift4String = "Swift 4"
        let filteredSwift4String =
            swift4String.filter{Int(String($0)) == nil}
        print("filteredSwift4String: \(filteredSwift4String)")
//        filteredSwift3String: Swift
//        filteredSwift4String: Swift

        //Swift3에서 substring에서 문자열을 리턴
        let swift3SpaceIndex = swift3String.characters.index(of: " ")
        let swift3Substring = swift3String.substring(to: swift3SpaceIndex!)
        print("swift3Substring: \(swift3Substring)")
        
        //Swift4에서 substring
        let swift4SpaceIndex = swift4String.index(of: " ")
        //one sided range를 사용해서 추출한다.
        let swift4Substring = swift4String[..<swift4SpaceIndex!]
        print("swift4Substring: \(swift4Substring)")
        
        
        

    }

실행하면 결과는
filteredSwift3String: Swift 
filteredSwift4String: Swift 
swift3Substring: Swift
swift4Substring: Swift

Swift 4에서 강화된 Set, Dictionary입니다.

    @IBAction func btn4(_ sender: Any) {
        //swift4에서 튜플의 배열로부터 사전구조를 생성하는 방법
        let tupleArray = [("Monday",30), ("Tuesday",25),
            ("Wednesday",27), ("Thursday",20), ("Friday",24),
            ("Saturday",22), ("Sunday",26)]
        //dict의 init(uniqueKeyWithValues:)를 통해서
        //튜플 배열에서 새로운 사전구조를 생성한다.
        let dictionary = Dictionary(uniqueKeysWithValues:
            tupleArray)
        print("dictionary: \(dictionary)")
        
        //아래와 같이 사용할 수 도 있다.
        let keys = ["Monday", "Tuesday", "Wednesday",
            "Thursday", "Friday", "Saturday", "Sunday"]
        let values = [30, 25, 27, 20, 24, 22, 26]
        let newDictionary = Dictionary(uniqueKeysWithValues:
            zip(keys, values))
        print("newDictionary:\(newDictionary)")
        
        //swift3에서 사용하는 nil병합 연산자(??)
        var seasons = ["Spring": 20, "Summer": 30, "Autumn": 10]
        let winterTemperature = seasons["Winter"] ?? 0
        print("winterTemperature: \(winterTemperature)")
        //swift4에서 사용하는 코드
        let winterTemperature2 = seasons["Winter", default: 0]
        print("winterTemperature2: \(winterTemperature2)")
        
        //기존 swift3에서 기존에 있는 키를 통한 업데이트
        if let authumnTemperature = seasons["Autumn"] {
            seasons["Autumn"] = authumnTemperature + 5
        }
        //if let을 사용해서 옵셔널에서 nil을 체크하고 접근했는데
        //이제는 아래와 같이 default value subscript를 통해
        //접근할 수 있다.
        seasons["Autumn", default: 0] += 5
        print(seasons["Autumn"] ?? "")
        
        //map()과 filter()도 swift4에서 새롭게 디자인되었다.
        //swift3에서 사전이 아닌 배열을 리턴했다.
        //let mappedArrayValues = seasons.map{$0.value * 2}
        let mappedArray = seasons.map{key, value in (key, value*2)}
        print("mappedArray: \(mappedArray)")
        //swift4에서는 아래와 같이 사용한다.
        let mappedArray2 = seasons.map{season in
            (season.key, season.value * 2)}
        print("mappedArray2: \(mappedArray2)")
        //좀 더 축약을 하면
        let mappedArrayShorthandVersion = seasons.map{($0.0, $0.1 * 2)}
        print("mappedArrayShorthandVersion: \(mappedArrayShorthandVersion)")
        //아니면 아래와 같이 접근해도 된다.
        let mappedDictionary = seasons.mapValues{$0 * 2}
        print("mappedDictionary:\(mappedDictionary)")
        
        //swift3에서의 필터
        let filteredArray = seasons.filter{$0.value > 15}
        print("filteredArray:\(filteredArray)")
        //swift4에서의 필터
        //완벽하게 동일한 결과이지만 원본과 동일한 구조의 필터링된
        //사전을 리턴한다.
        let filteredDictionary = seasons.filter{$0.value > 15}
        print("filteredDictionary:\(filteredDictionary)")
        
        //swift4는 사전구조를 스플릿할 수 있다.
        let scores = [7, 20, 5, 30, 100, 40, 200]
        let groupedDictionary = Dictionary(grouping: scores,
                                           by:{String($0).count})
        print("groupedDictionary:\(groupedDictionary)")
        //후행 클로저를 사용하면 다음과 같이 작성할 수 있다.
        let groupedDictionaryTrailingClosure =
            Dictionary(grouping: scores)
            {String($0).count}
        print("groupedDictionaryTrailingClosure:\(groupedDictionaryTrailingClosure)")
        
        //swift3에서 초기 용량을 지정해서 사전을 생성하는 코드
        let ratings: Dictionary<String, Int> =
            Dictionary(minimumCapacity:10)
        //swift4에서 처리
        seasons.capacity
        seasons.reserveCapacity(4)
        
        //swift3에서 필터
        let categories: Set<String> = ["Swift", "iOS",
           "macOS", "watchOS", "tvOS"]
        let filteredCategories = categories.filter{$0.hasSuffix("OS")}
        print("filteredCategories: \(filteredCategories)")
        

    }

[1, 5]
[1, 5, 2]
openFirstSlice: [1, 5]
closedFirstSlice: [1, 5, 2]
openSecondHalf: [8, 4, 10]
closedSecondHalf: [8, 4, 10]
closedSecondSlice: [8, 4, 10]
1: 1
2: 5
3: 2
4: 8
5: 4
6: 10
1: 1
2: 5
3: 2
4: 8
5: 4
6: 10
Your favourite number is a positive one.
교환 이후:[5, 1, 2, 8, 4, 10]
dictionary: ["Tuesday": 25, "Saturday": 22, "Sunday": 26, "Friday": 24, "Monday": 30, "Wednesday": 27, "Thursday": 20]
newDictionary:["Tuesday": 25, "Saturday": 22, "Sunday": 26, "Friday": 24, "Monday": 30, "Wednesday": 27, "Thursday": 20]
winterTemperature: 0
winterTemperature2: 0
20
mappedArray: [("Summer", 60), ("Spring", 40), ("Autumn", 40)]
mappedArray2: [("Summer", 60), ("Spring", 40), ("Autumn", 40)]
mappedArrayShorthandVersion: [("Summer", 60), ("Spring", 40), ("Autumn", 40)]
mappedDictionary:["Summer": 60, "Spring": 40, "Autumn": 40]
filteredArray:["Summer": 30, "Spring": 20, "Autumn": 20]
filteredDictionary:["Summer": 30, "Spring": 20, "Autumn": 20]
groupedDictionary:[2: [20, 30, 40], 3: [100, 200], 1: [7, 5]]
groupedDictionaryTrailingClosure:[2: [20, 30, 40], 3: [100, 200], 1: [7, 5]]
filteredCategories: ["watchOS", "iOS", "macOS", "tvOS"]

Swift 4에 새롭게 추가된 prefix, postfix, One Sided Range 연산자 입니다.

    @IBAction func btn3(_ sender: Any) {
        //Swift4에 추가된 prefix와 postfix버전
        //half open range와 closed range operator
        //배열의 절반에 접근하려면 기존에 사용하던 코드
        let array = [1,5,2,8,4,10]
        let halfIndex = (array.count - 1) / 2
        let openFirstHalf = array[0..<halfIndex]
        let closedFirstHalf = array[0...halfIndex]
        print(openFirstHalf)
        print(closedFirstHalf)
        
        //Swift4에서는 시작 인덱스를 명시하지 않고
        //접근할 수 있다.
        let openFirstSlice = array[..<halfIndex]
        let closedFirstSlice = array[...halfIndex]
        print("openFirstSlice: \(openFirstSlice)")
        print("closedFirstSlice: \(closedFirstSlice)")
        
        //range의 시작 인덱스를 삭제할 수 있다. 이유는 모든 배열 요소를
        //halfIndex를 통해 처리하도록 하기 때문이다.
        //기존 Swift3의 코드
        let nextIndex = halfIndex + 1
        let lastIndex = array.count - 1
        let openSecondHalf = array[nextIndex..<lastIndex + 1]
        let closedSecondHalf = array[nextIndex...lastIndex]
        print("openSecondHalf: \(openSecondHalf)")
        print("closedSecondHalf: \(closedSecondHalf)")
        
        //Swift4의 코드
        //half open range와 closed range operator를 사용하면서
        //끝부분을 생략할 수 있다. range의 end index를 생략할 수 있다.
        let closedSecondSlice = array[nextIndex...]
        print("closedSecondSlice: \(closedSecondSlice)")
        
        //one sided range 연산자
        //swift3에서 배열의 인덱스와 값을 출력할 경우
        for (index, value) in array.enumerated() {
            print("\(index + 1): \(value)")
        }
        //swift4에서는 아래와 같이 처리한다.
        //더이상 enumerated()메서드를 호출할 필요가 없고
        //시작 첨자를 1로 변경하고 싶으면 아래와 같이 한다.
        //zip함수를 사용해서 one sided range의 인덱스와 배열의 값을
        //결합한다.
        for (index, value) in zip(1..., array) {
            print("\(index): \(value)")
        }
        
        //One sided range는 switch구문과도 매칭된다.
        let favouriteNumber = 10
        switch favouriteNumber {
        case ..<0:
            print("Your favourite number is a negative one.")
        case 0...:
            print("Your favourite number is a positive one.")
        default:
            break
        }

        //기존 swap함수는 swapAt메서드를 사용하도록 한다.
        var numbers = [1,5,2,8,4,10]
        //swap(&numbers[0], &numbers[1])
        
        numbers.swapAt(0, 1)
        print("교환 이후:\(numbers)")
        

    }


[1, 5]
[1, 5, 2]
openFirstSlice: [1, 5]
closedFirstSlice: [1, 5, 2]
openSecondHalf: [8, 4, 10]
closedSecondHalf: [8, 4, 10]
closedSecondSlice: [8, 4, 10]
1: 1
2: 5
3: 2
4: 8
5: 4
6: 10
1: 1
2: 5
3: 2
4: 8
5: 4
6: 10
Your favourite number is a positive one.
교환 이후:[5, 1, 2, 8, 4, 10]

Swift 4의 JSON 인코더와 디코더 사용 데모입니다.

Xcode 9.0 beta3에서 iOS 11.0에 대한 테스트들입니다.

JSON EncodingDecoding
좀 더 간편하게 JSON포맷을 처리할 수 있게 됨

DemoSwift4로 저장함

아래와 같이 Tutorial클래스 파일을 추가한다.
//
//  Tutorial.swift
//  DemoSwift4
//
//  Created by jong deok Kim on 2017. 7. 17..
//  Copyright © 2017 credu. All rights reserved.
//

import Foundation

class Tutorial: Codable {
    let title: String
    let author: String
    let editor: String
    let type: String
    let publishDate: Date
   
    init(title: String, author: String, editor: String, type: String, publishDate: Date) {
        self.title = title
        self.author = author
        self.editor = editor
        self.type = type
        self.publishDate = publishDate
    }
}


버튼을 3개 추가해서 아래와 같이 코딩한다.
//
//  ViewController.swift
//  DemoSwift4
//
//  Created by jong deok Kim on 2017. 7. 17..
//  Copyright © 2017 credu. All rights reserved.
//

import UIKit

class ViewController: UIViewController {

    @IBAction func btn1(_ sender: Any) {
       
        let tutorial = Tutorial(title: "스위프트4 새로운 ", author: "papasmf", editor: "kim", type: "새로운 기능", publishDate: Date())
        //위의 객체를 바로 JSON포맷으로 인코딩해서 리턴한다.
        let encoder = JSONEncoder()
        do {
            let data = try encoder.encode(tutorial)
            let string = String(data: data, encoding: .utf8)
            print(string ?? "")
       
            let decoder = JSONDecoder()
            let article = try decoder.decode(Tutorial.self, from: data)
            let info = "\(article.title) \(article.author) "
                + "\(article.editor) \(article.type) \(article.publishDate)"
            print(info)
        } catch {
       
        }
       
    }
   
    @IBAction func btn2(_ sender: Any) {
    }
   
    @IBAction func btn3(_ sender: Any) {
    }
   
   
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }


}

결과는 아래와 같이 출력된다.
{"author":"papasmf","title":"스위프트4 새로운 ","publishDate":522004473.74601197,"type":"새로운 기능","editor":"kim"}
스위프트4 새로운 papasmf kim 새로운 기능 2017-07-17 17:14:33 +0000







요즘 많이 들리는 RAG에 대한 멋진 정리가 있어서 공유합니다. ㅎㅎ

 작년에는 ChatGPT가 크게 유행을 했는데 올해는 Gen AI, LLM, 랭체인등이 유행하고 있습니다. ㅎㅎ  RAG라는 단어도 상당히 많이 들리고 있습니다. 멋진 정리의 링크입니다.  https://brunch.co.kr/@ywkim36/146?...