22-09-22 목요일
2주차
1교시, 2교시, 3교시
Swift
데이터 타입, 상수, 그리고 변수
- 데이터 타입 : 정수(Int), 부동소수점(Float, Double), 문자(”유니코드”), 문자열(“유니코드s”), 불리언(true, false)
- 상수 : let
- 변수 : var
잠깐 본론으로 들어가기 전에... 모든 조들이 함께하는 게임을 진행했다!
Playground 놀이 규칙
12개의 회고조를 돌면서 한 조당 한 판씩 문제를 푼다.
단, 입력은 돌아가면서 진행한다.
- 11 → 7 → 3 → 12 → 9 → 10 → 2 → 4 → 5 → 6 → 8
우리팀 차례에서 조건문에 and, or, not을 사용해서 확인하는 판이 걸렸다! 새로운 개념이 나와서 시간이 조금 걸렸지만 채팅으로 서로 논의하니까 금방 풀 수 있었다. :-)
옵셔널
옵셔널 타입
Optional type
변수, 상수는 초기화를 하지 않고 미리 만들어둘 수 있다. 그때 값이 들어올 수도, 안들어갈 수도 있는데 이를 표현?해주는게 옵셔널이다.
- Swift 옵셔널 데이터 타입은 대부분의 다른 프로그래밍 언어에 없는 새로운 개념이다.
- Swift가 먼저 이 개념을 탑재했고, 다른 언어들도 그 영향을 받아 옵셔널 개념을 적용하고 있다.
- 옵셔널 타입의 목적은 변수 또는 상수에 값이 할당되지 않은 상황을 처리하기 위해 안전하고 일관된 접근 방식을 제공하는 것이다.
- 없으면 없는대로 확인했으니까 넘어가자~ 하고 체크가 가능하다.
- 즉, 내용이 없더라도 진행하는데 문제가 없도록 해준다.
- 변수를 선언할 때, 데이터 타입 선언 다음에 ‘?’ 문자를 두어 옵셔널이 되게 한다.
var index: Int?
- 이제 index 변수는 정수값이 할당되거나 아무런 값도 할당되지 않을 수 있다. 내부적으로 컴파일러와 런타임의 관점에서 볼 때 어떤 값도 할당되지 않은 옵셔널은 실제로 nil의 값을 갖는다.
- nil도 하나의 값이다. nil 자체도 type에 의한 값(value)이다.
- Int? → 정수형 옵셔널 타입
- Int → 정수형 타입
- Float? → 실수형 옵셔널 타입
- Float → 실수형 타입
- nil도 하나의 값이다. nil 자체도 type에 의한 값(value)이다.
- 옵셔널은 할당된 값이 있는지를 식별하기 위한 테스트를 다음과 같이 쉽게 할 수 있다.
var index: Int?
if index != nil {
// index 변수는 값이 할당되어 있다.
} else {
// index 변수는 값이 할당되어 있지 않다.
}
강제 언래핑
Forced unwrapping
- 만약 옵셔널에 값이 할당되었다면 해당 값이 옵셔널 내에서 ‘래핑되었다(wrapped)’고 말한다.
옵셔널 안에 래핑된 값을 사용할 때는 강제 언래핑(forced unwrapping)이라는 개념을 이용하게 된다.
- 래핑된 값은 옵셔널 데이터 타입에서 옵셔널 이름 뒤에 느낌표(!)를 두어 추출되게 한다.
- 상자를 흔들어보고 있는지 없는지 판단하고 뜯는게 아니라, 그냥 바로 뜯는게 강제 언래핑이라고 보면 된다…
var index: Int?
index = 3
var treeArray = ["Oak", "Pine", "Yew", "Birch"]
if index != nil {
print(treeArray[index!])
} else {
print("index does not contain a value")
}
// Birch
- 옵셔널로 할당된 값을 강제 언래핑하지 않고 직접 접근하면 에러가 발생한다!
var index: Int?
index = 3
var treeArray = ["Oak", "Pine", "Yew", "Birch"]
if index != nil {
print(treeArray[index]) // 에러 발생...
} else {
print("index does not contain a value")
}
- 강제 언래핑을 시도할 때 주의하지 않으면 에러가 생길 수 있다.
- 그러므로… 가능하면 사용하지 않는게 좋다!
- 근데 실제 개발하다보면 써야할 경우도 있고 🤣
var index: Int?
index = 5
var treeArray = ["Oak", "Pine", "Yew", "Birch"]
if index != nil {
print(treeArray[index])
} else {
print("index does not contain a value")
}
옵셔널 바인딩
Optional binding
- 강제 언래핑 대신, 옵셔널로 할당된 값은 옵셔널 바인딩(optional binding)을 이용하여 임시 변수나 상수에 할당할 수 있다.
- 다음의 코드는 두 가지 작업을 수행한다.
- 지정된 옵셔널이 가지고 있는지를 확인한다.
- 옵셔널 변수가 값을 가지고 있는 경우에 선언된 상수 또는 변수에 그 값을 할당하고 코드가 실행된다.
if let constantName = optionalName { ... } if var variableName = optionalName { ... }
- 옵셔널 바인딩
- if let ~ else { ~ }
var index: Int?
index = 3
var treeArray = ["Oak", "Pine", "Year", "Birch"]
if let myValue = index {
print(treeArray[myValue])
} else {
print("index does not contain a value")
}
- 위 코드는 index 변수에 할당된 값이 언래핑되어 myValue라는 임시 상수에 할당되어 배열에 대한 인덱스로 사용된다.
- 임시 상수는 if 구문 안에서만 유효하다. (if 구문 실행이 끝나면 이 상수는 더 이상 존재하지 않게 된다)
- 위의 이유로 옵셔널로 할당된 동일한 이름을 사용해도 충돌이 발생하지 않는다.
if let index = index {
print(treeArray[index])
} else {
...
}
그러나!!! 귀찮다고 같은 이름을 쓰지말자. 이렇게 쓴 코드를 코드리뷰 시간에 꼭 말해주자.
같이 협업하는 상황에서 저렇게 하면… 읽기가 힘들어진다.
이론적으로는 가능하지만, 하지마라.
- 옵셔널 바인딩은 여러 개의 옵셔널을 언래핑하고 조건문을 포함하는 데 사용될 수 있다.
if let 상수명1 = 옵셔널이름1, let 상수명2 = 옵셔널이름2, let 상수명3 = 옵셔널이름3, ... <조건식> {
...
}
var pet1: String?
var pet2: String?
pet1 = "cat"
pet2 = "dog"
if let firstPet = pet1, let secondPet = pet2 {
print(firstPet)
print(secondPet)
} else {
print("insufficient pets")
}
- 다음의 코드는 조건문을 사용하는 예제다.
- petCount가 1보다 크지 않다면 옵셔널 바인딩이 수행되지 않을 것이다.
var pet1: String?
var pet2: String?
pet1 = "cat"
pet2 = "dog"
let petCount = 15
if let firstPet = pet1, let secondPet = pet2, petCount > 1 {
print(firstPet)
print(secondPet)
} else {
print("insufficient pets")
}
/*
cat
dog
*/
갑자기 수업 중간에 꿀팁.
Swift Evolution
: Swift의 기능을 제안할 수 있는 사이트.
open source로 나와있으니까, 이런 기능을 제안해줄 수 있나? 하고 올려두는 것이다.
강제적으로 언래핑
아예 타입에 느낌표를 쓰는 방법
- 강제적으로 언래핑되도록 옵셔널을 선언할 수 있다.
- 이 방식으로 옵셔널을 선언하면 강제 언래핑이나 옵셔널 바인딩을 하지 않아도 값에 접근할 수 있다.
- 옵셔널을 선언할 때 물음표(?) 대신에 느낌표(!)를 사용하여 강제적으로 언래핑되도록 하는 것이다.
var index: Int! // 이제 옵셔널은 강제적으로 언래핑된다.
index = 3
var treeArray = ["Oak", "Pine", "Yew", "Birch"]
if index != nil {
print(treeArray[index]) // 이제 index를 언래핑없이 바로 쓸 수 있다.
} else {
print("index does not contain a value")
}
// Birch
- 할당된 값이 없거나 nil을 할당할 수 있는 것은 옵셔널 타입뿐이다.
- 옵셔널이 아닌 변수 또는 상수에는 nil을 할당할 수 없다.
- 다음의 코드는 모두 유효하지 않다. (옵셔널로 선언된 변수가 아니다)
// var myInt = nil // NO
// var myString: String = nil // NO
// let myConstant = nil // NO
Any, AnyObject 와 nil
Any
- 스위프트의 모든 데이터 타입을 사용할 수 있다는 뜻
- 변수 또는 상수의 데이터 타입이 Any로 지정되어 있다면 그 변수 또는 상수에는 어떤 종류의 데이터 타입이든지 상관없이 할당할 수 있다.
var someVar: Any = "dadahae"
someVar = 60 // 가능
someVar = 100.1 // 가능
- 예제 코드 (아래 쪽을 보자)
- (1) : someAny → Int
- 100을 할당했기 때문에 타입 추론으로 Int형이 된다.
- (2) : someAny → String
- 문자열을 재할당했기 때문에 String 형이 된다.
- (3) : someAny → Float
- 실수형 숫자가 재할당되었기 때문에 Float 형이 된다.
- 컴파일 오류…
- Any형인 someAny를 Double 형인 someDouble에 넣을 수 없다..!
- (1) : someAny → Int
var someAny: Any = 100 // (1)
someAny = "어떤 타입도 수용 가능합니다" // (2)
someAny = 123.12 // (3)
let someDouble: Double = someAny // 컴파일 오류
AnyObejct
- Any보다는 조금 한정된 의미
- 클래스와 인스턴스만 할당될 수 있다.
- Any와 AnyObject는 가능한 사용하지 않는 것이 좋다.
- 타입에 엄격한 Swift 언어의 특성상 Any 또는 AnyObject로 선언된 변수의 값을 가져다 쓰려면 배번 타입 확인 및 변환을 해줘야 하는 불편과 예기치 못한 오류의 위험 증가의 문제가 생긴다.
- 타입은 될 수있는 한 정확하게 명시하는 것이 좋다.
nil
- 특정 타입이 아니라 ‘없음’을 나타내는 Swift의 키워드
- 변수 또는 상수에 값이 들어있지 않고 비어있음을 나타내는 데 사용한다.
- nil이면 해당 변수 또는 상수에 접근했을 때 잘못된 메모리 접근으로 런타임 오류가 발생한다.
someAny = nil // 컴파일 오류
someAnyObject = nil // 컴파일 오류
타입 캐스팅과 타입 검사
타입캐스팅 → 욱여넣는다.
타입 캐스팅
Type casting
- Swift 코드를 작성할 때 컴파일러가 어떤 값의 특정 타입을 식별하지 못하는 경우가 발생할 것이다.
- 이런 경우는 메서드나 함수가 반환하는 값이 불분명하거나 예상되지 않은 타입의 값일 때 종종 발생한다.
- 이럴 때는 as 키워드를 사용하여 코드가 의도하는 값의 타입을 컴파일러가 알 수있게 해야 한다. (타입 캐스팅 = 형 변환)
- object(forked:) 메서드가 반환하는 값을 String 타입으로 처리해야 한다고 컴파일러에게 알려줘야 한다면…
let myValue = record.object(forKey: "comment") as! String
업캐스팅
upcasting
- 타입캐스팅의 두 가지 형태 중 하나
- 특정 클래스의 객체가 상위 클래스들 중의 하나로 변형되는 것
- as 키워드를 사용해, 이러한 변환은 성공할 것이라고 줌 - 보장된 변환(guaranteed conversion)
let myButton: UIButton = UIButton()
let myControl = myButton as UIControl
밑에서 위로 간다? 무슨 말이냐면...
클래스들은 상속관계를 가지고 있을 경우 super, sub 으로 상위와 하위 클래스의 관계를 가진다.
어떤 느낌이냐면 아래 그림처럼 큰 항목인 '회사'의 아래에는 '벤츠'라는 회사도 있을 것이고, '현대','기아'와 같은 회사들이 있을 것이다.
여기서 '회사' 클래스는 상위클래스이고 '벤츠', '현대', '기아'는 회사 클래스의 하위 클래스이다.
- as? 를 사용한 옵셔널 바인딩을 사용하면 더 안전하다.
타입 검사
Type check
- is 키워드를 사용하여 타입 검사를 할 수도 있다.
- 다음의 코드는 MyClass라는 이름의 클래스의 인스턴스인지를 검사하는 코드다.
is myObject is MyClass {
// myObject는 MyClass의 인스턴스이다.
}
요약
데이터 타입, 상수, 그리고 변수
- 상수와 변수를 어떻게 선언하는가
- 타입 안정성, 타입 추론, 옵셔널의 개념
- 각각은 Swift 프로그래밍의 핵심 부분으로 오류없는 코드를 만들기 위하여 특별히 제작되었다.
Swift
연산자와 표현식
&&, ||, !, = +, -, /, %, *
목표
연산자와 표현식
- 앞서 배운 것
- 변수와 상수를 어떻게 사용하는가
- 여러 데이터 타입
- 이번에 배울 것
- 코드와 변수와 상수를 어떻게 활용할까
- 변수, 상수와 같은 데이터를 가지고 작업하는 가장 기본적인 방법은 표현식(expression) 형태로 작업하는 것이다.
- 우리가 쓰는 한줄한줄의 문장이 표현식이라고 생각해도 된다.
표현식 구문
Expression
- 하나의 연산자(operator)
- 두 개의 피연산자(operand)
- 할당자(assignment)
- 값 → copy
- call by value / call by reference
var myResult = 1 + 2
- +
- ‘+’ 연산자
- 1과 2를 더하는 데 사용
- =
- ‘=’ 할당 연산자
- 덧셈의 결과를 myResult라는 이름의 변수에 할당한다.
- 1, 2
- 피 연산자
- 숫자 외에도 변수, 상수의 혼합도 가능
기본 할당 연산자
a, the, an …
- 앞서 본 할당 연산자(’=’ 연산자)는 표현식의 결과를 변수에 저장하는 역할을 한다.
- 기본적으로 ‘=’할당 연산자는 두 개의 피 연산자를 받는다.
- 왼쪽의 피연산자 : 값을 할당받는 변수 또는 상수
- 오른쪽의 피연산자 : 할당할 값, 대체로 여러 종류의 산술식이거나 논리식을 수행하는 표현식으로 왼쪽에 그 결과 반영(copy)
var myResult = 1 + 2
- var myResult : 왼쪽의 피연산자(할당 받을 대상)
- 1 + 2 : 오른쪽의 피연산자(할당할 값)
var x: Int? // 옵셔널 Int 변수 선언
var y = 10 // 두번째 Int 변수 선언과 초기화
x = 10 // x에 값 할당
x = x! + y // 언래핑한 x와 y의 합을 x에 할당
x = y // y의 값을 x에 할당
산술 연산자
- Swift는 수학적 표현식을 생성하기 위하여 다양한 연산자를 제공한다.
- 이들 연산자 대부분은 두 개의 피연산자를 받는 이항 연산자(binary operator)다.
- 양수를 음수로 만들어주는 단항 음수 연산자(unary negative operator)는 예외적으로 하나의 피연산자를 받는다.
- 두 개의 피연산자를 받는 뺄셈 연산자(substraction operator)와 대조된다.
var x = -10 // 단향 '-'연산자는 변수 x에 -10을 할당하기 위해 사용한다.
x = x - 5 // 뺄셈 연산자로 x에서 5를 뺀다.
- +, -, *(곱셈), /(나눗셈), 5(몫)
- 하나의 표현식 안에 여러 개의 연산자를 사용할 수도 있다.
x = y * 10 + z - 5 / 4
괄호를 써서 연산의 우선순위를 구분해주자.
복합 할당 연산자
- Swift는 산술 또는 노리 연산과 할당 연산자를 결합하기 위해 설계된 연산자들을 다양하게 제공한다.
- 이러한 연산자들은 연산을 수행한 결과를 피연산자들 중 하나에 저장하기 위해 주로 사용한다.
x = x + y
x += y
// 위 표현식은 모두 같은 의미이다.
비교 연산자
- 스위프트는 비교를 수행하는 데 유용한 논리 연산자들을 가지고 있다.
- 이들 연산자 모두는 비교 결과에 따라 불리언 결과를 반환한다.
- 이들 연산자들은 두 개의 피연산자들을 가지고 작업한다는 점에서 이항연산자(binary operator)이다.
- 비교연산자는 프로그램 흐름 제어 로직을 만드는데 가장 많이 사용된다.
if x == y {
// 작업 수행
}
불리언 논리 연산자
- Swift는 true 또는 false 값을 반환하도록 설계된, 소위 논리 연산자들도 제공한다.
- 이러한 연산자들은 피연산자로 불리언 값을 받아서 불리언 결과를 반환한다.
- NOT (!)
- AND (&&)
- OR (||)
NOT(!) 연산자
- 단순히 불리언 변수의 현재 값 또는 표현식의 결과를 반전시킨다.
- flag라는 이름의 변수가 현재 true라 한다면 변수명 앞에 ! 문자를 두면 값이 false로 바뀔 것이다.
var flag: Bool = true // 변수는 true이다.
var secondFlag = !flag // secondFlag에는 false가 저장된다.
OR(||) 연산자
- 두 개의 피연산자 중 하나가 true라고 판단되면 true를 반환하고
- 두 개의 피연산자 중 어느 것도 true가 아니라면 false를 반환한다.
if (10 < 20) || (20 < 10) { // true 반환: OR 연산자를 기준으로 하나가 true이므로.
print("Expression is true")
}
AND(&&) 연산자
- 두 개의 피연산자 모두 true라고 판단될 때만 true를 반환한다.
if (10 < 20) && (20 < 10) { // false 반환: AND 연산자를 기준으로 모두 false이기 때문
print("Expression is true")
}
범위 연산자
- Swift는 값이 범위를 선언할 수 있도록 하는 몇 가지 연산자가 포함되어 있다.
- 이들 연산자는 프로그램에서 반복 작업을 할 때 매우 중요하다.
- 닫힌 범위 연산자(closed range operator)
- x…y : x로 시작하여 y로 끝나는 숫자의 범위, x와 y는 이 범위에 포한된다.
- 5…8 : 5,6,7,8
- 반 개방 범위 연산자(half-open range operator)
- x..<y : x로 시작하는 모든 숫자를 포함하지만 y는 포함되지 않는다.
- 5..<8 : 5,6,7
- 단방향 범위 연산자(one-sided range operator)
- 그 범위 앞의 시작 또는 끝에 도달할 때까지 (또는 다른 조건이 충족할 때까지) 지정된 범위 방향으로 최대한 확장할 수 있는 범위를 지정한다.
- 범위 선언부의 한쪽 부분을 생략하여 선언한다.
- x…
- …y
- 2… : 예)문자열의 길이와는 상관없이 문자열의 세번째 텍스트부터 시작해서 마지막 문자들까지 지정하는 범위
- …6 : 첫번째부터 7번째까지의 범위
삼항 연산자
- Swift는 코드 내에서 판단을 간단히 하기 위한 방법으로 삼항 연산자(ternary operator)를 지원한다.
조건문 ? 참(true)인 경우의 표현식 : 거짓(false)인 경우의 표현식
- 삼항 연산자의 동작 방식은 true 또는 false를 반환하는 표현식을 ‘조건문’ 위치에 두는 것이다.
- 만약 그 결과가 true이면 ‘참인 경우의 표현식’이 수행된다.
- 만약 그 결과가 false이면 ‘거짓인 경우의 표현식’이 수행된다.
let x = 10
let y = 20
print("Largest number is \\(x > y ? x : y)")
// Largest number is 20
요약
연산자와 표현식
- 다양한 종류의 연산자
- 연산자와 표현식은 Swift 코드 내에서 변수와 상수를 변경하고 판단하는 기본 메커니즘을 제공한다.
- 가장 간단한 형태로는 덧셈 연산자를 이용하여 두 개의 숫자를 더하고 할당 연산자를 이용하여 그 결과를 변수에 저장하는 것이다.
'외부활동 > 멋사 앱스쿨 1기' 카테고리의 다른 글
[TIL] 22-09-26: Swift (함수, 메서드, 클로저) (0) | 2022.09.26 |
---|---|
[TIL] 22-09-23: 오픈소스, Swift(반복문, 조건문) (0) | 2022.09.24 |
[TIL] 22-09-21: Swift 사전 지식(데이터타입/변수/상수/튜플) (1) | 2022.09.24 |
[TIL❌결석] 22-09-20: CS기초(알고리즘) (0) | 2022.09.23 |
[TIL] 22-09-19: 스프린트회고, Swift Tour (1) | 2022.09.23 |