본문 바로가기
ios 개발 일지

[패스트캠퍼스][나만의 iOS 앱 개발 입문] [ iOS개발 강의] 2주차 학습일지

by IGBR 2022. 1. 4.

2주차는 함수 , 옵셔널 , 컬렉션, 클로져를 배웠다. 

 


함수

함수의 선언

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

함수 선언의 예 

- sum이라는 이름을 가지고 
- a와 b라는 Int 타입의 매개변수를 가지며 
- Int 타입의 값을 반환하는 함수

func sum(a: Int, b: Int) -> Int {
    return a + b
}

만약 함수가 반환하는 값이 없다면

func printName(name: String) -> Void {
    print(name)
}

// Void는 생략가능
func printName(name: String) {
    print(name)
}

매개 변수가 없다해도 함수명 옆에 빈공간의 ()를 추가해줘야한다. 

func printHello() -> Void { 
	print("hello") 
}

함수의 호출 방법 >> 함수명(매개변수)

printHello() // hello

convertTemp(15) // 59

plus(1,2) // 3

전달인자 레이블

- 전달인자 레이블은 한글로도 설정이 가능하여(물론 매개변수도 한글 사용이 가능하다) 실제 함수를 쓰는 입장에서 매개변수가 한글로 보이다 보니 접근성이 오르는 효과를 볼 수 있다. 

func 함수이름(전달인자 레이블 매개변수1이름: 매개변수1타입, 전달인자 레이블 매개변수2이름: 매개변수2타입 ...) -> 반환타입 {
    // 함수의 실행 구문
    return
}

전달인자 레이블의 주의사항

// 함수 내부에서 전달인자를 사용할 때에는 매개변수 이름을 사용
func greeting(to friend: String, from me: String) {
    print("Hello \(friend), I'm \(me)")
}

// 함수를 호출할 때에는 전달인자 레이블을 사용
greeting(to: "hanjo", from: "moon") // Hello hanjo, I'm moon

전달 받을 값의 갯수를 모른다면 가변 매개변수를 사용한다. 

- 함수에 하나밖에 쓰지 못한다. 

func 함수명(매개변수1이름: 매개변수1타입, 전달인자 레이블 매개변수2이름: 매개변수2타입...) -> 반환타입 {
    // 함수 실행 부분
    return
}

가변 매개변수의 예

func sayHelloToFriends(me: String, friends: String...) -> String {
    return "Hello \(friends)! I'm \(me)!"
}

함수를 통하여 매개변수를 직접 수정하는 방법

- 매개변수는 상수로 받아지기 떄문에 수정이 불가하다. 

var value = 3
func incrementAndPrint(_ value: inout Int) {
	value +=1
    print(value)
}

incrementAndPrint(&value) // 4

 

 

좋은 함수는? 

 

1. 하나의 함수엔 하나의 기능만. 

2. 적은 매개변수 갯수

3. 짧은 함수 (5줄을 넘기지마라. )

 


Optional

변수의 값이 nil 일 수 있다는걸 표현

 

선언 방법 nil일수 있는 변수의 타입 뒤에 ?를 붙인다. 

var name : String?

Optional 변수를 사용 하려면 크게 4가지 방법이 있다. 

- Forced unwrapping

- Optional binding(if let의 활용)

- Optional binding(guard 의 활용)

- Nil coalescing  

 

 

Forced unwrapping

- 변수명 뒤에 !을 활용하여 사용

var number1:Int? = 20
var number2:Int = 100

if number1 {
    let sum = number1! + number1!
}

Optional binding(if let의 활용)

 

var number1:Int? = 20
var number2:Int = 100

if let nonOptionalNumber1 = number1 {
    let sum = nonOptionalNumber1 + number2

Optional binding(guard 의 활용)

func printParsedInt(from: String) {
	guard let parsedInt = Int(from) else {
    print("Int로 컨버팅이 되지 않습니다.")
    return
 	}
    print(parsedInt)
}

Nil coalescing( ?? 사용)

let myCarName : String = carName ?? "타이칸"

print(myCarName)

 


Collection(컬렉션)

3가지의 컬렉션

- Array , Dictionary , Set 

 

Array

- 아이템이 순서(index)를 가지는 리스트형태의 컬렉션 타입

- 각 아이템들은 같은 타입이어야한다. 

- 순서가 있는 아이템, 아이템의 순서를 알면 유용할 때 사용한다. 

 

Array의 선언 및 생성

- 다양한 리터럴 문법이 사용가능하다. 

// 빈 Int Array 생성
var integers: Array<Int> = Array<Int>()

// 같은 표현
// var integers: Array<Int> = [Int]()
// var integers: Array<Int> = []
// var integers: [Int] = Array<Int>()
// var integers: [Int] = [Int]()
// var integers: [Int] = []
// var integers = [Int]()

 

Array 의 활용 방법

var evenNumbers: [Int] = [2,4,6,8]

// array에 아이템 추가
evenNumbers.append(10) // [2,4,6,8,10]
evenNumbers += [12,14,16]

// array의 아이템 삭제
evenNumbers.remove(at: 0)

// array에 아이템이 있는지 확인하기
evenNumbers.isEmpty

// array에 아이템이 몇개있는지 확인하기
evenNumbers.count

// array의 첫번째 아이템 가져오기
evenNumbers.first

// array의 마지막 아이템 가져오기
evenNumbers.last

// first와 last는 옵셔널로 추출이 된다 . if let 사용하여 추출 한다.

// array에 특정 아이템을 포함하는지 확인하기 
evenNumbers.contains(10) // true

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]()

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)

 

Set

- 순서가 없고, 멤버가 유일한 것을 보장하는 컬렉션 타입입니다. 

- 집합 연산에 유리합니다.

 

Set의 선언 및 구현

// 빈 Int Set 생성
var integerSet: Set<Int> = Set<Int>()
integerSet.insert(1)
integerSet.insert(100)
integerSet.insert(99)
integerSet.insert(99)
integerSet.insert(99)

print(integerSet) // [100, 99, 1]
print(integerSet.contains(1)) // true
print(integerSet.contains(2)) // false

integerSet.remove(100)
integerSet.removeFirst()

print(integerSet.count) // 1

Closure(클로저)

클로저 (컴퓨터 프로그래밍)
컴퓨터 언어에서 클로저(Closure)는 일급 객체 함수(first-class functions)의 개념을 이용하여 스코프(scope)에 묶인 변수를 바인딩 하기 위한 일종의 기술이다. 기능상으로, 클로저는 함수를 저장한 레코드(record)이며, 스코프(scope)의 인수(Factor)들은 클로저가 만들어질 때 정의(define)되며, 스코프 내의 영역이 소멸(remove)되었어도 그에 대한 접근(access)은 독립된 복사본인 클로저를 통해 이루어질 수 있다. (위키백과)

흔히들 많이 어려워 하는 내용이라고 들었고 나또한 공부하면서 많이 헤매고 정확한 이해를 하는데 시간이 많이 걸렸다. ( 사실 지금도 어렵다

 

클로저의 특징들을 나열하면 이렇다. 

 

- 일급 객체(first-class)로 변수/상수 저장 및 인자로 사용가능, 리턴 값이 될 수도 있음  

- 우리가 흔히 쓰던 함수이름이 있는 클로저 라고 볼 수 있다.

- 유저의 코드 안에서 전달되어 사용할 수 있는 로직을 가지며, 중괄호로 구분된 코드의 블럭이다. 

 

 

클로저의 표현 방식

{ (인자1, 인자2 ) -> 반환타입 in
	실행될 구문
}

// 만약 클로저의 바디가 짧으면 아래 처럼 한줄로도 표현한다. 
{ (인자1 , 인자2 ) -> 반환타입 in 실행될 구문 }

// in 을 기준으로 in 앞쪽에 있으면 함수 head 부분
// 뒤에 있다면 body 부분이라 한다.

 

함수의 전달인자로 사용가능한 클로저

- 클로저는 주로 함수의 전달인자로 많이 사용된다.

- 함수 내부에서 원하는 코드블럭을 실행 할 수 있다.

 

// 상수 타입 선언 부에 파라미터의 타입과 리턴타입을 명시
let add: (Int, Int) -> Int
add = { (a: Int, b: Int) in
    return a + b
}

let substract: (Int, Int) -> Int
substract = { (a: Int, b: Int) in
    return a - b
}

let divide: (Int, Int) -> Int
divide = { (a: Int, b: Int) in
    return a / b
}

func calculate(a: Int, b: Int, method: (Int, Int) -> Int) -> Int {
    return method(a, b)
}

var calculated: Int

calculated = calculate(a: 2, b: 3, method: add)

print(calculated) // 5

calculated = calculate(a: 5, b: 2, method: substract)

print(calculated) // 3

calculated = calculate(a: 6, b: 2, method: divide)

print(calculated) // 3

//따로 클로저를 상수/변수에 넣어 전달하지 않고, 
//함수를 호출할 때 클로저를 작성하여 전달할 수도 있다.

calculated = calculate(a: 5, b: 10, method: { (left: Int, right: Int) -> Int in
    return left * right
})

print(calculated) // 50

 

후행 클로저

클로저가 만약 함수의 마지막으로 전달되는 인자라면 소괄호 외부에 클로저 구현이 가능하다.

func calculate(a: Int, b : Int , method : (Int, Int) -> Int) -> Int {
	return method(a,b)
}

var result : Int

// 중괄호 부터 클로저 시작
result = calculate( a : 10, b: 10) { (left : Int, right : Int ) -> Int in
	return left + right
}

print(result) // 20 출력

 

클로저 실행 방법

- 클로저가 대입된 변수나 상수로 호출

- 클로저를 직접 실행

 

- 클로저가 대입된 변수나 상수로 호출

let closure = { () -> String in
    return "Hello World!"
}

closure()

- 클로저를 직접 실행

클로저를 만들고 앞뒤로 () 로 감싸준 다음 끝에 ()를 다시 사용 (완전 일회성일 때 사용한다.)

({ () -> () in
	print("Hello World!")
})()

 


 

이것으로 2주차 학습도 종료가 되었다. 어려운 내용도 몇몇 있었지만 복습해서 꼭 기본을 잘 다졌으면 좋겠다. 

 

댓글