개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
인프런, 야곰의 스위프트 기본문법 강좌를 듣고 정리하였습니다.
Optional
값이 ‘있을 수도, 없을 수도 있음’
letoptionalConstant:Int?=nil//혹은letoptionalConstant:Optional<Int>=nilletsomeConstant:Int=nil// 컴파일 에러 발생
옵셔널이 아닌 상수에 nil값을 할당하려고 하면 컴파일 오류가 발생한다.
Optional은 왜 필요한가?
nil의 가능성을 명시적으로 표현해주는 것
nil의 가능성을 문서화하지 안아도 코드만으로 충분히 표현 가능
문서/주석 작성 시간을 절약
전달받은 값이 옵셔널이 아니라면 nil체크를 하지 않더라도 안심하고 사용 가능
효율적인 코딩이 가능해짐
예외 상황을 최소화하는 안정된 코딩 가능
funcsomeFunction(someOptionalParam:Int?){// ...}funcsomeFunction(someOptionalParam:Int){// ...}someFunction(someOptionalParam:nil)someFunction(someOptionalParam:nil)// 컴파일 에러 발생
컴파일 단계에서도 안전하게 Optional값을 처리 가능하다.
Optional의 표현방식 > ?, !
Implicitly Unwrapped Optional, 암시적 추출 옵셔널 > !
타입 뒤에 !를 표현하는 것
옵셔널 타입 자체는 열거형이기 때문에 switch구문으로 표현이 가능하다.
varoptionalValue:Int!=100switchoptionalValue{case.none:// 값이 없다print("This Optional variable is nil!!")case.some(letvalue):// 값이 들어왔다print("Value is \(value)")}// 기존 변수처럼 사용 가능optionalValue=optionalValue+1// nil 할당 가능optionalValue=nil// 잘못된 접근으로 인한 런타임 오류 발생, 이미 nil값을 할당했기 때문optionalValue=optionalValue+1
일반적인 옵셔널 > ?
varoptionalValue:Int?=100switchoptionalValue{case.none:// 값이 없다print("This Optional variable is nil!!")case.some(letvalue):// 값이 들어왔다print("Value is \(value)")}// nil 할당 가능optionalValue=nil// 기존 변수처럼 사용불가 - 옵셔널과 일반 값은 다른 타입이기 때문에 연산불가optionalValue=optionalValue+1
Optional Unwrapping, 옵셔널 값 추출
옵셔널 값을 어떻게 꺼내서 쓰고 활용하는가?
옵셔널 바인딩(Optional Binding) > if let
강제 추출(Force Unwrapping) > !
옵셔널 바인딩(Optional Binding)
옵셔널 값을 꺼내오는 방법 중 하나로 nil체크 + 안전한 값 추출하다는 특징을 가진다.
값이 있는지 확인해보고 값이 있다면 꺼내오고 없다면 지나간다.
funcprintName(_name:String){print(name)}varmyName:String?=nil// 전달되는 값의 타입이 다르기 때문에 컴파일 오류 발생printName(myName)
전달되는 값의 타입이 다를때마다 컴파일 오류가 발생하기 때문에 if-let을 통해 안전하게 옵셔널 값을 추출하도록 한다.
funcprintName(_name:String){print(name)}varmyName:String!=nilifletname:String=myName{printName(name)}else{print("myname == nil")}// name이라는 상수는 if-let 구문안에서만 사용이 가능하다.// 구문 바깥에서 사용했기 때문에 컴파일 오류가 발생한다.printName(myName)
그리고 여러 옵셔널 변수들을 바인딩할 수 있다. 그러나 해당 변수들에 모두 값이 들어가있어야 한다.
varmyName:String?="zehye"varyoutName:String?=nilifletname=myName,letfriend=youtName{print("\(name) and \(friend)")// youtName이 nil이기 때문에 실행이 안됨}yourName="hana"ifletname=myName,letfriend=youtName{print("\(name) and \(friend)")// 실행됨}
강제 추출(Force Unwrapping)
옵셔널의 값을 강제로 추출
funcprintName(_name:String){print(name)}varmyName:String?="zehye"printName(myName!)// zehye !를 사용함으로써 값을 강제로 추출myName=nilprint(myName!)// 강제추출 시 값이 없으므로 런타임 오류 발생varyourName:String!=nil// 처음 선언시 사용 가능printName(yourName)// 여기서 ! 사용하지 않았어도 강제추출 가능
개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
인프런, 야곰의 스위프트 기본문법 강좌를 듣고 정리하였습니다.
매개변수 기본값
기본값을 갖는 매개변수는 매개변수 목록 중에 뒤쪽에 위치하는 것이 좋다.
func 함수이름(매개변수1 이름: 매개변수1 타입, 매개변수2 이름: 매개변수2 타입 = 매개변수 기본값 ...) -> 반환타입 {
함수 구현부
return 반환값
}
예시는 아래와 같다.
funcgreeting(friend:String,me:String="zehye"){print("hello \(friend)! I'm \(me)")}// 뿐만 아니라 매개변수 기본값을 가지는 매개변수는 생략이 가능하고 수정도 가능하다.greeting(friend:"hana")greeting(friend:"John",me:"eric")
전달인자 레이블
전달인자 레이블은 함수를 호출할 때 매개변수의 역할을 좀 더 명확하게 하거나 함수 사용자의 입장에서 표현하고자 할 때 사용한다.
func 함수이름(전달인자 레이블 매개변수1 이름: 매개변수1 타입, 전달인자 레이블 매개변수2 이름: 매개변수2 타입 ...) -> 반환타입 {
함수 구현부
return 반환값
}
스위프트의 함수는 일급객체이므로 변수, 상수 등에 저장이 가능하고 매개변수를 통해 전달 또한 가능하다.
그래서 스위프트의 함수는 하나의 데이터 타입으로서 표현이 될 수 있다.
(매개변수1 타입, 매개변수2 타입) -> 반환타입 // 반환타입은 생략 불가능
// 해당 변수에 함수가 들어올 것이라고 선언varsomeFunction:(String,String)->Void=greeting(to:from:)someFunction("eric","hana")someFunction=greeting(friend:me:)someFunction("eric","hana")// 타입이 다른 함수는 할당 불가능, 가변매개변수로 오는 함수someFunction=sayHelloToFriends(me:friends:)funcrunAnother(function:(String,String)->Void){function("jenny","mike")}runAnother(function:greeting(friend:me:))// 변수에 담겨있는 함수를 넘겨줄 수 있다runAnother(function:someFunction)
개인공부 후 자료를 남기기 위한 목적임으로 내용 상에 오류가 있을 수 있습니다.
인프런, 야곰의 스위프트 기본문법 강좌를 듣고 정리하였습니다.
컬렉션 타입
여러 값들을 묶어 하나의 변수를 표현할 수 있도록 해준다.
Array
순서가 있는(인덱스가 있는) 리스트 컬렉션
varintegers:Array<Int>=Array<Int>()// []integers.append(1)// [1]integers.appenr(100)// [1,100]integers.contains(100)// trueintegers.contains(99)// false// 0번 인덱스의 값을 삭제integers.remove(at:0)// 1// 마지막 인덱스 값을 삭제integers.remove()// 모든 인덱스 값을 삭제integers.removeAll()integers.count()integers[0]
Array를 생성하는 다양한 방법
vardoubles:Array<Double>=[Double]()varstrings:[String]=[String]()varcharacters:[Character]=[]// let을 사용해 Array를 선언하면 불면 Array가 된다.letimmutableArray=[1,2,3]
Dictionary
키와 값의 쌍으로 이루어진 컬렉션(key, value)
특별한 정렬 순서는 정해져있지 않다.
varanyDictionary:Dictionary<Stinrg:Any>=[String:Any]()anyDictionary["someKey"]="value"anyDictionary["anotherKey"]=100// key에 해당하는 value를 삭제하고 싶을 때anyDictionary.removeValue(forKey:"anotherKey")anyDictionary["someKey"]=nil// let으로 선언했기 때문에 Dictionary의 값을 변경할 수 없다letemptyDictionary:[String:Stinrg]=[:]letinitalizedDictionary:[String:String]=["name":"zehye","gender":"female"]
Set
순서가 없고, 멤버가 유일한 컬렉션(중복된 값이 없다)
varintegerSet:Set<Int>=Set<Int>()integerSet.insert(1)integerSet.insert(100)integerSet.insert(99)integerSet.insert(99)integerSet.insert(99)integerSet// {100,99,1}integerSet.contains(1)// trueintegerSet.contains(2)// falseintegerSet.remove(100)integerSet.removeFirst()integerSet.countletsetA:Set<Int>=[1,2,3,4,5]letsetB:Set<Int>=[3,4,5,6,7]// A와 B의 합집합letunion:Set<Int>=setA.union(setB)// {2,4,5,6,1,3,7}// 합집합을 정렬letsortedUnion:[Int]=union.sorted()// {1,2,3,4,5,6,7}// 교집합letintersection:Set<Int>=setA.intersection(setB)// {5,3,4}// 차집합letsubtracting:Set<Int>=setA.subtracting(setB)// {2,1}