티스토리 뷰

Swift 공부하면서 기본 문법이 정리가 잘 되어 있지 않다고 생각해서,, 강의를 들으면서 정리를 해보려고 한다. ㅎㅇㅌ!

이름짓기 규칙

  • Lower Camel Case: function, method, variable, constant
  • Upper Camel Case: type(class, struct, enum, extenstion)
  • 대소문자를 구분 !

콘솔로그

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

문자열 보간법

  • String inetrpolation
  • 프로그램 실행 중 문자열 내에 변수 또는 상수의 실질적인 값을 표현하기 위해 사용
  • \()

상수와 변수

//상수, 변수의 선언 

//상수 선언 키워드 let 
//변수 선언 키워드 var 

//상수의 선언 let 이름: 타입 = 값 
//변수의 선언 var 이름: 타입 = 값 

//값의 타입이 명확하다면 타입은 생략 가능 
let 이름 = 값 
var 이름 = 값 

let constant: String = "차후에 변경이 불가능한 상수 let" 
let variable: String = "차후에 변경이 가능한 변수 let" 

//상수 선언 후 나중에 값 할당하기 

//나중에 할당하려고 하는 상수나 변수는 타입을 꼭 명시해야 함. 
let sum: Int let inputA: Int = 100 let inputB: Int = 200 

//선언 후 첫 할당 sum = inputA + inputB sum = 1 
//그 이후에는 다시 값을 바꿀 수 없다 -> 오류발생

Any, AnyObject, nil

Any - Swift의 모든 타입을 지칭하는 키워드 
AnyObject - 모든 클래스 타입을 지칭하는 프로토콜 
nil - 없음을 의미하는 키워드 

//Mark: - Any var someAny: Any = 100 
someAny = "어떤 타입도 수용 가능하다" someAny = 123.12 
//let someDouble: Double = someAny -> 오류 

//Mark: - AnyObject class SomeClass {}
var someAnyObject: AnyObject = SomeClass() 
someAnyObject = 123.12 -> 오류
//Mark: - nil someAny = nil -> 오류 
someAnyObject = nil -> 오류

컬렉션 타입 (Array, Dictionary, Set)

Array

컬렉션 타입 
Array - 순서가 있는 리스트 컬렉션 
Dictionary - 키와 값의 쌍으로 이루어진 컬렉션 
Set - 순서가 없고, 멤버가 유일한 컬렉션 

//Mark: - Array 
//빈 Int Array 생성 var integers: Array<Int> = Array<Int>() 
-> [] integers.append(1) -> [1] 
integers.append(100) -> [100] 

integers.contains(100) -> true 
integers.contains(100) -> false

integers.remove(at: 0) -> 1 
integers.removeLast() -> 100 
integers.removeAll() -> [] 
integers.count -> 0 

//Array<Double>와 [Double]는 동일한 표현
//빈 Double Array 생성 
var doubles: Array<Double> = [Double]() 
//빈 String Array 생성 var strings: [String] = [String]()
//빈 Character Array 생성 
//[]는 새로운 빈 Array var characters: [Character] = [] 
//let을 사용하여 Array를 선언하면 불변 Array 
let immutableArray= [1, 2, 3]

Dictionary

// Dictionary의 선언과 생성
// Key가 String 타입이고 Value가 Any인 빈 Dictionary 생성 

var anyDictionary: Dictionary<String, Any> = [String: Any]() 
// 위와 동일한 표현 
// var anyDictionary: Dictionary <String, Any> = Dictionary<String, Any>() 
// var anyDictionary: Dictionary <String, Any> = [:]
// var anyDictionary: [String: Any] = Dictionary<String, Any>() 
// var anyDictionary: [String: Any] = [String: Any]() 
// var anyDictionary: [String: Any] = [:] 
// var anyDictionary = [String: Any]()

// 2. Dictionary 활용 
// 키에 해당하는 값 할당 

anyDictionary["someKey"] = "value" 
anyDictionary["anotherKey"] = 100 
print(anyDictionary) 
// ["someKey": "value", "anotherKey": 100] 

// 키에 해당하는 값 변경 
anyDictionary["someKey"] = "dictionary" 
print(anyDictionary) ["someKey": "dictionary", "anotherKey": 100] 

// 키에 해당하는 값 제거
anyDictionary.removeValue(forKey: "anotherKey")
anyDictionary["someKey"] = nil print(anyDictionary) -> [:] 

// 3. 불변 Dictionary: let을 사용하여 Dictionary 선언 
let emptyDictionary: [String: String] = [:] 
let initalizedDictionary: [String: String] = ["name": "yagom", "gender": "male"] 

// 불변 Dictionary이므로 값 변경 불가 
//emptyDictionary["key"] = "value"

Set

// Set 생성 및 선언 var integerSet: Set<Int> = Set<Int>() 
// insert : 새로운 멤버 입력
// 동일한 값은 여러번 insert해도 한번만 저장됩니다.
integerSet.insert(1) 
integerSet.insert(99) 
integerSet.insert(99)
integerSet.insert(99) 
integerSet.insert(100)
 print(intigerSet)
 // {100, 99, 1}
 // contains: 멤버 포함 여부 확인 
 print(integerSet.contatins(1)) 
 // true print(integerSet.contains(2))
 // false 
 // remove: 멤버 삭제 integerSet.remove(99)
 // {100, 1} integerSet.removeFirst() 
 // {1}
 // count: 멤버 개수 integerSet.count
 // 1
 // 2. Set의 활용
 // 멤버의 유일성이 보장되기 때문에 집합 연산에 활용하면 유용합니다. 
 let setA: Set<Int> = [1, 2, 3, 4, 5] 
 let setB: Set<Int> = [3, 4, 5, 6, 7] 
 // 합집합 let union: Set<Int> = setA.union(setB) print(union) 
 // [2, 4, 5, 6, 7, 3, 1] 
 // 합집합 오름차순 정렬 let sortedUnion: [Int] = union.sorted()
 print(sortedUnion)
 // [1, 2, 3, 4, 5, 6, 7] 
 // 교집합 let intersection: Set<Int> = setA.intersection(setB) 
 print(intersection) 
 // [5, 3, 4]
 // 차집합 let subtracting: Set<Int> = setA.subtracting(setB) print(subtracting)
 // [2, 1]

함수 기본

함수 선언의 기본 형태

함수 선언의 기본 형태 
func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입 ...) -> 반환타입 { 
/* 함수 구현부 */ 
return 반환값 
} 
// sum이라는 이름을 가지고 
// a와 b라는 Int 타입의 매개변수를 가지며
// Int 타입의 값을 반환하는 함수 
func sum(a: Int, b: Int) -> Int { return a + b }

반환 값이 없는 함수

반환 값이 없는 함수 func 함수이름(매개변수1이름: 매개변수1타입, 매개변수2이름: 매개변수2타입 ...) -> Void {
/* 함수 구현부 */ 
return 
} 

// 예) 
func printMyName(name: String) -> Void {
print(name)
} 
// 반환 값이 없는 경우, 반환 타입(Void)을 생략 가능 

func printYourName(name: String) {
print(name) 
}

매개변수가 없는 함수

매개변수가 없는 함수 func 함수이름() -> 반환타입 {
/* 함수 구현부 */ 
return 반환값
}
// func maximumIntegerValue() -> Int {
return Int.max
}

매개변수와 반환값이 없는 함수

매개변수와 반환값이 없는 함수 func 함수이름() -> Void {
/* 함수 구현부 */ 
return
} 

// 함수 구현이 짧은 경우
// 가독성을 해치지 않는 범위에서
// 줄바꿈을 하지 않고 한 줄에 표현해도 무관합
func hello() -> Void {
print("hello")
}

// 반환 값이 없는 경우, 반환 타입(Void)을 생략 가능 
func 함수이름() {
/* 함수 구현부 */
return 
} 

func bye() {
print("bye")

}

함수의 호출

함수의 호출 sum(a: 3, b: 5)
// 8
printMyName(name: "yagom") 
// yagom printYourName(name: "hana") 
// hana maximumIntegerValue() 
// Int의 최댓값 hello()
// hello bye() 
// bye

함수 고급

매개변수 기본값

매개변수 기본값 매개변수에 기본적으로 전달될 값을 미리 지정해 둘 수 있다.
기본값을 갖는 매개변수는 매개변수 목록 중 뒤쪽에 위치하는 것이 좋다. 
func 함수 이름(매개변수1 이름: 매개변수1 타입, 매개변수2 이름: 매개변수 타입 = 매개변수 기본값../) -> 반환타입 { 
// 함수 구현부
return 반환값
 } 
 
 func greeting(friend: String, me: String = "seungchan"){
 print("Hi \(friend) I'm \(me)")
 }
 매개변수 기본값을 가지는 매개변수는 호출 시 생략 가능 
 
 greeting(friend: "hana") greeting(friend: "john", me: "eric")

전달인자 레이블

전달인자 레이블 함수를 호출할 때 함수 사용자의 입장에서 매개변수의 역할을 좀 더 명확하게 표현하고자 할 때 사용 전달인자 레이블은 변경하여 동일한 이름의 함수를 중복으로 생성 가능
func 함수이름(전달인자 레이블 매개변수1 이름: 매개변수1 타입...) -> 반환 타입 {
// 함수 구현부 
return 반환값 
} 
함수 내부에서 전달인자를 사용할 때에는 매개변수 이름을 사용 

func greeting(to friend: String, from me: String)}{ 
print("Hello") 
} 
함수를 호출할 때에는 전달인자 레이블을 사용해야 함. 
greeting(to: "hana", from: "seungchan")

가변 매개변수

가변 매개변수 전달 받을 값의 개수를 알기 어려울 때 사용 가변 매개변수는 함수당 하나만 가질 수 있음 기본값이 있는 매개변수와 같이 가변 매개변수 역시 매개변수 목록 중 뒤쪽에 위치하는 것이 좋음 //func 함수이름(매개변수1이름: 매개변수1타입, 전달인자 레이블 매개변수2이름: 매개변수2타입...) -> 반환타입 { // /* 함수 구현부 */ // return //} func sayHelloToFriends(me: String, friends: String...) -> String { return "Hello \(friends)! I'm \(me)!" } print(sayHelloToFriends(me: "seungchan", friends: "hana", "eric", "wing")) // Hello ["seungchan", "eric", "wing"]! I'm seungchan! print(sayHelloToFriends(me: "seungchan")) // Hello []! I'm seungchan!

데이터 타입으로서의 함수

데이터 타입으로서의 함수 스위프트는 함수형 프로그래밍 패러다임을 포함하는 다중 패러다임 언어이므로 스위프트의 함수는 일급객체이다.
함수를 변수, 상수에 할당이 가능하고, 매개변수를 통해 전달할 수 있다.
함수의 타입 표현: 반환 타입을 생략할 수 없다. 
(매개변수1 타입, 매개변수2 타입...) -> 반환타입 
var someFunction: (String, String) -> Void = greeting(to:from:) someFunction("eric", "seungchan") 
// Hello eric! I'm seungchan someFunction = greeting(friend:me:) someFunction("eric", "seungchan")
// Hello eric! I'm seungchan
// 타입이 다른 함수는 할당할 수 없습니다 - 컴파일 오류 발생
//someFunction = sayHelloToFriends(me: friends:) 
func runAnother(function: (String, String) -> Void) { 
function("jenny", "mike") 
} 
// Hello jenny! I'm mike runAnother(function: greeting(friend:me:))
// Hello jenny! I'm mike runAnother(function: someFunction)

조건문

if-else

if-else 구문
1. if만 단독으로 사용해도 되고, else, else if 와 조합해서 사용 가능
2. if 뒤의 조건 값에는 Bool 타입의 값만 위치해야 함. 
3. 조건을 감싸는 소괄호는 선택사항 
if 조건 { /* 실행 구문 */ } 
else if 조건 { /* 실행 구문 */ } 
else { /* 실행 구문 */ }

if-else 의 사용 

let someInteger = 100 if someInteger < 100 { 
print("100 미만") 

} else if someInteger > 100 {
print("100 초과") 

} else { 

print("100")
}
// 100
// 스위프트의 조건에는 항상 Bool 타입이 들어와야 합니다.
// someInteger는 Bool 타입이 아닌 Int 타입이기 때문에
// 컴파일 오류가 발생합니다. 
//if someInteger { }

switch case

switch 구문
1. 기본적으로 사용하던 정수타입의 값만 비교하는 것이 아니라 대부분의 스위프트 기본 타입을 지원하며, 다양한 패턴과 응용이 가능
2. 각각의 case 내부에는 실행가능한 코드가 반드시 위치해야 함. 
3. 매우 한정적인 값 (enum의 case 등)이 비교값이 아닌 한 default 구문은 반드시 작성해야 함. 
4. 명시적 break를 하지 않아도 자동으로 case마다 break 됨.
5. fallthrough 키워드를 사용하여 break를 무시할 수 있음. 
6. 쉼표(,)를 사용하여 하나의 case에 여러 패턴을 명시할 수 있음.

switch 비교값 {
case 패턴: /실행구문/ 
default: /실행구문/ 
} 
// 범위 연산자를 활용하면 더욱 쉽고 유용 
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") 
} 
// 100 
// 정수 외의 대부분의 기본 타입을 사용할 수 있다 
switch "seungchan" { 
case "jake": print("jake") 
case "mina": print("mina") 
case "yagom": print("seungchan!!") 
default: print("unknown") 
} 
// seungchan!!

반복문

for-in 구문

기존 언어의 for-each 구문과 유사 
Dictionary의 경우 이터레이션 아이템으로 튜플이 들어옴. 

for-in 구문 기본 형태 
for item in items { 
/실행 구문/
}
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 integers.count > 1 {
integers.removeLast() 
}

repeat - while 구문

기존 언어의 do-while 구문과 형태/동작이 유사 

repeart { /실행 구문/ }

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

옵셔널

옵셔널이란 ?

값이 있을 수도, 없을 수도 있음을 표현
nil이 할당 될 수 있는지 없는지 표현

// someOptionalParam에 nil이 할당 될 수 있다. 
func someFunction(someOptionalParam: Int?) { // .... }
/// someOptionalParm에 nil이 할당 될 수 없다. 
func someFunction(someOptionalParam: Int) { // .... }
someFunction(someOptionalParam: nil)
// someFunction(someParam: nil)

옵셔널을 쓰는 이유

명시적 표현

1. nil의 가능성을 코드만으로 표현 가능
2. 문서/주석 작성 시간 절약

안전한 사용

1. 전달 받은 값이 옵셔널이 아니라면 nil체크를 하지 않고 사용 가능
2. 예외 상황을 최소화 하는 안전 코딩
3. 효율적 코딩

옵셔널 문법과 선언

옵셔널 문법 = enum + general
옵셔널 선언

enum Optional<Wrapped>: ExpressibleByNiliteral { 
case none
case some(Wrapped) 
}

let optionalValue: Optional<Int> = nil 
let optionalValue: Int? =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 
-> 이미 nil을 선언해서 그 다음 값은 오류 발생

물음표(?)를 이용한 옵셔녈 (일반적인 옵셔널)

// 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

옵셔널 추출

옵셔널 추출이란?

옵셔녈에 들어있는 값을 사용하기 위해 꺼내 오는 것

옵셔널 방식

옵셔널 바인딩

1. nil 체크 + 안전한 추출
2. 옵셔널 안에 값이 들어있는지 확인하고 값이 있으면 값을 꺼내옴
3. if-let 방식 사용

func printName(_ name: String) { 
print(name) 
} v
ar 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") 
} 
// name 상수는 if-let 구문 내에서만 사용가능합니다 
// 상수 사용범위를 벗어났기 때문에 컴파일 오류 발생 
//printName(name) 
// ,를 사용해 한 번에 여러 옵셔널을 바인딩 할 수 있습니다
// 모든 옵셔널에 값이 있을 때만 동작합니다 
myName = "seungchan" 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)") }
// seungchan and hana

강제추출

옵셔널에 값이 들어있는지 아닌지 확인하지 않고 강제로 값을 꺼내는 방식
만약 값이 없을 경우(nil) 런타임 오류가 발생하기 때문에 옵셔널 바인딩을 주로 사용

var myName: String? = seungchan var youName: String! = nil printName(myName!) 
// seungchan myName = nil
//print(myName!)
// 강제추출시 값이 없으므로 런타임 오류 발생 yourName = nil
//printName(yourName)
// nil 값이 전달되기 때문에 런타임 오류발생

'Swift 문법 정리 - iOS' 카테고리의 다른 글

[Swift] 클래스 VS 구조체 / 열거형  (0) 2021.08.02
[Swift] 인스턴스 / 프로퍼티 / 메서드  (1) 2021.08.02
[Swift] 열거형 (enum)  (0) 2021.08.01
[Swift] 클래스 (Class)  (0) 2021.08.01
[Swift] 구조체 (struct)  (0) 2021.08.01
댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
«   2024/09   »
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28
29 30
글 보관함