이름 짓기 규칙
- Lower Camel Case : 함수, 메소드, 변수, 상수
- ex) someVariableName
- Upper Camel Case: 타입(class, struct, enum, extension ...)
- ex)Person, Point,Week
- 대소문자 구분함
콘솔 로그
- print : 단순 문자열 출력
- dump : 인스턴스의 자세한 설명(description property)까지 출력
문자열 보간법
- 프로그램 실행 중 문자열 내에 변수 또는 상수의 실질적인 값을 표현하기 위해 사용하는 것
- ex) "안녕하세요! 저는 \(age + 5)살 입니다."
상수와 변수
let : 상수 선언 키워드, 차후에 값을 변경할 수 없음.
let 이름: 타입 = 값
var : 변수 선언 키워드, 차후에 값 변경이 가능함.
var 이름: 타입 = 값
- 값의 타입이 명확하다면 타입은 생략가능
- 나중에 할당하려고 한느 상수나 변수는 타입을 꼭 명시해야함
let sum: Int
sum = InputA + inputB
- 띄어쓰기 신경쓰기
기본 데이터 타입
- Bool : true / flase, 0이나 1로 표현 불가능
- Int : 정수형 타입
- UInt: Unsigned Int, 양의 정수.UInt에 Int 대입 불가
- Float: 부동소수 타입, 정수타입을 넣어도 문제 없음
- Double: 64비트 부동수소 타입, Double에 Float 대입 불가
- Character: 문자 하나. 큰따옴표(")로 묶어주기
- String: 문자열 타입. String에 Character 대입 불가
Any, AnyObject, nil
- Any: Swift의 모든 타입을 지칭하는 키워드. 어떤 타입도 수용 가능.
- AnyObject: 모든 클래스 타입을 지칭하는 프로토콜
- nil: 없음을 의미하는 키워드 (다른 언어의 null과 같은 의미)
- Any나 AnyObject에 nil을 할당할 수는 없음
컬렉션 타입
Array: 순서가 있는 리스트 컬렉션
//1
var Integers: Array<Int> = Array<Int> ()
//2
var Integers: Array<Int> = [Int]()
//3
var Integers: [Int] = [Int]()
//4
var Integers: [Int] = []
//요소 추가
Integers.append(1)
Integers.append(100)
//요소 존재 확인
Integers.contains(100) //true
Integers.contains(99) //false
//요소 삭제
Integers.remove(at:0) //인덱스
Integers.removeLast() //마지막 요소
Integers.removeAll() //모든 요소
//요소 개수
Integers.count()
//let을 사용하여 Array를 선언하면 불변 Array (append,remove 등 불가)
let immutableArray = [1,2,3]
Dictionary: 키와 값의 쌍으로 이루어진 컬렉션
//1
var anyDictionary: Dictionary<String,Any> = [String: Any]()
//2
var anyDictionary: [String:Any] = [:]
//초기에 값추가
var initializedDictionary: [String:String] =["name" : "yagom", "gender" : "male"]
//값 추가
anyDictionary["someKey"] = "value"
anyDictionary["anotherKey"] = 100
//값 변경
anyDictionary["someKey"] = "dictionary"
//값 제거
anyDictionary.removeValue(forKey: "anotherKey")
anyDictionary["someKey"] = nil
Set: 순서가 없고, 멤버가 유일한 컬렉션
var IntegerSet: Set<Int> = Set<Int>()
//요소 추가 결과:[100,99,1] - 중복 허용 X
IntegerSet.insert(1)
IntegerSet.insert(100)
IntegerSet.insert(99)
IntegerSet.insert(99)
IntegerSet.insert(99)
//요소 존재 확인
IntegerSet.contains(99)
//요소 삭제
IntegerSet.remove(100) //100삭제
IntegerSet.removeFirst()
//요소 개수
IntegerSet.count
//합집합
let union: Set<Int> = setA.union(setB)
//요소 정렬
let sortedUnion: [Int] = union.sorted() //배열 표현
//교집합
let intersection: Set<Int> = setA.intersection(setB)
//차집합
let subtracting: Set<Int> = setA.subtracting(setB)
함수
//기본형태
func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입, ... ) -> 반환타입 {
함수 구현부
return 반환값
}
//예시
func sum(a: Int, b: Int) -> Int {
return a + b
}
//반환값 없을 때는 Void, 또는 생략
func printMyName(name: String) -> Void {
print(name)
}
func printMyName(name: String) {
print(name)
}
//함수 호출
sum(a: 3, b: 5)
printMyName(name: "yagom")
매개 변수 기본값
- 매개 변수 목록 중 뒤쪽에 위치하는것이 좋다
//매개변수 기본값
func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입 = 매개변수 기본값, ... ) -> 반환타입 {
함수 구현부
return 반환값
}
//예시
func greeting(freind: String, me: String = "yagom") {
print("Hello \(friend)! I'm \(me)")
}
greeting(friend: "Hana")
greeting(friend: "John", me: "eric")
전달인자 레이블
- 매개변수의 역할을 좀 더 명확하게 하거나 함수 사용자의 입장에서 표현하고자 할 때 사용
- 함수 내부에서 전달인자를 사용할 때는 매개변수 이름 사용
- 함수를 호출할 때는 전달인자 레이블 사용
//기본형태
func 함수이름(전달인자 레이블 매개변수1이름: 매개변수1타입, 전달인자 레이블 매개변수2이름: 매개변수2타입, ... ) -> 반환타입 {
함수 구현부
return 반환값
}
//예시
func greeting(to freind: String, from me: String = "yagom") {
print("Hello \(friend)! I'm \(me)")
}
greeting(to: "hana", from: "yagom")
가변 매개변수
- 전달 받을 인자의 개수를 알기 어려울 때 사용
- ...을 붙이면 됨
- 가변매개변수는 함수 당 하나만 사용 가능
//기본형태
func 함수이름(매개변수1이름: 매개변수1타입, 전달인자 레이블 매개변수2이름: 매개변수2타입... ) -> 반환타입 {
함수 구현부
return 반환값
}
//예시
func sayHelloToFriend(me: String, friends: String... ) -> String {
return "Hello \(friend)! I'm \(me)"
}
sayHelloToFriend(me: "yagom", friends: "hana", "eric", "wing")
/* sayHelloToFriend(me: "yagom", friends: nil)
sayHelloToFriend(me: "yagom", friends: )는 오류!
전달인자가 없을 경우 그냥 생략 */
sayHelloToFriend(me: "yagom")
데이터 타입으로서의 함수
- 스위프트는 함수형 프로그래밍 패러다임을 포함하는 다중 패러다임 언어
- 스위프트의 함수는 일급 객체 -> 변수, 상수등에 저장 가능, 매개변수를 통해 전달 가능
함수의 타입표현
(매개변수 1 타입, 매개변수 2 타입 ...) -> 반환타입
var someFunction: (String,String) -> Void = greeting(to:from:)
someFunction("eric", "yagom") //Hello eric! I'm yagom
someFunction = greeting(friend:me:)
someFunction("eric", "yagom") //Hello eric! I'm yagom
someFunction = sayHelloToFriends(me:friends:) //error, 매개변수타입이 다름
func runAnother(function: (String,String) -> Void) {
function("jenny", "mike")
}
runAnother(function: greeting(friend:me:))
runAnother(function: someFunction)
조건문
if-else
- 조건에는 항상 Bool 타입이 와야한다.
if condition {
statements
}else if condition{
statements
}else{
statements
}
switch
switch value{
case pattern:
code
default:
code
}
- 범위 연산자를 활용하면 더욱 쉽고 유용
switch someInteger{
case 0:
print("zero")
case 1..<100:
print("1~99")
case 100:
print("100")
case 101...Int.max:
print("over 100")
default:
print("unknown")
}
- break를 명시해주지 않아도 각 case에서 break가 걸림
switch value{
case pattern1:
case pattern2:
code
default:
code
} //오류!!!
//방법 1
switch value{
case pattern1,pattern2:
code
default:
code
}
//방법 2
switch value{
case pattern1:
code
fallthrough //다음 케이스까지 내려가게됨
case pattern2:
code
default:
code
} //오류!!!
반복문
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
- 조건문에는 Bool 타입이어야함
while (integers.count > 1) { //소괄호는 선택사항
integers.removeLast()
}
repeat-while
- do-while문과 비슷한 역할
repeat {
integers.removeLast()
} while integers.count > 0
옵셔널
- 값이 있을 수도, 없을 수도 있음을 뜻함
- nil의 가능성을 명시적으로 표현
- nil 가능성을 문서화 하지 않아도 코드만으로 충분히 표현 가능 -> 문서/주석 작성 시간 절약
- 전달받은 값이 옵셔널이 아니라면 nil체크를 하지 않더라도 안심하고 사용 -> 효율적인 코딩, 예외 상황을 최소화하는 안전한 코딩
Implicitly Unwrapped Optional ( ! )
var implicitlyUnwrappedOptionalValue: Int! = 100
switch implicitlyUnwrappedOptionalValue {
case .none:
print("This Optional variable is nil")
case .some(let value):
print("Value is \(value)")
}
// 기존 변수처럼 사용 가능
implicitlyUnwrappedOptionalValue = implicitlyUnwrappedOptionalValue + 1
// nil 할당 가능
implicitlyUnwrappedOptionalValue = nil
// 잘못된 접근으로 인한 런타임 오류 발생
//implicitlyUnwrappedOptionalValue = implicitlyUnwrappedOptionalValue + 1
Optional ( ? )
var optionalValue: Int? = 100
switch optionalValue {
case .none:
print("This Optional variable is nil")
case .some(let value):
print("Value is \(value)")
}
// nil 할당 가능
optionalValue = nil
// 기존 변수처럼 사용불가 - 옵셔널과 일반 값은 다른 타입이므로 연산불가
//optionalValue = optionalValue + 1
Optional Unwrapping ( 옵셔널 값 추출)
Optional Binding
- nil체크 + 안전한 값 추출
- if let 구문 사용
func printName(_ name: String) {
print(name)
}
var myName: String? = nil
//printName(myName)
// 전달되는 값의 타입이 다르기 때문에 컴파일 오류발생
if let name: String = myName {
printName(name)
} else {
print("myName == nil")
}
var yourName: String! = nil
if let name: String = yourName {
printName(name)
} else {
print("yourName == nil")
}
- ,를 사용해 한 번에 여러 옵셔널을 바인딩 할 수 있음
- 모든 옵셔널에 값이 있을 때만 동작
myName = "yagom"
yourName = nil
if let name = myName, let friend = yourName {
print("\(name) and \(friend)")
}
// yourName이 nil이기 때문에 실행되지 않습니다
yourName = "hana"
if let name = myName, let friend = yourName {
print("\(name) and \(friend)")
}
Force Unwrapping
- 옵셔널의 값을 강제로 추출
- 변수뒤에 !를 붙여주면됨
- 추천하는 방법은 아님
printName(myName!) // yagom
myName = nil
//print(myName!)
// 강제추출시 값이 없으므로 런타임 오류 발생
//yourName은 선언시점부터 강제추출을 가정함
yourName = nil
//printName(yourName)
// nil 값이 전달되기 때문에 런타임 오류발생
구조체
프로퍼티 및 메서드
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
//mutable.immutableProperty = 200
//타입 프로퍼티 및 메서드
Sample.typeProperty = 300
Sample.typeMethod()
//인스턴스에서 사용시 오류
//mutable.typeProperty = 300
//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입니다
클래스
프로퍼티 및 메서드
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, let 상관없이 가변 프로퍼티 변경 가능
// 인스턴스 생성 - 참조정보 수정 가능
var mutableReference: Sample = Sample()
mutableReference.mutableProperty = 200
// 인스턴스 생성 - 참조정보 수정 불가
let immutableReference: Sample = Sample()
// 클래스의 인스턴스는 참조 타입이므로 let으로 선언되었더라도 인스턴스 프로퍼티의 값 변경이 가능합니다
immutableReference.mutableProperty = 200
// 다만 참조정보를 변경할 수는 없습니다
// 컴파일 오류 발생
//immutableReference = mutableReference
// 타입 프로퍼티 및 메서드
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입니다