'2017/06'에 해당되는 글 11건

  1. 2017.06.29 상속
  2. 2017.06.27 사진 게시판 API 만들기 [1] (2)
  3. 2017.06.26 프로퍼티 - Property (2)
  4. 2017.06.23 Swift 4 변경사항 (8)
  5. 2017.06.22 클로저 - Closure
  6. 2017.06.19 클래스, 구조체, 열거형 비교
  7. 2017.06.15 열거형 - Enumerations
  8. 2017.06.12 클래스
  9. 2017.06.08 구조체 (2)
  10. 2017.06.05 옵셔널
  11. 2017.06.01 반복문

상속

Swift/기본문법 2017.06.29 11:00

상속

스위프트의 상속은 클래스, 프로토콜 등에서 가능합니다. 열거형, 구조체는 상속이 불가능합니다. 스위프트는 다중상속을 지원하지 않습니다.   

이번 파트에서는 클래스의 상속에 대해서 알아봅니다


소스코드



클래스의 상속과 재정의

상속 문법

class 이름: 상속받을 클래스 이름 {
    /* 구현부 */
}



// 기반 클래스 Person
class Person {
    var name: String = ""
    
    func selfIntroduce() {
        print("저는 \(name)입니다")
    }
    
    // final 키워드를 사용하여 재정의를 방지할 수 있습니다
    final func sayHello() {
        print("hello")
    }
    
    // 타입 메서드
    // 재정의 불가 타입 메서드 - static
    static func typeMethod() {
        print("type method - static")
    }
    
    // 재정의 가능 타입 메서드 - class
    class func classMethod() {
        print("type method - class")
    }
    
    // 재정의 가능한 class 메서드라도 
    // final 키워드를 사용하면 재정의 할 수 없습니다
    // 메서드 앞의 `static`과 `final class`는 똑같은 역할을 합니다
    final class func finalCalssMethod() {
        print("type method - final class")
    }
}

// Person을 상속받는 Student
class Student: Person {
    var major: String = ""
    
    override func selfIntroduce() {
        print("저는 \(name)이고, 전공은 \(major)입니다")
    }
    
    override class func classMethod() {
        print("overriden type method - class")
    }
    
    // static을 사용한 타입 메서드는 재정의 할 수 없습니다
//    override static func typeMethod() {    }
    
    // final 키워드를 사용한 메서드, 프로퍼티는 재정의 할 수 없습니다
//    override func sayHello() {    }
//    override class func finalClassMethod() {    }

}


동작 확인

let yagom: Person = Person()
let hana: Student = Student()

yagom.name = "yagom"
hana.name = "hana"
hana.major = "Swift"

yagom.selfIntroduce()
// 저는 yagom입니다

hana.selfIntroduce()
// 저는 hana이고, 전공은 Swift입니다

Person.classMethod()
// type method - class

Person.typeMethod()
// type method - static

Person.finalCalssMethod()
// type method - final class


Student.classMethod()
// overriden type method - class

Student.typeMethod()
// type method - static

Student.finalCalssMethod()
// type method - final class



관련문서

The Swift Programming Language - Inheritance





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 

저작자 표시 비영리 변경 금지
신고

'Swift > 기본문법' 카테고리의 다른 글

옵셔널 체이닝  (0) 2017.07.06
인스턴스의 생성과 소멸  (0) 2017.07.03
상속  (0) 2017.06.29
프로퍼티 - Property  (2) 2017.06.26
클로저 - Closure  (0) 2017.06.22
클래스, 구조체, 열거형 비교  (0) 2017.06.19
Posted by yagom


Perfect 미니 프로젝트 [1]

1. 프로젝트 개요
2. mongoDB 설치 

3. 패키지 설치 



우분투에 스위프트 설치를 시작으로 이후 두 포스팅에 걸쳐 퍼펙트에 대해 조금 알아보았습니다.



2017/04/03 - [Swift/Perfect] - 우분투(Ubuntu)에 스위프트 설치하기

2017/05/17 - [Swift/Perfect] - Perfect 시작하기

2017/05/24 - [Swift/Perfect] - Perfect 라우팅


이번 부터는 실질적으로 퍼펙트를 사용하여 작은 미니프로젝트를 해보려합니다.

아... 물론 이런 허접한 구성은 실제 서버에서 사용하면 안되지만 간단한 예제로 감만 잡아보는 겁니다. 인증도 없고, 뭐도 없고, 보안도 안되고... 뭐... 암것도 없어요. 그러나 한 번 작은 프로젝트 해보는데에 의의를 가지는 것이니 나중에 삘받으면 하나하나 덧붙여 가면 됩니다.

그저 DB 연결해보고, API로 클라이언트와 핑퐁 해보는 것이 전부이긴 하지만, 그래도 감잡기는 좋을 것 같아요 :)

이 감 말고요... 'ㅁ' 아하핳


프로젝트 개요

간단한 사진게시판을 위한 REST API 서버를 만들어보겠습니다.

API 

HTTP Method 

URI 

사진 게시물 등록 

POST 

/article 

사진 게시물 목록

GET 

사진 게시물 수정 

POST 

/article/{article_id}

사진 게시물 삭제 

DELETE

사진 게시물 정보 가져오기 

GET


사진 게시물 등록

요청(Request)

  • HTTP Method : POST
  • Content-Type: multipart/form-data

 매개변수

자료형 

값의 범위/기본 값 

비고 

 필수여부

image 

binary data

 

이미지 데이터 

user_name

string 

 

사용자 이름 

Y

description

string 

 

이미지 설명 

N

title

string 

 

이미지 제목 

Y


응답(Response)

Key 

자료형 

비고 

필수여부 

article_id 

string 

업로드된 게시물 고유 식별자 


사진 게시물 목록

요청(Request)

  • HTTP Method : GET
  • Content-Type: application/json

 매개변수

자료형 

값의 범위/기본 값 

비고 

 필수여부

page

integer

조회하고자 하는 페이지 번호

user_name

string 


특정 사용자의 게시물만 받아오고자 할 때

N

articles_per_page

integer

1~100 / 10 

각 페이지 당 게시물 수 

N


응답(Response)

Key 

자료형 

비고 

필수여부 

articles 

json object array (string) 

게시물 정보 배열 

Y

articles_per_page

integer

각 페이지 당 게시물 수

 Y

current_page

integer 

전송된 페이지 

total_page

integer 

전체 페이지 수 

Y

articles item object 형태

Key 

자료형 

비고 

필수여부 

image_url

string

이미지 URL

Y

user_name

string

업로드한 사용자 이름 

description

string 

이미지 설명 

title

string 

이미지 제목 

article_id

string 

게시물 고유 식별자


사진 게시물 수정

요청(Request)

  • HTTP Method : POST
  • Content-Type: multipart/form-data

 매개변수

자료형 

값의 범위/기본 값 

비고 

 필수여부

image 

binary data

이전 데이터

이미지 데이터 

N

user_name

string 


사용자 이름이 이전 사용자 이름과 일치하지 않으면 수정에 실패

Y

description

string 

이전 데이터

이미지 설명 

N

title

string 

이전 데이터

이미지 제목 

N


응답(Response)

Key 

자료형 

비고 

필수여부 

article_id 

string 

수정된 게시물 고유 식별자


사진 게시물 삭제

요청(Request)

  • HTTP Method : DELETE
  • Content-Type: application/json

매개변수 없음


응답(Response)

Key 

자료형 

비고 

필수여부 

article_id

string

삭제된 게시물 고유 식별자

Y


사진 게시물 정보 가져오기 

요청(Request)

  • HTTP Method : GET
  • Content-Type: application/json

매개변수 없음


응답(Response)

매개변수 

자료형 

비고 

필수여부 

image_url

string

이미지 URL

Y

user_name

string

업로드한 사용자 이름 

description

string 

이미지 설명 

title

string 

이미지 제목 

article_id

string 

게시물 고유 식별자



모든 응답데이터는 JSON 형식을 사용합니다.

이 정도를 구현해 볼건데요, 데이터베이스가 필요할테니 쓸만한 데이터베이스가 무엇이 있을지 찾아봅니다.


현재(2017년 6월) 퍼펙트에서 공식적으로 제공하는 데이터베이스 커넥터 목록입니다.

  • SQLite
  • MySQL
  • MariaDB
  • PostgreSQL
  • FileMaker
  • MongoDB
  • Working with BSON
  • Apache CouchDB
  • LDAP
  • Kafka
  • Mosquitto
  • ZooKeeper
  • Hadoop

와우... 많네요!! 저는... 몽고디비를 써봐야겠습니다. 



mongoDB 설치

그러려면 먼저 mongoDB를 설치해봐야겠지요.

설치방법은 아래 링크에 친절히 나와있으니 참고하시면 되겠습니다 :)


퍼펙트에서 몽고디비를 사용하기 위해서는 mongo-c 라이브러리를 사용해야합니다. 

먼저, mongo-c 드라이버를 설치합니다. mongo-c와 관련된 설명은 Perfect의 문서를 참고하셔도 좋습니다.


macOS

HomeBrew를 먼저 설치(링크)하신 후, 터미널에서 아래 명령어를 입력합니다.

> brew install mongo-c-driver


ubuntu

아래 명령어를 입력합니다.

> sudo apt-get install libmongoc


패키지 설치

그리고 이제 새로운 프로젝트를 시작하기 위해서 프로젝트를 진행하길 원하는 위치에서 프로젝트 폴더를 생성합니다. 프로젝트 폴더 이름은 ImageBoard라고 하겠습니다.

> mkdir ImageBoard
> cd ImageBoard


그 다음 스위프트 패키지 매니저를 통해 패키지 초기화를 합니다. 스위프트 패키지 매니저는 지난 포스트[우분투(Ubuntu)에 스위프트 설치하기]에서 설치했었죠?

> swift package init --type executable 


swift package init 명령어를 실행 후 폴더에 생성된 Package.swift 파일을 열어서 Perfect 패키지 의존성을 추가합니다.

> vi Package.swift


Package.swift 파일에 아래 코드를 작성합니다.  (우리는 새로운 프로젝트를 만들면서 함께 mongo-c 패키지도 설치할거예요.)

import PackageDescription let package = Package( name: "ImageBoard", targets: [], dependencies: [ .Package(url: "https://github.com/PerfectlySoft/Perfect-HTTPServer.git", versions: Version(0,0,0)..<Version(10,0,0)), .Package(url:"https://github.com/PerfectlySoft/Perfect.git", versions: Version(0,0,0)..<Version(10,0,0)), .Package(url:"https://github.com/PerfectlySoft/Perfect-MongoDB.git", versions: Version(0,0,0)..<Version(10,0,0)) ] )

위 패키지 설명은 Perfect HTTP Sever, Perfect, Perfect MongoDB 커넥터 패키지를 버전 0부터 10까지 중 최신 버전을 가져오도록 합니다. (현재시점으로 모두 2.x.x 버전)


소스를 저장하고 나와서 패키지를 설치합니다.

> swift package update


만약에 맥에서 Xcode 프로젝트를 생성해주고 싶다면

> swift package generate-xcodeproj

해주시면 해당 폴더에 Xcode 프로젝트가 생성됩니다. 그러면 이후 코딩을 Xcode 프로젝트로 진행할 수 있습니다.



이제 프로젝트 준비가 완료되었습니다!

다음부터는 실질적으로 코딩을 해봅니다 :D

다음에 또 만나요~!




by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom

p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 




저작자 표시 비영리 변경 금지
신고

'Swift > Perfect' 카테고리의 다른 글

사진 게시판 API 만들기 [2]  (0) 2017.07.11
사진 게시판 API 만들기 [1]  (2) 2017.06.27
Perfect 라우팅  (0) 2017.05.24
Perfect 시작하기  (0) 2017.05.17
우분투(Ubuntu)에 스위프트 설치하기  (0) 2017.04.03
Posted by yagom

프로퍼티

프로퍼티는 클래스, 구조체, 열거형과 연관된 값입니다. 타입과 관련된 값을 저장할 수도, 연산할 수도 있습니다.


소스코드


프로퍼티의 종류

  • 인스턴스 저장 프로퍼티
  • 타입 저장 프로퍼티
  • 인스턴스 연산 프로퍼티
  • 타입 연산 프로퍼티
  • 지연 저장 프로퍼티

이번 파트에서는 지연 저장 프로퍼티를 제외한 저장 프로퍼티와 연산 프로퍼티에 대해 알아봅니다.


정의와 사용

프로퍼티는 구조체, 클래스, 열거형 내부에 구현할 수 있습니다. 다만 열거형 내부에는 연산 프로퍼티만 구현할 수 있습니다. 연산 프로퍼티는 var로만 선언할 수 있습니다.

연산프로퍼티를 읽기전용으로는 구현할 수 있지만, 쓰기 전용으로는 구현할 수 없습니다. 읽기전용으로 구현하려면 get 블럭만 작성해주면 됩니다. 읽기전용은 get블럭을 생략할 수 있습니다. 읽기, 쓰기 모두 가능하게 하려면 get 블럭과 set블럭을 모두 구현해주면 됩니다.  

set 블럭에서 암시적 매개변수 newValue를 사용할 수 있습니다.

struct Student {
    
    // 인스턴스 저장 프로퍼티
    var name: String = ""
    var `class`: String = "Swift"
    var koreanAge: Int = 0
    
    // 인스턴스 연산 프로퍼티
    var westernAge: Int {
        get {
            return koreanAge - 1
        }
        
        set(inputValue) {
            koreanAge = inputValue + 1
        }
    }
    
    // 타입 저장 프로퍼티
    static var typeDescription: String = "학생"
    
    /*
    // 인스턴스 메서드
    func selfIntroduce() {
        print("저는 \(self.class)반 \(name)입니다")
    }
     */
    
    // 읽기전용 인스턴스 연산 프로퍼티
    // 간단히 위의 selfIntroduce() 메서드를 대체할 수 있습니다
    var selfIntroduction: String {
        get {
            return "저는 \(self.class)반 \(name)입니다"
        }
    }
        
    /*
     // 타입 메서드
     static func selfIntroduce() {
     print("학생타입입니다")
     }
     */
    
    // 읽기전용 타입 연산 프로퍼티
    // 읽기전용에서는 get을 생략할 수 있습니다
    static var selfIntroduction: String {
        return "학생타입입니다"
    }
}

// 타입 연산 프로퍼티 사용
print(Student.selfIntroduction)
// 학생타입입니다

// 인스턴스 생성
var yagom: Student = Student()
yagom.koreanAge = 10

// 인스턴스 저장 프로퍼티 사용
yagom.name = "yagom"
print(yagom.name)
// yagom

// 인스턴스 연산 프로퍼티 사용
print(yagom.selfIntroduction)
// 저는 Swift반 yagom입니다

print("제 한국나이는 \(yagom.koreanAge)살이고, 미쿡나이는 \(yagom.westernAge)살입니다.")
// 제 한국나이는 10살이고, 미쿡나이는 9살입니다.


응용

struct Money {
    var currencyRate: Double = 1100
    var dollar: Double = 0
    var won: Double {
        get {
            return dollar * currencyRate
        }
        set {
            dollar = newValue / currencyRate
        }
    }
}

var moneyInMyPocket = Money()

moneyInMyPocket.won = 11000

print(moneyInMyPocket.won)
// 11000

moneyInMyPocket.dollar = 10

print(moneyInMyPocket.won)
// 11000


지역변수 및 전역변수

저장 프로퍼티와 연산 프로퍼티의 기능은 함수, 메서드, 클로저, 타입 등의 외부에 위치한 지역/전역 변수에도 모두 사용 가능합니다.

var a: Int = 100
var b: Int = 200
var sum: Int {
    return a + b
}

print(sum) // 300


프로퍼티 감시자


프로퍼티 감시자를 사용하면 프로퍼티 값이 변경될 때 원하는 동작을 수행할 수 있습니다. 값이 변경되기 직전에 willSet블럭이, 값이 변경된 직후에 didSet블럭이 호출됩니다. 둘 중 필요한 하나만 구현해 주어도 무관합니다. 변경되려는 값이 기존 값과 똑같더라도 프로퍼티 감시자는 항상 동작합니다. 

willSet 블럭에서 암시적 매개변수 newValue를 사용할 수 있고, didSet 블럭에서 암시적 매개변수 oldValue를 사용할 수 있습니다.

프로퍼티 감시자는 연산 프로퍼티에 사용할 수 없습니다.


소스코드



정의 및 사용

struct Money {
    // 프로퍼티 감시자 사용
    var currencyRate: Double = 1100 {
        willSet(newRate) {
            print("환율이 \(currencyRate)에서 \(newRate)으로 변경될 예정입니다")
        }
        
        didSet(oldRate) {
            print("환율이 \(oldRate)에서 \(currencyRate)으로 변경되었습니다")
        }
    }

    // 프로퍼티 감시자 사용
    var dollar: Double = 0 {
        // willSet의 암시적 매개변수 이름 newValue
        willSet {
            print("\(dollar)달러에서 \(newValue)달러로 변경될 예정입니다")
        }
        
        // didSet의 암시적 매개변수 이름 oldValue
        didSet {
            print("\(oldValue)달러에서 \(dollar)달러로 변경되었습니다")
        }
    }

    // 연산 프로퍼티
    var won: Double {
        get {
            return dollar * currencyRate
        }
        set {
            dollar = newValue / currencyRate
        }
        
        /* 프로퍼티 감시자와 연산 프로퍼티 기능을 동시에 사용할 수 없습니다
        willSet {
            
        }
         */
    }    
}

var moneyInMyPocket: Money = Money()

// 환율이 1100.0에서 1150.0으로 변경될 예정입니다
moneyInMyPocket.currencyRate = 1150
// 환율이 1100.0에서 1150.0으로 변경되었습니다

// 0.0달러에서 10.0달러로 변경될 예정입니다
moneyInMyPocket.dollar = 10
// 0.0달러에서 10.0달러로 변경되었습니다

print(moneyInMyPocket.won)
// 11500.0



관련문서

The Swift Programming Language - Properties





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 


저작자 표시 비영리 변경 금지
신고

'Swift > 기본문법' 카테고리의 다른 글

인스턴스의 생성과 소멸  (0) 2017.07.03
상속  (0) 2017.06.29
프로퍼티 - Property  (2) 2017.06.26
클로저 - Closure  (0) 2017.06.22
클래스, 구조체, 열거형 비교  (0) 2017.06.19
열거형 - Enumerations  (0) 2017.06.15
Posted by yagom

Swift 4 변경사항

Swift 2017.06.23 11:00


오늘의 주제

스위프트 4 추가/변경사항


아, 벌써 스위프트가 4번째 버전이 나오네요! 참으로 빠르게 변합니다. 이제 문법적으로 변경되는 부분이 크게 많지 않아서 서 3 버전과 크게 달라진 문법은 많지 않습니다. 내부적으로 수정되거나 추가된 문법이 많고, 삭제된 부분은 거의 없습니다.

긴 말 필요없이 한 번 무엇이 바뀌었는지 살펴볼까요?

스따뚜~~~~~~~~~~~~


단방향 범위 연산자

이제 범위연산자에서 양 쪽 끝을 모두 신경쓸 필요가 없습니다, 야호! [SE-0172]

var numbers = [1, 2, 3, 4, 5]

// Swift 3
numbers[2..<numbers.endIndex] // [3, 4, 5]
numbers[0...2] // [1, 2, 3]
numbers[0..<2] // [1, 2]

// Swift 4
numbers[2...] // [3, 4, 5]
numbers[...2] // [1, 2, 3]
numbers[..<2] // [1, 2]

numbers = []

// Swift 3
//numbers[0...numbers.endIndex] // out of range - error

// Swift 4
numbers[0...] // []


let number: Int = 100

// Swift 3
switch number {
case Int.min..<0:
    print("negative")
case 0:
    print("zero")
case 1...Int.max:
    print("positive")
default:
    print("unknwon")
}


// Swift 4
switch number {
case ..<0:
    print("negative")
case 0:
    print("zero")
case 1...:
    print("positive")
default:
    print("unknwon")
}


 

String의 많은 변화

Swift 4에서 String은 정말 많은 변화가 있는 부분 중 하나입니다. 그 중 눈에 띌만한 내용을 위주로 정리했습니다. 더 많은 사항은 [String Processing For Swift 4] 문서를 참고해보시기 바랍니다.


String 구조체가 다시 Collection 프로토콜을 따릅니다. [SE-0163]

var greeting: String = "Hello, Swift!"

// Swift 3
greeting.characters.forEach { print($0) }
print(greeting.characters.count) // 13

// Swift 4
greeting.forEach { print($0) }
print(greeting.count) // 13


Unicode 9이 적용되었습니다. [String Processing For Swift 4 - Unicode 9 Conformance]

이전에 문자열 길이 결과가 제각각이었던 유니코드 문자들이 사람이 인지할 수 있는 단위로 세어집니다.

// Swift 3
"😍".characters.count // 1
"🇰🇷".characters.count // 1
"🐻".characters.count // 1
"🙌🏻".characters.count // 2
"🙌🏾".characters.count // 2
"‍‍👨‍👨‍👦".characters.count // 3
"‍‍‍👨‍👨‍👦‍👦".characters.count // 4

// Swift 4
"😍".count // 1
"🇰🇷".count // 1
"🐻".count // 1
"🙌🏻".count // 1
"🙌🏾".count // 1
"‍‍👨‍👨‍👦".count // 1
"‍‍‍👨‍👨‍👦‍👦".count // 1


여러 줄 리터럴 문법이 생겼습니다. [SE-0168]

  • 큰따옴표 세 개를 연결하여 표현하면 여러 줄 문자열을 표현하는 리터럴 문법입니다.   
  • 반드시 """ 다음 줄부터 문자열을 입력해야하며, 문자열 마지막 줄 다음줄에 """로 닫아줘야 합니다.

// Swift 3
greeting = "Hello\nHow are you?\nI'm fine thanks, and you?"

// Swift 4
greeting = """
Hello
How are you?
I'm fine thanks, and you?
"""


Substring 타입과 StringProtocol 프로토콜이 생겼습니다.

기존에 String 타입에 구현되어있던 주요 기능을 StringProtocol에 기본구현 하였습니다.

let subIndex = greeting.index(greeting.startIndex, offsetBy: 4)

// Swift 3
let subGreeting = greeting[greeting.startIndex...subIndex]
print(type(of: subGreeting)) // String

// Swift 4
let subGreeting = greeting[...subIndex]
print(type(of: subGreeting)) // Substring
let stringFromSubstring: String = String(subGreeting)


Character 타입에 unicodeScalars 프로퍼티가 추가되었습니다. [SE-0178]

Swift 3에서는 Character 인스턴스의 유니코드 스칼라 값을 알아내려면 String 타입으로 변환하여야 했지만, 이제는 바로 Character 인스턴스의 unicodeScalars 프로퍼티를 이용해 알아낼 수 있습니다.

let character: Character = ""

// Swift 3
print(String(character).unicodeScalars)

// Swift 4
print(character.unicodeScalars)


DictionarySet

자주 사용하는 콜렉션 타입인 DictionarySet의 기능이 한층 강화되었습니다.  

[SE-0154], [SE-0165]


키와 값의 시퀀스를 통해 새로운 딕셔너리를 생성할 수 있습니다. 또, 키와 값을 기존의 딕셔너리에 병합할 수 있습니다.

let zipSequence = zip("abcdefghijklmnopqrstuvwxyz", 97...)
let asciiTable = Dictionary(uniqueKeysWithValues: zipSequence)
// ["w": 119, "n": 110, "u": 117, "v": 118, "x": 120, "q": 113, ...]

let vegetables = ["tomato", "carrot", "onion", "onion", "carrot", "onion"]
let vegetableZipSequence = zip(vegetables, repeatElement(1, count: Int.max))

var vegetableCounts = Dictionary(vegetableZipSequence, uniquingKeysWith: +)
vegetableCounts.merge([("tomato", 1)], uniquingKeysWith: +)
// ["tomato": 2, "carrot": 2, "onion": 3]


DictionarySetfilter 결과가 이제 Array대신 각각의 원래 타입으로 반환됩니다. 또, 딕셔너리는 mapValues(_:) 메서드를 통해 값이 변형된 새로운 딕셔너리를 만들 수 있습니다.

let vowels: Set<Character> = ["a", "e", "i", "o", "u"]
let asciiVowels = asciiTable.filter({ vowels.contains($0.key) })

// Swift 3
print(type(of: asciiVowels)) // Array<(key : Character, value : Int)>

// Swift 4
print(type(of: asciiVowels)) // Dictionary<Character, Int>
asciiVowels["a"]  // 97
asciiVowels["b"]  // nil

let filteredSet: Set<Character> = vowels.filter{ $0 < "h" }

// Swift 3
print(type(of: filteredSet)) // Array<Character>

// Swift 4
print(type(of: filteredSet)) // Set<Character>

// Swift 3
let strangeMap = asciiTable.map { [$0: "0x" + String($1, radix: 16)] }
print(type(of: strangeMap)) // Array<Dictionary<Character, String>>
// [["u": "0x75"], ["v": "0x76"], ["w": "0x77"], ["x": "0x78"], ["q": "0x71"], ["n": "0x6e"], ...]

// Swift 4
let asciiHexTable = asciiTable.mapValues({ "0x" + String($0, radix: 16) })
// ["w": "0x77", "n": "0x6e", "u": "0x75", "v": "0x76", "x": "0x78", ...]


딕셔너리 서브스크립트 문법이 추가되었습니다. 원하는 키에 해당하는 값이 없으면 nil 대신 기본값을 돌려줍니다. 

기본값이 있다는 것은 값이 항상 존재한다는 의미이므로, 해당 서브스크립트의 반환값은 옵셔널이 아닌 값이라는 뜻입니다. 딕셔너리 옵셔널 전쟁에서 해방될 수도!

let favoriteSubject: [String: String] = ["yagom": "swift", "hana": "communication", "jisu": "swift"]

// Swift 3
type(of: favoriteSubject["minji"]) // Optional<String>

// Swift 4
type(of: favoriteSubject["minji"]) // Optional<String>
type(of: favoriteSubject["minji", default: "unknown"]) // String

var favoriteCount = [String: Int]()

favoriteSubject.forEach { favoriteCount[$0.value, default: 0] += 1 }
print(favoriteCount) // ["swift": 2, "communication": 1]


init(grouping:by:) 이니셜라이저를 통해 특정 조건에 따라 Array 또는 다른 시퀀스를 딕셔너리 형태로 그룹지을 수 있습니다. 그룹 기준값은 딕셔너리의 키가 됩니다.

struct Person: CustomStringConvertible {
    enum Gender {
        case male, female, unknwon
    }
    
    let name: String
    var gender: Gender
    
    var description: String { return name }
}

let yagom = Person(name: "yagom", gender: .male)
let hana = Person(name: "hana", gender: .female)
let jisu = Person(name: "jisu", gender: .unknwon)
let eric = Person(name: "eric", gender: .male)
let mike = Person(name: "mike", gender: .male)

let friends = [yagom, hana, jisu, eric, mike]
let friendsByGender = Dictionary(grouping: friends, by: { $0.gender })
print(type(of: friendsByGender))    // Dictionary<Gender, Array<Person>>
print(friendsByGender)
// [Person.Gender.unknwon: [jisu], Person.Gender.male: [yagom, eric, mike], Person.Gender.female: [hana]]


reserveCapacity(_:) 메서드를 통해 Array 처럼 예약된 공간을 가질 수 있습니다.

var emptyDictionary = [String: String]()
print(emptyDictionary.capacity) // 0
emptyDictionary.reserveCapacity(100)
print(emptyDictionary.capacity) // 192
// 최소 100개의 요소가 들어갈 수 있도록 공간을 확보하기 때문에 꼭 100이지 않을 수 있습니다
emptyDictionary.reserveCapacity(10)
print(emptyDictionary.capacity) // 192
emptyDictionary.reserveCapacity(1000)
print(emptyDictionary.capacity) // 1536


Key path

Cocoa에서 단순한 문자열로 표현하던 key path를 스위프트에서는 정확한 타입(KeyPath 라는 제네릭 클래스) 방식으로 표현합니다. 조금 더 안전한 동적 프로그래밍을 할 수 있지 않을까 기대됩니다. [SE-0161]

  • key path를 통하여 프로퍼티에 접근할 수 있도록 모든 타입에 자동으로 [keyPath:] 서브스크립트 메서드가 추가됩니다.
  • key path는 백슬래시(\)를 통해 표현합니다.

struct Person {
    var name: String
}

struct Stuff {
    var name: String
    var owner: Person
}


var yagom = Person(name: "yagom")
let macbook = Stuff(name: "macbook pro", owner: yagom)

print(type(of: \Person.name)) // WritableKeyPath<Person, String>

var result: Any = macbook[keyPath: \Stuff.name]
print(result) // macbook pro

let keyPath = \Stuff.owner
let nameKeyPath = keyPath.appending(path: \.name)

result = macbook[keyPath: nameKeyPath]
print(result) // yagom

result = macbook[keyPath: \Stuff.owner.name]
print(result) // yagom


프로토콜 혼합 타입

Objective-C 에서 특정 클래스와 프로토콜을 동시에 따르고 있는 타입이라는 의미로 사용되었던 표현이 있습니다. 

SomeClass<SomeProtocol, AnotherProtocol> *name
// SomeProtocol과 AnotherProtocol을 준수하는 SomeClass 타입의 변수 name

이 표현이 이제 스위프트에서도 가능해졌습니다. [SE-0156]

class ClassA { }
class ClassB: ClassA { }
protocol ProtocolA { }
extension ClassB: ProtocolA { }

var someVariable: ClassA & ProtocolA
// someVariable = ClassA()
// 오류발생 : ProtocolA를 충족하지 않음

someVariable = ClassB() // 모든 조건 충족


where 확장

프로토콜과 그 연관 타입에 where 절을 사용하여 타입 제약을 줄 수 있습니다. [SE-0142]

protocol StringRepresentable: RawRepresentable
where RawValue == String { }

protocol RawStringWrapper {
  associatedtype Wrapped: RawRepresentable
    where Wrapper.RawValue == String
}



제네릭 서브스크립트

서브스크립트가 이제 제네릭 매개변수와 반환 타입을 사용할 수 있게 되었습니다. [SE-0148]

struct CustomModel<Key: Hashable, Value> {
    var dictionary: [Key: Value]
    
    subscript<T>(key: Key) -> T? {
        return dictionary[key] as? T
    }
}

let information = CustomModel(dictionary: ["name": "yagom", "age": 100, "height": 183.0])
let name: String? = information["name"] // yagom


Private 접근수준의 변경

기존의 private 접근수준은 같은 파일인 여부와 상관없이 private 요소를 해당 범위를 벗어나면 사용할 수 없었습니다. 대체제로 fileprivate를 사용하였는데, 이는 문제를 야기할 수 있는 가능성을 가지고 있습니다. 같은 파일이라도 접근을 원치 않는 요소가 있는데, extension 등으로 타입을 확장하여 요소를 사용려면 fileprivate로 지정해 주어야 하는 문제가 있었기 때문이죠. 아래 Swift 3의 예를 먼저 보겠습니다.

// Swift 3
struct Person {
    var name: String
    // private로 지정하면 extension에서 접근할 수 없기 때문에 fileprivate로 선언
    fileprivate var age: Int = 0
    init(name: String) {
        self.name = name
    }
}

extension Person {
    mutating func passedYear() {
        self.age += 1
    }
}

var yagom = Person(name: "yagom")
yagom.passedYear()
yagom.age // 접근가능! 원하던 시나리오가 아님!


나이라는 민감한 부분은 숨기고 싶었기 때문에 private로, 어디서든 접근을 막고 싶었지만, 같은 파일의 익스텐션에서 조차 접근할 수 없기 때문에 fileprivate로 접근수준을 지정했습니다. 그 결과, 엉뚱하게 같은 파일의 다른 소스에서도 접근할 수 있게 되었습니다.

// Swift 4

struct Person { var name: String private var age: Int = 0 init(name: String) { self.name = name } } extension Person { mutating func passedYear() { // private라도 같은 파일의 extension에서 접근 가능 self.age += 1 } } var yagom = Person(name: "yagom") yagom.passedYear() // yagom.age // 접근불가

Swift 4에서는 이 문제를 개선하여 같은 파일의 익스텐션에서는 접근할 수 있도록 변경되었습니다.


아카이브와 시리얼라이제이션 / JSON 인코딩

NSCodingNSObject를 손쉽게 사용할 수 있는 클래스 타입을 제외하고, 구조체나 열거타입에서는 아카이빙이 참으로 난해했습니다. 물론 NSObject를 상속받지 않는 스위프트 고유 클래스도 마찬가지였습니다. 그러나 이제 타입이 스스로 어떻게 아카이브하고 시리얼라이즈 할지 정의할 수 있게 되었습니다. 그저 타입과 그 타입의 하위 타입이 모두 Codable 프로토콜을 준수하면 아카이브하고 그것을 풀어낼 수 있도록 할 수 있습니다. 기존에 사용하던 NSKeyedArchiver 클래스도 Codable 프로토콜을 완벽히 지원합니다. Codable과 함께 JSONEncoder, JSONDecoder로 인해 JSON 인코딩과 디코딩이 엄청나게 편해졌습니다!! 으아아아아아아아~!! [SE-0166],  [SE-0167]

struct Person: Codable {
    enum Gender: String, Codable {
        case male, female, unknown
    }
    
    var name: String
    var age: Int
    var gender: Gender
    var friends: [Person]
}

let yagom = Person(name: "yagom", age: 20, gender: .male, friends: [])
let hana = Person(name: "hana", age: 22, gender: .female, friends: [yagom])
let eric = Person(name: "eric", age: 25, gender: .male, friends: [yagom, hana])

var encoder = JSONEncoder()

let jsonData = try encoder.encode(eric)
let jsonString = String(data: jsonData, encoding: .utf8)
print(jsonString) 
// "{\"age\":25,\"gender\":\"male\",\"friends\":[{\"age\":20,\"gender\":\"male\",\"friends\":[],\"name\":\"yagom\"},{\"age\":22,\"gender\":\"female\",\"friends\":[{\"age\":20,\"gender\":\"male\",\"friends\":[],\"name\":\"yagom\"}],\"name\":\"hana\"}],\"name\":\"eric\"}"

let decoder = JSONDecoder()
let decoded: Person = try decoder.decode(Person.self, from: jsonData)
print(decoded.name) // eric


NSNumber 브릿징

예상치 못한 결과를 낼 수 있는 NSNumber 브릿징 결과가 수정되었습니다.

// Swift 3

let numberOne = NSNumber(value: Int64.max)

if numberOne is Int16 {
    print("numberOne == Int16")
} else if numberOne is Int64 {
    print("numberOne == Int64")
} // numberOne == Int16

let numberTwo = NSNumber(value: UInt32(777))
if let value = numberTwo as? Int8 {
    print(value)
} // 9

// Swift 4
let numberOne = NSNumber(value: Int64.max)

if numberOne is Int16 {
    print("numberOne == Int16")
} else if numberOne is Int64 {
    print("numberOne == Int64")
} // numberOne == Int64

let numberTwo = NSNumber(value: UInt32(777))
if let value = numberTwo as? Int8 {
    print(value)
} // 아무 출력 없음


그 외 기타 변경사항

* Core Foundation 타입들은 HashableEquatable 프로토콜을 CFHashCFEqual 함수구현을 통해 준수합니다. Swift 3 모드(Swift 3.2 버전)에서도 적용되는 사항입니다. [SR-2388]

* 암시적인 @objc 선언을 이제 더욱 명확히 표현해 주어야 합니다. [SE-0160]

* raw buffer를 슬라이스 한 결과는 더이상 같은 타입으로 반환되지 않습니다. [SE-0138]

* 재정의(override)가 더 완벽하게 지원됩니다. [SR-1529]

* 제네릭 매개변수를 갖는 서브스크립트를 정의할 수 있습니다. [SE-0148]

* 스위프트 타입 시스템이 이제는 하나의 튜플 전달인자를 가지는 함수와 여러 매개변수를 가지는 함수를 구분합니다. [SE-0110]

* 여러 연산자를 수반한 정수형 상수를 정의하는 C 언어의 매크로의 형태를 더 다양하게 임포트 할 수 있습니다. 

* inout 매개변수를 사용하는 reduce 함수가 추가되었습니다. [SE-0171]

* 컬렉션 타입의 두 요소를 서로 바꿔주는 swapAt(_:_:) 메서드가 추가됐습니다. [SE-0173], [SE-0176]


참고문서

Swift CHANGELOG - Swift 4.0






by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 


저작자 표시 비영리 변경 금지
신고

'Swift' 카테고리의 다른 글

Swift 4 변경사항  (8) 2017.06.23
Posted by yagom

클로저

클로저는 코드의 블럭입니다. 일급시민(first-citizen)으로, 전달인자, 변수, 상수 등으로 저장, 전달이 가능합니다.  
함수는 클로저의 일종으로, `이름이 있는 클로저`라고 생각하면 됩니다.


소스코드


기본 클로저 문법

{ (매개변수 목록) -> 반환타입 in
    실행 코드
}


클로저의 사용

// sum이라는 상수에 클로저를 할당
let sum: (Int, Int) -> Int = { (a: Int, b: Int) in
    return a + b
}

let sumResult: Int = sum(1, 2)
print(sumResult) // 3


함수의 전달인자로서의 클로저

클로저는 주로 함수의 전달인자로 많이 사용됩니다. 함수 내부에서 원하는 코드블럭을 실행할 수 있습니다.

let add: (Int, Int) -> Int
add = { (a: Int, b: Int) in
    return a + b
}

let substract: (Int, Int) -> Int
substract = { (a: Int, b: Int) in
    return a - b
}

let divide: (Int, Int) -> Int
divide = { (a: Int, b: Int) in
    return a / b
}

func calculate(a: Int, b: Int, method: (Int, Int) -> Int) -> Int {
    return method(a, b)
}

var calculated: Int

calculated = calculate(a: 50, b: 10, method: add)

print(calculated) // 60

calculated = calculate(a: 50, b: 10, method: substract)

print(calculated) // 40

calculated = calculate(a: 50, b: 10, method: divide)

print(calculated) // 5

//따로 클로저를 상수/변수에 넣어 전달하지 않고, 
//함수를 호출할 때 클로저를 작성하여 전달할 수도 있습니다.

calculated = calculate(a: 50, b: 10, method: { (left: Int, right: Int) -> Int in
    return left * right
})

print(calculated) // 500



다양한 클로저표현

클로저는 다양한 모습으로 표현될 수 있습니다.

  • 함수의 매개변수 마지막으로 전달되는 클로저는 후행클로저(trailing closure)로 함수 밖에 구현할 수 있습니다. 
  • 컴파일러가 클로저의 타입을 유추할 수 있는 경우 매개변수, 반환 타입을 생략할 수 있습니다.
  • 반환 값이 있는 경우, 암시적으로 클로저의 맨 마지막 줄은 return 키워드를 생략하더라도 반환 값으로 취급합니다.
  • 전달인자의 이름이 굳이 필요없고, 컴파일러가 타입을 유추할 수 있는 경우 축약된 전달인자 이름($0, $1, $2...)을 사용 할 수 있습니다.


소스코드



클로저 매개변수를 갖는 함수 calculate(a:b:method:)와 결과값을 저장할 변수 result를 먼저 선언해둡니다.

func calculate(a: Int, b: Int, method: (Int, Int) -> Int) -> Int {
    return method(a, b)
}

var result: Int


후행 클로저

클로저가 함수의 마지막 전달인자라면 마지막 매개변수 이름을 생략한 후 함수 소괄호 외부에 클로저를 구현할 수 있습니다.

result = calculate(a: 10, b: 10) { (left: Int, right: Int) -> Int in
    return left + right
}

print(result) // 20


반환타입 생략

calculate(a:b:method:) 함수의 method 매개변수는 Int 타입을 반환할 것이라는 사실을 컴파일러도 알기 때문에 굳이 클로저에서 반환타입을 명시해 주지 않아도 됩니다. 

대신 in 키워드는 생략할 수 없습니다.

result = calculate(a: 10, b: 10, method: { (left: Int, right: Int) in
    return left + right
})

print(result) // 20

// 후행클로저와 함께 사용할 수도 있습니다
result = calculate(a: 10, b: 10) { (left: Int, right: Int) in
    return left + right
}

print(result) // 20


단축 인자이름

클로저의 매개변수 이름이 굳이 불필요하다면 단축 인자이름을 활용할 수 있습니다. 단축 인자이름은 클로저의 매개변수의 순서대로 $0, $1, $2... 처럼 표현합니다.

result = calculate(a: 10, b: 10, method: {
    return $0 + $1
})

print(result) // 20


// 당연히 후행 클로저와 함께 사용할 수 있습니다
result = calculate(a: 10, b: 10) {
    return $0 + $1
}

print(result) // 20


암시적 반환 표현

클로저가 반환하는 값이 있다면 클로저의 마지막 줄의 결과값은 암시적으로 반환값으로 취급합니다.

result = calculate(a: 10, b: 10) { $0 + $1 } print(result) // 20 // 간결하게 한 줄로 표현해 줄 수도 있습니다 result = calculate(a: 10, b: 10) { $0 + $1 } print(result) // 20


축약 전과 후 비교

//축약 전
result = calculate(a: 10, b: 10, method: { (left: Int, right: Int) -> Int in
    return left + right
})

//축약 후
result = calculate(a: 10, b: 10) { $0 + $1 }

print(result) // 20


관련문서

* The Swift Programming Language - Closures

* 일급시민(first-citizen)





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 


저작자 표시 비영리 변경 금지
신고

'Swift > 기본문법' 카테고리의 다른 글

상속  (0) 2017.06.29
프로퍼티 - Property  (2) 2017.06.26
클로저 - Closure  (0) 2017.06.22
클래스, 구조체, 열거형 비교  (0) 2017.06.19
열거형 - Enumerations  (0) 2017.06.15
클래스  (0) 2017.06.12
Posted by yagom

Class vs Struct/Enum

소스코드


열거형과 구조체는 값 타입이며, 클래스는 참조 타입이라는 것이 가장 큰 차이입니다. 또한, 클래스는 상속이 가능하지만 구조체와 열거형은 상속이 불가능합니다.

struct ValueType {
    var property = 1
}

class ReferenceType {
    var property = 1
}

// 첫 번째 구조체 인스턴스
let firstStructInstance = ValueType()
// 두 번째 구조체 인스턴스에 첫 번째 인스턴스 값 복사
var secondStructInstance = firstStructInstance
// 두 번째 구조체 인스턴스 프로퍼티 값 수정
secondStructInstance.property = 2

// 두 번째 구조체 인스턴스는 첫 번째 구조체를 똑같이 복사한 
// 별도의 인스턴스이기 때문에 
// 두 번째 구조체 인스턴스의 프로퍼티 값을 변경해도
// 첫 번째 구조체 인스턴스의 프로퍼티 값에는 영향이 없음
print("first struct instance property : \(firstStructInstance.property)")    // 1
print("second struct instance property : \(secondStructInstance.property)")  // 2


// 클래스 인스턴스 생성 후 첫 번째 참조 생성
let firstClassReference = ReferenceType()
// 두 번째 참조 변수에 첫 번째 참조 할당
let secondClassReference = firstClassReference
secondClassReference.property = 2

// 두 번째 클래스 참조는 첫 번째 클래스 인스턴스를 참조하기 때문에
// 두 번째 참조를 통해 인스턴스의 프로퍼티 값을 변경하면
// 첫 번째 클래스 인스턴스의 프로퍼티 값을 변경하게 됨
print("first class reference property : \(firstClassReference.property)")    // 2
print("second class reference property : \(secondClassReference.property)")  // 2


관련문서

The Swift Programming Language - Enumerations

The Swift Programming Language - Classes and Structures





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 


저작자 표시 비영리 변경 금지
신고

'Swift > 기본문법' 카테고리의 다른 글

프로퍼티 - Property  (2) 2017.06.26
클로저 - Closure  (0) 2017.06.22
클래스, 구조체, 열거형 비교  (0) 2017.06.19
열거형 - Enumerations  (0) 2017.06.15
클래스  (0) 2017.06.12
구조체  (2) 2017.06.08
Posted by yagom

열거형


소스코드



정의 문법

스위프트의 열거형은 다른 언어의 열거형과는 많이 다릅니다. 잘 살펴보아야 할 스위프트의 기능 중 하나입니다.

  • enum은 타입이므로 대문자 카멜케이스를 사용하여 이름을 정의합니다
  • 각 case는 소문자 카멜케이스로 정의합니다
  • 각 case는 그 자체가 고유의 값입니다
  • 각 케이스는 한 줄에 개별로도, 한 줄에 여러개도 정의할 수 있습니다

enum 이름 {
	case 이름1
	case 이름2
	case 이름3, 이름4, 이름5
	// ...
}


열거형 사용

enum Weekday {
    case mon
    case tue
    case wed
    case thu, fri, sat, sun
}

// 열거형 타입과 케이스를 모두 사용하여도 됩니다
var day: Weekday = Weekday.mon

// 타입이 명확하다면 .케이스 처럼 표현해도 무방합니다
day = .tue

print(day) // tue

// switch의 비교값에 열거형 타입이 위치할 때
// 모든 열거형 케이스를 포함한다면
// default를 작성할 필요가 없습니다
switch day {
case .mon, .tue, .wed, .thu:
    print("평일입니다")
case Weekday.fri:
    print("불금 파티!!")
case .sat, .sun:
    print("신나는 주말!!")
}


원시값(Raw value)

C 언어의 enum처럼 정수값을 가질 수도 있습니다. rawValue를 사용하면 됩니다. 

case별로 각각 다른 값을 가져야합니다.

enum Fruit: Int {
    case apple = 0
    case grape = 1
    case peach
    
    // mango와 apple의 원시값이 같으므로 
    // mango 케이스의 원시값을 0으로 정의할 수 없습니다
//    case mango = 0
}

print("Fruit.peach.rawValue == \(Fruit.peach.rawValue)")
// Fruit.peach.rawValue == 2


정수 타입 뿐만 아니라 Hashable 프로토콜을 따르는 모든 타입이 원시값의 타입으로 지정될 수 있습니다.

enum School: String {
    case elementary = "초등"
    case middle = "중등"
    case high = "고등"
    case university
}

print("School.middle.rawValue == \(School.middle.rawValue)")
// School.middle.rawValue == 중등

// 열거형의 원시값 타입이 String일 때, 원시값이 지정되지 않았다면
// case의 이름을 원시값으로 사용합니다
print("School.university.rawValue == \(School.university.rawValue)")
// School.middle.rawValue == university


원시값을 통한 초기화

rawValue를 통해 초기화 할 수 있습니다. rawValuecase에 해당하지 않을 수 있으므로 rawValue를 통해 초기화 한 인스턴스는 옵셔널 타입입니다.

// rawValue를 통해 초기화 한 열거형 값은 옵셔널 타입이므로 Fruit 타입이 아닙니다
//let apple: Fruit = Fruit(rawValue: 0)
let apple: Fruit? = Fruit(rawValue: 0)

// if let 구문을 사용하면 rawValue에 해당하는 케이스를 곧바로 사용할 수 있습니다
if let orange: Fruit = Fruit(rawValue: 5) {
    print("rawValue 5에 해당하는 케이스는 \(orange)입니다")
} else {
    print("rawValue 5에 해당하는 케이스가 없습니다")
} // rawValue 5에 해당하는 케이스가 없습니다


메서드

스위프트의 열거형에는 메서드도 추가할 수 있습니다.

enum Month {
    case dec, jan, feb
    case mar, apr, may
    case jun, jul, aug
    case sep, oct, nov
    
    func printMessage() {
        switch self {
        case .mar, .apr, .may:
            print("따스한 봄~")
        case .jun, .jul, .aug:
            print("여름 더워요~")
        case .sep, .oct, .nov:
            print("가을은 독서의 계절!")
        case .dec, .jan, .feb:
            print("추운 겨울입니다")
        }
    }
}

Month.mar.printMessage()


관련문서

The Swift Programming Language - Enumerations





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 

저작자 표시 비영리 변경 금지
신고

'Swift > 기본문법' 카테고리의 다른 글

클로저 - Closure  (0) 2017.06.22
클래스, 구조체, 열거형 비교  (0) 2017.06.19
열거형 - Enumerations  (0) 2017.06.15
클래스  (0) 2017.06.12
구조체  (2) 2017.06.08
옵셔널  (0) 2017.06.05
Posted by yagom

클래스

Swift/기본문법 2017.06.12 11:00

클래스


소스코드


정의 문법

클래스는 참조 타입입니다. 타입이름은 대문자 카멜케이스를 사용하여 정의합니다.

class 이름 {
	/* 구현부 */
}


프로퍼티 및 메서드 구현

클래스의 타입 메서드는 두 종류가 있습니다. 상속 후 재정의가 가능한 class 타입메서드, 상속 후 재정의가 불가능한 static 타입메서드가 있습니다. 자세한 내용은 상속 부분에서 다시 다룹니다.

class Sample {
    // 가변 프로퍼티
    var mutableProperty: Int = 100 

    // 불변 프로퍼티
    let immutableProperty: Int = 100 
    
    // 타입 프로퍼티
    static var typeProperty: Int = 100 
    
    // 인스턴스 메서드
    func instanceMethod() {
        print("instance method")
    }
    
    // 타입 메서드
    // 재정의 불가 타입 메서드 - static
    static func typeMethod() {
        print("type method - static")
    }
    
    // 재정의 가능 타입 메서드 - class
    class func classMethod() {
        print("type method - class")
    }
}


클래스 사용

// 인스턴스 생성 - 참조정보 수정 가능
var mutableReference: Sample = Sample()

mutableReference.mutableProperty = 200

// 불변 프로퍼티는 인스턴스 생성 후 수정할 수 없습니다
// 컴파일 오류 발생
//mutableReference.immutableProperty = 200


// 인스턴스 생성 - 참조정보 수정 불가
let immutableReference: Sample = Sample()

// 클래스의 인스턴스는 참조 타입이므로 let으로 선언되었더라도 인스턴스 프로퍼티의 값 변경이 가능합니다
immutableReference.mutableProperty = 200

// 다만 참조정보를 변경할 수는 없습니다
// 컴파일 오류 발생
//immutableReference = mutableReference

// 참조 타입이라도 불변 인스턴스는 
// 인스턴스 생성 후에 수정할 수 없습니다
// 컴파일 오류 발생
//immutableReference.immutableProperty = 200


// 타입 프로퍼티 및 메서드
Sample.typeProperty = 300
Sample.typeMethod() // type method

// 인스턴스에서는 타입 프로퍼티나 타입 메서드를
// 사용할 수 없습니다
// 컴파일 오류 발생
//mutableReference.typeProperty = 400
//mutableReference.typeMethod()


학생 클래스 만들어보기

class Student {
	// 가변 프로퍼티
    var name: String = "unknown"

    // 키워드도 `로 묶어주면 이름으로 사용할 수 있습니다
    var `class`: String = "Swift"
    
    // 타입 메서드
    class func selfIntroduce() {
        print("학생타입입니다")
    }
    
    // 인스턴스 메서드
    // self는 인스턴스 자신을 지칭하며, 몇몇 경우를 제외하고 사용은 선택사항입니다
    func selfIntroduce() {
        print("저는 \(self.class)반 \(name)입니다")
    }
}

// 타입 메서드 사용
Student.selfIntroduce() // 학생타입입니다

// 인스턴스 생성
var yagom: Student = Student()
yagom.name = "yagom"
yagom.class = "스위프트"
yagom.selfIntroduce()   // 저는 스위프트반 yagom입니다

// 인스턴스 생성
let jina: Student = Student()
jina.name = "jina"
jina.selfIntroduce() // 저는 Swift반 jina입니다




관련문서

The Swift Programming Language - Classes and Structures





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 

저작자 표시 비영리 변경 금지
신고

'Swift > 기본문법' 카테고리의 다른 글

클래스, 구조체, 열거형 비교  (0) 2017.06.19
열거형 - Enumerations  (0) 2017.06.15
클래스  (0) 2017.06.12
구조체  (2) 2017.06.08
옵셔널  (0) 2017.06.05
반복문  (0) 2017.06.01
Posted by yagom

구조체

Swift/기본문법 2017.06.08 11:00

구조체


소스코드



정의 문법

스위프트 대부분의 타입은 구조체로 이루어져 있습니다.
구조체는 값 타입입니다.
타입이름은 대문자 카멜케이스를 사용하여 정의합니다.

struct 이름 {
	/* 구현부 */
}


프로퍼티 및 메서드 구현

struct Sample {
	// 가변 프로퍼티
    var mutableProperty: Int = 100 
    
    // 불변 프로퍼티
    let immutableProperty: Int = 100 
    
    // 타입 프로퍼티
    static var typeProperty: Int = 100 
    
    // 인스턴스 메서드
    func instanceMethod() {
        print("instance method")
    }
    
    // 타입 메서드
    static func typeMethod() {
        print("type method")
    }
}


구조체 사용

// 가변 인스턴스 생성
var mutable: Sample = Sample()

mutable.mutableProperty = 200

// 불변 프로퍼티는 인스턴스 생성 후 수정할 수 없습니다
// 컴파일 오류 발생
//mutable.immutableProperty = 200

// 불변 인스턴스
let immutable: Sample = Sample()

// 불변 인스턴스는 아무리 가변 프로퍼티라도
// 인스턴스 생성 후에 수정할 수 없습니다
// 컴파일 오류 발생
//immutable.mutableProperty = 200
//immutable.immutableProperty = 200


// 타입 프로퍼티 및 메서드
Sample.typeProperty = 300
Sample.typeMethod() // type method

// 인스턴스에서는 타입 프로퍼티나 타입 메서드를
// 사용할 수 없습니다
// 컴파일 오류 발생
//mutable.typeProperty = 400
//mutable.typeMethod()


학생 구조체 만들어보기

struct Student {
	// 가변 프로퍼티
    var name: String = "unknown"

    // 키워드도 `로 묶어주면 이름으로 사용할 수 있습니다
    var `class`: String = "Swift"
    
    // 타입 메서드
    static func selfIntroduce() {
        print("학생타입입니다")
    }
    
    // 인스턴스 메서드
    // self는 인스턴스 자신을 지칭하며, 몇몇 경우를 제외하고 사용은 선택사항입니다
    func selfIntroduce() {
        print("저는 \(self.class)반 \(name)입니다")
    }
}

// 타입 메서드 사용
Student.selfIntroduce() // 학생타입입니다

// 가변 인스턴스 생성
var yagom: Student = Student()
yagom.name = "yagom"
yagom.class = "스위프트"
yagom.selfIntroduce()   // 저는 스위프트반 yagom입니다

// 불변 인스턴스 생성
let jina: Student = Student()

// 불변 인스턴스이므로 프로퍼티 값 변경 불가
// 컴파일 오류 발생
//jina.name = "jina"
jina.selfIntroduce() // 저는 Swift반 unknown입니다


관련문서

The Swift Programming Language - Classes and Structures





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 

저작자 표시 비영리 변경 금지
신고

'Swift > 기본문법' 카테고리의 다른 글

열거형 - Enumerations  (0) 2017.06.15
클래스  (0) 2017.06.12
구조체  (2) 2017.06.08
옵셔널  (0) 2017.06.05
반복문  (0) 2017.06.01
조건문  (0) 2017.05.29
Posted by yagom

옵셔널

Swift/기본문법 2017.06.05 11:00

옵셔널


소스코드

학습자료


옵셔널 값 추출


소스코드

학습자료




관련문서

The Swift Programming Language - The Basics





by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 


저작자 표시 비영리 변경 금지
신고

'Swift > 기본문법' 카테고리의 다른 글

클래스  (0) 2017.06.12
구조체  (2) 2017.06.08
옵셔널  (0) 2017.06.05
반복문  (0) 2017.06.01
조건문  (0) 2017.05.29
함수  (2) 2017.05.25
Posted by yagom

반복문

Swift/기본문법 2017.06.01 11:00

반복문

  • for-in
  • while
  • repeat-while

소스코드


for-in 구문

기존 언어의 for-each 구문과 유사합니다. Dictionary의 경우 이터레이션 아이템으로 튜플이 들어옵니다. 튜플에 관해서는 Swift Language Guide의 Tuples 부분을 참고하면 되겠습니다.


for-in 구문의 기본 형태

for item in items {
    /* 실행 구문 */
}

for-in 구문의 사용

var integers = [1, 2, 3]
let people = ["yagom": 10, "eric": 15, "mike": 12]

for integer in integers {
    print(integer)
}

// Dictionary의 item은 key와 value로 구성된 튜플 타입입니다
for (name, age) in people {
    print("\(name): \(age)")
}

while 구문

while 구문의 기본 형태

while 조건 {
    /* 실행 구문 */
}


while 구문의 사용

while integers.count > 1 {
    integers.removeLast()
}


repeat-while 구문

기존 언어의 do-while 구문과 형태 및 동작이 유사합니다

repeat-while 구문의 기본 형태

repeat {
    /* 실행 구문 */
} while 조건


while 구문의 사용

repeat {
    integers.removeLast()
} while integers.count > 0


관련문서

The Swift Programming Language - Control Flow







by yagom

facebook : http://www.facebook.com/yagomSoft

facebook group : https://www.facebook.com/groups/yagom/


p.s 제 포스팅을 RSS 피드로 받아보실 수 있습니다.

RSS Feed 받기   


↓↓↓ 블로거에게 공감은 큰 힘이 됩니다 ↓↓↓ 

저작자 표시 비영리 변경 금지
신고

'Swift > 기본문법' 카테고리의 다른 글

구조체  (2) 2017.06.08
옵셔널  (0) 2017.06.05
반복문  (0) 2017.06.01
조건문  (0) 2017.05.29
함수  (2) 2017.05.25
컬렉션 타입  (0) 2017.05.22
Posted by yagom


티스토리 툴바