Skip to content

Commit

Permalink
initial
Browse files Browse the repository at this point in the history
  • Loading branch information
Hyunsok Oh authored and Hyunsok Oh committed Jun 15, 2014
1 parent 0d75449 commit c40108a
Show file tree
Hide file tree
Showing 26 changed files with 3,330 additions and 0 deletions.
138 changes: 138 additions & 0 deletions [스위프트 대충보기] 0. 기본.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,138 @@
---
layout: post
title: [스위프트 대충보기] 0. 기본
tags:
-스위프트
-swift
-상수
-let
-변수
-var
-튜플
-tuple
-옵션
-option
-타입안정성
---

# [스위프트 대충보기] 0. 기본

애플에서 스위프트를 발표하면서 관심이 늘고 있다. 애플의 스위프트 가이드를 정리해 본다.

## 상수, 변수 선언

- 상수: let 상수이름 = 값 (굳이 상수라고 이름 붙인걸 보면 기존 코더들을 배려한 것 같음)

- 변수: var 변수이름 = 값

- 여러 선언을 ,로 구분해 한줄에 가능: var x=0.0, y=1, z=10

- 타입지정(타입 애노테이션): 콜론(:) 다음에 타입을 씀. 스위프트난 강타입 언어이지만, 타입 추론을 사용하기 때문에 타입을 직접 쓸 일은 많지 않을 것임

- 이름에는 유니코드 문자 사용 가능. 다만 수학기호, private(또는 잘못된) 유니코드 포인트, 선긋기/박스그리기 문자는 사용할 수 없음. 이름은 숫자로 시작할 수 없음.

## 타입 안전성

- 변수(상수포함)에는 해당 변수 타입에 맞는 값만 대입 가능

- 상수 정의문이 아닌 곳에서 상수를 변경하려고 값을 대입하면 컴파일 오류

- 타입 안전성(type safety) : 스위프트는 타입 안전한 언어. 모든 이름에는 타입이 붙고, 타입 체크를 통과해야 함

- 타입 추론(type inference) : 컴파일러가 각 이름의 사용을 보고 타입을 추론해 부여함. 특별한 경우가 아니면 타입을 직접 표기할 필요가 없음

## 출력

- 콘솔 출력: println사용

## 코멘트

- 한줄 코멘트: // 부터 줄 끝까지

- 여러줄 코멘트: /* 부터 */ 까지. 코멘트 내에 코멘트 내포 가능(당빠 큰 코드블럭 comment out위해 만든 기능)

## 세미콜론

- 세미콜론: 여러 명령을 한 줄에 쓸 때만 ;로 각 명령을 구분

## 기본타입

- 정수: UInt8, Int32 등 크기와 부호 여부에 따라 8, 16, 32, 64비트 정수가 있음

- 정수의 한계값들: UInt8.min, UInt8.max

- Int/UInt : 32비트 머신에서는 Int32/UInt32 64비트 머신에서는 Int64/UInt64 (! 이건 좀 맘에 안드는데 ㅋㅋ)

- 부동소수점수: 3.14159, 0.1, -273.15, 1e18, -1E-9 : Double, Float

- 불린(Boolean): 타입 이름은 Bool, 상수는 true/false

- C와 달리 불린 타입을 써야할 자리에 다른 정수 타입을 쓰면 안됨

## 리터럴

- 10진 정수 리터럴: 접두사 없는 10진수

- 16진 정수 리터럴: 0x 다음에 16진수

- 8진 정수 리터럴: 0o 다음에 8진수

- 2진 정수 리터럴 : 0b 다음에 2진수

- 10진 부동소수 리터럴: 1.2312e12 = 1.2312 * power(10,12)

- 16진 부동소수 리터럴: 0xF.DCp-2 = 0xF.DC * power(2,-2)

- 가독성을 위해 수 리터럴의 중간에 _를 넣어서 자릿수 표시하거나 앞에 0으로 패딩 가능: 000123.456, 1_000_000

- 기본적으로 크기가 맞지 않은 수 리터럴을 대입하는 것은 컴파일 오류. let x:UInt8 = -1, var x:Int8 = 257

## 기본 타입간의 변환

- 명시적으로 타입 변환: UInt16(1) 등 타입이름(변환대상) 형태의 (팩토리) 메서드 사용

- 정수 -> 부동소수 변환도 물론 명시적으로 해야 함

- 부동소수 -> 정수 변환도 명시적으로 해야 함. 항상 truncate(소숫점 잘라냄-0쪽으로 보내기. 반올림이나 내림이 아님)

- 여러 타입의 수 리터럴간에는 바로 더할 수 있음(0.123+1230 ???)

## 다른 기본 타입

- 타입 별명(type alias) : typealias AudioSample = UInt16

- 튜플 : (1,2,3)

- 튜플 해체(decompose) : let (status, message) = http404Error

- _를 사용해 관심없는 쪽은 제외할 수 있음 : let (status, _) = http404Error

- .0, .1(0베이스. 1베이스가 아님!)을 사용해 튜플의 원소 액세스 가능: let status = http404Error.0

- 이름붙은 튜플(named tuple): let http200Status = (status:200, message:"OK")

- 이름붙은 튜플의 원소는 해당 이름을 사용해 액세스가능:

`println("status = \(http200Status.status)")`

- 튜플의 타입은 (Int, String) 처럼 각 원소의 타입을 ,로 분리하고 ()로 둘러쌈. 함수에서 튜플을 반환할 수 있음.

- 옵션(optional) : 어떤 식별자에 값이 있거나 없을 수 있는 경우를 표현. 예: let intValue = possibleNumber.toInt() 하면 수로 변환 가능하면 수가, 아니면 아무것도 아니므로 Int? (Int 옵션형)를 반환

- 값이 있는지 여부는 if로 체크:

`if intValue { println("\(intValue!)") } else { println("x됐당!")}`

- 값을 벗겨내는건 !를 뒤에 붙여서 가져옴. 만약 값이 없는데 !를 사용하면 런타임 오류

- 옵션 바인딩(optional binding) : if let 상수이름 = 옵션값이름 { ... } : 옵션에 값이 있는 경우에만 "상수이름"에 옵션에 들어있는 값을 넣어줌.

- nil : 옵션 타입의 변수를 값이 없는 상태로 설정하고 싶을 때 사용. var code:Int? = 404; code = nil

- 옵션 타입 변수를 선언하고 값을 초기화하지 않으면 자동으로 nil로 초기화: var code:Int? // code는 nil

- 암시적으로 벗겨낸 옵션(implicitly unwrapped optional): 타입? 대신 타입!로 선언하면 !로 벗겨내지 않고 옵션에 저장한 값을 사용 가능. 물론 이렇게 선언한 변수를 사용하는데, 옵션 내부에 값이 없으면 런타임 오류 발생함. 암.벗.옵을 그냥 옵션이 필요한 자리에 사용하는건 아무 문제 없음

## 기타

- 단언문(assertion) : assert(age >= 0, "나이는 0보다 작을 수 없음")
71 changes: 71 additions & 0 deletions [스위프트 대충보기] 10. 첨자(subscript).md
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
---
layout: post
title: [스위프트 대충보기] 10.첨자(subscript)
tags: 스위프트, swift, 첨자, subscript, 첨자 오버로딩, subscript overloading
---
# [스위프트 대충보기] 10.첨자(subscript)

## 첨자?

- 클래스, 구조체, 열거형 안에 첨자를 정의할 수 있음

- 첨자: `someArray[index]`와 같이 `[]`사이에 인덱스를 넣어서 인스턴스 정보를 액세스하는 연산

## 첨자 문법

- `subscript(입력 파라미터들) -> 반환타입 {} `

subscript(index: Int) -> Int {
get {
// 적절한 값 반환
}
set(newValue) {
// 적절하게 설정
}
}

- 읽기전용 첨자인 경우 get을 생략하고, 첨자 본문에 바로 코드를 적는다

subscript(index: Int) -> Int {
// 적절한 값 반환
}

## 첨자를 어디에 쓸까?

- 컬렉션 원소 액세스: 딕셔너리나 배열을 생각해 볼것

- 원한다면 다른 목적으로도 사용가능(예제는 없음)

## 선택 사항

- 첨자에서 가변길이 파라미터를 쓸 수 있고, var 파라미터도 쓸 수 있음

- inout 파라미터는 쓸 수 없고, 파라미터의 디폴트 값도 지정할 수 없음

- 한 클/구/열(귀찮아서 앞으론 이렇게...) 안에 필요한 만큼 첨자를 넣을 수 있음: subscript overloading

- 파라미터를 2개 이상 받을 수도 있음

struct Matrix {
let rows: Int, columns: Int
var grid: Double[]
init(rows: Int, columns: Int) {
self.rows = rows
self.columns = columns
grid = Array(count: rows * columns, repeatedValue: 0.0)
}
func indexIsValidForRow(row: Int, column: Int) -> Bool {
return row >= 0 && row < rows && column >= 0 && column < columns
}
subscript(row: Int, column: Int) -> Double {
get {
assert(indexIsValidForRow(row, column: column), "Index out of range")
return grid[(row * columns) + column]
}
set {
assert(indexIsValidForRow(row, column: column), "Index out of range")
grid[(row * columns) + column] = newValue
}
}
}

118 changes: 118 additions & 0 deletions [스위프트 대충보기] 3. 컬렉션타입.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,118 @@
---
layout: post
title: [스위프트 대충보기] 3. 컬렉션타입
tags: 스위프트, swift, 배열, 딕셔너리, 맵, array, dictionary, map
---
# [스위프트 대충보기] 3. 컬렉션타입

## 기본 소개

- 배열(array)과 딕셔너리(dictionary)라는 두 컬렉션 제공(두개만? 아님! generic collection을 지원함. 배열과 딕셔너리도 역시 그 일부임)

- 배열: 같은 타입의 원소를 저장하는 순서가 있는(ordered) 컬렉션

- 딕셔너리: 키(key)와 값(value)의 대응 관계(association)를 순서 없이 저장한 컬렉션. 키는 한 딕셔너리 안에서 유일함.

## 배열

- 배열은 `NSArray``NSMutableArray` 클래스와 다름(원소 타입이 있다는 점에서)

- 배열 타입은 `Array<SomeType>`이라고 쓰나, 짧게 `SomeType[]`이라고도 쓸 수 있음

- 배열 리터럴: [원소1,원소2,...] 예: `let x = [1,2,3,4,5]`

### 배열 연산

- 배열 참조: `x[0]` 0부터 인덱스 시작

- 원소갯수: `x.count`

- 빈 배열여부 확인: `x.isEmpty`

- 원소추가: `x.append`

- 배열 붙이기: `x += [6,7,8]`

- 원소변경: `x[0] = 0`

- 원소변경(범위지정): `x[0...2] = [10,11]` (3개의 원소를 2개로 대치했으므로 길이가 1 줄어듦)

- 변경이나 범위지정은 기존 인덱스 범위를 넘어서는 부분에 무언가를 넣는 용도로는 사용 불가. 예: x.count가 5인 배열에 x[5] = 10이라고 대입 불가.

- 원소 삽입: `x.insert(0, atIndex: 0)`

- 원소 삭제: `x.removeAtIndex(1)`

- 마지막 원소 삭제: `x.removeLast`

- 배열 이터레이션: `for i in x { ... }`

- 배열 이터레이션(인덱스까지):

// global enumerate 함수 사용
for (index, value) in enumerate(x) { ... }

- 배열 생성: `var foo = Int[]()`

- 배열을 비우려면, `x = []` 라고 해서 비울 수 있음(길이가 0인 배열이 됨. 타입은 그대로)

- 같은 원소를 반복해 초기화: `var threeDoubles = Double[](count: 3, repeatedValue: 0.0)`

- 배열 concatenation : `+` 사용. `arr1 + arr2`

## 딕셔너리

- 딕셔너리 : 역시 `NSDictionary`, `NSMutableDictionary` 와 달리 키, 값의 타입을 지정해야만 함

- 딕셔너리 타입은 `Dictionary<KeyType, ValueType>`

- `KeyType`은 해시가능한 타입이어야 함. 예: 기본타입들(`String`, `Int`, `Double`, `Bool`), 열거형(enumuration type)...

- 딕셔너리 리터럴: `[ k1: v1, ..., kn: vn]`

### 딕셔너리 연산

- 딕셔너리 원소갯수: `x.count`

- 딕셔너리 원소 추가(변경) 1: `x[newKey] = newValue`

- 딕셔너리 원소 추가(변경) 2: `x.updateValue(newValue, forKey: oldKey)`
- 옛날 값을 `ValueType?` 타입(옵션타입임!)으로 반환(즉, 없었다면 `null`이고, 옛날 값이 있었다면 반환값 뒤에 !를 붙여서 원소를 찾거나 `if let v = ... ` 바인딩으로 원소를 찾아 처리 가능)

- 딕셔너리 검색: `x[keyVal]` : 역시 `ValueType?` 타입임

- 딕셔너리 원소삭제 1: `x[keyVal] = nil`

- 딕셔너리 원소삭제 2: `x.removeValueForKey(kevVal)`

- 역시 기존 값을 `ValueType?` 타입으로 리턴함

- 이터레이션: `for (key, value) in dict { ... }`

- 키만 이터레이션: `for key in dict.keys { ... }`

- 값만 이터레이션: `for value in dict.values { ... }`

- 키만 배열로 가져오기: `Array(dict.keys)`

- 값만 배열로 가져오기: `Array(dict.values)`

- 주의: 이터레이션시 순서는 정해져 있지 않음

- 빈 딕셔너리 생성: `Dictionary<Int, String>()`

- 기존 딕셔너리 모든 원소 삭제: `namesOfIntegers = [:]`

## 컬렉션의 변경가능성(mutability)
- `var`로 배열이나 딕셔너리를 만들면 변경가능 컬렉션이어서 컬렉션의 크기를 변경할 수 있음(즉, 원소를 자유롭게 추가 삭제 가능)

- `let`으로 배열이나 딕셔너리를 만들면, 변경불가능 컬렉션이기 때문에, 크기를 변경할 수는 없음(즉, 원소를 추가하거나 삭제할 수 없음)

- (`let`으로 선언한) 상수 딕셔너리의 경우에는 원소 업데이트도 금지됨. 즉, `dict["key"] = "value"` 하면 컴파일 안됨.

- 상수 배열에서는 원소 삭제나 삽입, 추가는 안되지만, 어떤 인덱스에 해당하는 원소를 바꿔치는 것은 가능. 즉, `arr[0] = 10` 같은게 가능(물론 `arr``count`에 따라 다름)

----------
감상: 뭐.. ^^ 있을게 있음. 별다른 것 없음

다른 언어 쓰던 사용자들도 상당히 쉽게 스위프트 언어 자체는 접근 가능할듯. 물론 코코아를 얼마나 잘 사용할 수 있는가는 또 다른 문제임.
Loading

0 comments on commit c40108a

Please sign in to comment.