이름 짓기 규칙

  • Lower Camel Case : 함수, 메소드, 변수, 상수
    • ex) someVariableName
  • Upper Camel Case: 타입(class, struct, enum, extension ...)
    • ex)Person, Point,Week
  • 대소문자 구분함

 

콘솔 로그

  • print : 단순 문자열 출력
  • dump : 인스턴스의 자세한 설명(description property)까지 출력

print(yagom)
dump(yagom)

 

문자열 보간법

  • 프로그램 실행 중 문자열 내에 변수 또는 상수의 실질적인 값을 표현하기 위해 사용하는 것
    • 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입니다

+ Recent posts