브래의 슬기로운 코딩 생활
iOS 프로그래밍 실무 2주차 정리 본문
이번 주차는 엠티 때문에 동영상 강의로 대체되었다.
주된 내용은 지난학기에 배운 내용 복습이었다.
데이터 타입(자료형, data type)
Bool, Character, Int, Float, Double, String, Void
자료형의 종류와 크기가 궁금해요
var x = 10
print(type(of:x))
let s = MemoryLayout.size(ofValue: x)//8
일반적으로 초깃값을 주지 않을 경우에만 자료형을 씀
정수 데이터 타입 : Int
\(출력하고 싶은 변수나 상수)
부동 소수점 데이터 타입: Double
부울 데이터 타입 : Bool
문자 데이터 타입 : Character
주의 : 초깃값은 작은 따옴표가 아니고 큰 따옴표
var myChar3 : Character = "X"
주의 여기서 : Character 생략불가, 생략하면 String형으로 인식
문자열 데이터 타입 : String
특수 문자/이스케이프 시퀀스
일반적으로 많이 사용되는 특수 문자
\n ― 개행
\r ― 캐리지 리턴(carriage return)
\t ― 수평 탭
\\ ― 역슬래시
\" ― 큰따옴표(문자열 선언부에 큰따옴표를 쓰고 싶을 경우에 사용됨)
\' ― 작은따옴표(문자열 선언부에 작은따옴표를 쓰고 싶을 경우에 사용됨)
\u{nn} ― nn 위치에 유니코드 문자를 표현하는 두 개의 16진수가 배치되는 1바이트 유니코드 스칼라
\u{nnnn} ― nnnn 위치에 유니코드 문자를 표현하는 네 개의 16진수가 배치되는 2바이트 유니코드 스칼라
\U{nnnnnnnn} ― nnnnnnnn 위치에 유니코드 문자를 표현하는 네 개의 16진수가 배치되는 4바이트 유니코드 스칼라
변수 : var / 상수 : let
타입 어노테이션과 타입 추론
var userCount : Int = 10 // : Int가 type annotation
선언부에 타입 어노테이션이 없으면 스위프트 컴파일러는 상수 또는 변수의 타입을 식별하기 위하여 타입 추론(type inference) 사용
튜플(Tuple)
여러 값을 하나의 개체에 일시적으로 묶는 방법
let myTuple = (10, 12.1, "Hi")
typealias Void = ()
함수(메서드)를 선언할 때 반환 값이 없으면 반환형을 지정할 필요 없음
그러나 함수, 메서드 또는 클로저의 형(type)에는 반환형 반드시 작성
func logMessage(_ s: String) { // {앞에 ->Void나 ->() 생략
print("Message: \(s)")
}
let logger: (String) -> Void = logMessage //여기서 ->Void는 생략 불가
logger("Hello")
옵셔널(optional)
값을 반환할 때 오류가 발생할 가능성이 있는 값은 옵셔널 타입이라는 객체로 감싸서 반환함
- Int("100") // 100이 아닌 Optional(100)을 리턴함,print(Int("100")), Int형 initializer
- Int("Hi") // 정수 값을 반환할 수 없음, 아무런 값도 반환할 수 없다는 의미로 nil을 반환
- Swift에서 기본 자료형(Int, Double, String 등)은 nil값을 저장할 수 없음
- nil도 저장하려면 옵셔널 타입으로 선언해야 함
옵셔널 타입 강제 언래핑(forced unwrapping)
강제 추출 연산자 !는 피연산자와 꽉 묶이는(tightly associates) 높은 우선순위를 가진다.
즉, 대부분의 다른 연산자보다 먼저 계산되며, 다른 연산자와 함께 사용되는 표현식에서는 피연산자에 밀접하게(bind tightly) 결합되어, 표현식에서 다른 연산자와는 무관하게 즉시 적용된다.
예를 들어, let x = optionalValue! + 5 표현식에서 강제 추출 연산자 !는 덧셈 연산자 +보다 높은 우선순위를 가지므로, 옵셔널 값이 5에 더해지기 전에 먼저 추출된다.
그러나 옵셔널 값이 nil인 경우 런타임 오류가 발생할 수 있으므로, 가능한한 강제 추출 대신 옵셔널 바인딩 또는 옵셔널 체인을 사용하는 것이 좋다.
이렇게 하면 코드를 보다 견고하게 만들어 crash를 피할 수 있다
optional binding
if let constantName = optionalName{
//옵셔널 변수가 값이 있다면 언래핑해서 일반 상수 constantName에 대입하고 if문 실행
//값이 없다면 if문의 조건이 거짓이 되어 if문을 실행하지 않음
}
if var variableName = optionalName {
//옵셔널 변수가 값이 있다면 언래핑해서 일반 변수 varibleName에 대입하고 if문 실행
//값이 없다면 if문의 조건이 거짓이 되어 if문을 실행하지 않음
}
두 가지 옵셔널 타입
암묵적인 언래핑으로 옵셔널을 선언하기 위해서는 선언부에 물음표(?) 대신에 느낌표(!)를 사용
- var x : Int? //옵셔널 변수 선언방법 1
- var y : Int! //옵셔널 변수 선언방법 2
Implicitly Unwrapped Optional
- 형 다음에 ?가 아닌 !를 쓰는 옵셔널 형
- 일반 옵셔널 값으로 사용하려고 하지만, optional로 사용할 수 없는 경우 Swift는 값을 강제로 푼다.
- Optional로 사용되지 않으면 자동으로 unwrap한다.
왜 옵셔널을 사용하나요?
- 옵셔널 타입만이 값을 갖지 않는다는 의미의 nil 값을 가질 수 있음
nil
- 옵셔널 변수에 nil을 할당하면 값이 없는 상태가 된다
- 상수나 변수가 값이 없는 상태가 존재한다면 옵셔널 타입으로 선언해야 한다.
옵셔널 변수와 nil
옵셔널 변수에 초깃값을 할당하지 않으면 자동으로 nil이 할당됨
- var surveyAnswer: String? // surveyAnswer is automatically set to nil
Any와 AnyObject
AnyObject(protocol)
- 범용 타입
- 모든 클래스가 암시적으로 준수하는 프로토콜임
- 상속관계가 아니라도 타입 캐스팅 가능한 타입
- 어떤 클래스의 객체도 저장 가능
- 가장 추상화된 최상위 개념(Obj-C의 id)
- 클래스만 허용하며 구조체나 열거형은 허용하지 않음
Any
- 클래스, 구조체, 열거형, 함수타입도 가능
AnyObject 예제
class Person {
var name: String = "HAN"
}
let han: AnyObject = Person()
//모든 클래스가 암시적으로 준수하는 프로토콜
let han2 = han as! Person // 부모인스턴스 as! 자식클래스
print(han2.name)
if let han1 = han as? Person {
print(han1.name)
}
연산자(operator)
연산자의 우선순위와 결합성
기본 할당 연산자
var x: Int? // 옵셔널 Int 변수를 선언함
var y = 10 // 일반 Int 변수를 선언하고 초기화함
x = 10 // 값을 x에 할당함, Optional(10)
x = x! + y // x + y의 결과를 x에 할당함, Optional(20)
x = y // y의 값을 x에 할당함, Optional(10)
산술 연산자
- (단항) 변수 또는 표현식의 값을 음수로 만듦
* 곱셈
/ 나눗셈
+ 덧셈
- 뺄셈
% 나머지 연산
복합 할당 연산자
x += y x와 y를 더하고 그 결과를 x에 할당
x -= y x에서 y를 빼고 그 결과를 x에 할당
x *= y x와 y를 곱하고 그 결과를 x에 할당
x /= y x를 y로 나누고 그 결과를 x에 할당
x %= y x를 y로 나눈 나머지를 x에 할당
x &= y x와 y의 bit AND 연산 결과를 x에 할당
x |= y x와 y의 bit OR 연산 결과를 x에 할당
증가 연산자와 감소 연산자
x = x + 1 // x 변수의 값을 1 증가시킴
x = x - 1 // x 변수의 값을 1 감소시킴
이러한 방법 대신 ++ 연산자와 --연산자를 사용할 수도 있었음
x++ // x를 1 증가시킴, Swift 3에서 없어짐, x+=1
x-- // x를 1 감소시킴, Swift 3에서 없어짐, x-=1
비교 연산자
비교의 결과로 불리언(Boolean) 값을 반환
x == y x와 y가 같다면 true를 반환
x > y x가 y보다 크면 true를 반환
x >= y x가 y보다 크거나 같다면 true를 반환
x < y x가 y보다 작다면 true를 반환
x <= y x가 y보다 작거나 같다면 true를 반환
x != y x와 y가 같지 않다면 true를 반환
== operator checks if their instance values are equal, "equal to"
=== operator checks if the references point the same instance, "identical to"
불리언 논리 연산자
NOT(!), AND(&&), OR(||)와 XOR(^)
범위 연산자
- 닫힌 범위 연산자(closed range operator)
x...y
x에서 시작하여 y로 끝나는 범위에 포함된 숫자
- 반 열린 범위 연산자(half-open range operator)
x..<y
x부터 시작하여 y가 포함되지 않는 모든 숫자
- One-Sided Ranges
let names = ["A", "B", "C", "D"]
for name in names[2...] { //[...2], [..<2]
print(name)
} // C
// D
삼항 연산자 ?:
[조건] ? [참 표현식] : [거짓 표현식]
Nil-Coalescing Operator (Nil합병연산자) ??
옵셔널변수 ?? nil일 때 할당되는 값
let defaultColor = "black"
var userDefinedColor: String? // defaults to nil
var myColor = userDefinedColor ?? defaultColor
//nil이므로 defaultColor인 black으로 할당됨
print(myColor) //black
userDefinedColor = "red"
myColor = userDefinedColor ?? defaultColor
//nil이 아니므로 원래 값인 red가 할당됨
print(myColor) //red, 주의 optional(red)가 아님
형 변환(as로 upcasting)
상속 관계가 있는 클래스들끼리만 타입 캐스팅 가능
자식인스턴스 as 부모클래스 // upcasting 안전한 캐스팅. 자식이 추상화됨
형 변환(as! as?로 downcasting)
- 다운캐스팅은 부모 인스턴스를 자식 클래스로 변환하는 데 사용
- 성공 확신이 있으면 as! 키워드를 사용하며 강제 변환(forced conversion) - 변환이 안되면 crash
- 성공 확신이 없으면 as?를 사용하여 안전하게 변환 - 변환이 안되면 nil을 리턴하므로 옵셔널 타입으로 반환함
부모인스턴스 as! 자식클래스 // downcasting 일반 타입으로 반환, 다운캐스팅이 반드시 성공할 것이라는 확신이 있을 때
부모인스턴스 as? 자식클래스 // downcasting 옵셔널 타입으로 반환. 확신이 없을 경우
타입 검사(is)
타입 검사(type check)
let x = 1
if x is Int {
print("Int!")
} //Int!
객체가 MyClass라는 이름의 클래스의 인스턴스인지 검사
인스턴스가 해당 클래스인가?
- 인스턴스 is 클래스
if myobject is MyClass {
// myobject는 MyClass의 인스턴스이다
}
class A {}
let a = A()
if a is A{
print("Yes")
}
연산자의 우선순위와 결합성
과제
int형도 구조체로 되어있다
var x : Int
x =1090
//주의 error '=' must have consistent whitespace on both sides, '=' 양쪽에 일관된 공백
//1090
print(x) // 실습: print()함수 사용법 구글링과 실행 결과를 주석으로 달기
// swift
// Copy code
// print("출력할 텍스트")
// 예를 들어, "Hello, World!"를 출력하려면 다음과 같이 작성합니다.
// swift
// Copy code
// print("Hello, World!")
// 출력 결과는 다음과 같습니다.
// Hello, World!
// 출력할 내용이 여러 줄일 경우, 다음과 같이 줄바꿈 문자("\n")를 사용하여 여러 줄에 걸쳐 출력할 수 있습니다.
// swift
// Copy code
// print("첫 번째 줄\n두 번째 줄\n세 번째 줄")
// 출력 결과는 다음과 같습니다.
// 첫 번째 줄
// 두 번째 줄
// 세 번째 줄
// 또한, "print" 함수를 사용하여 변수나 상수의 값을 출력할 수도 있습니다.
// swift
// Copy code
// let name = "John"
// print("내 이름은 \(name)입니다.")
// 출력 결과는 다음과 같습니다.
// 내 이름은 John입니다.
// 이처럼, "print" 함수는 스위프트에서 매우 유용한 함수 중 하나입니다.
구글링 실습: 자료형의 종류와 크기
스위프트는 여러 가지 자료형을 제공합니다. 각 자료형은 특정한 종류의 값을 저장하는 데 사용됩니다. 스위프트에서 제공하는 자료형과 그 크기는 다음과 같습니다.
Int: 부호 있는 정수형, 32비트 또는 64비트
UInt: 부호 없는 정수형, 32비트 또는 64비트
Float: 부동 소수점 수, 32비트
Double: 부동 소수점 수, 64비트
Bool: 불리언, 1바이트
String: 문자열, 문자의 개수에 따라 다름
Character: 문자, 1바이트
자료형의 크기를 구하는 방법은 언어에 따라 다르지만, 스위프트에서는 MemoryLayout<T> 구조체를 사용하여 자료형의 크기를 구할 수 있습니다. 예를 들어, Int 자료형의 크기를 구하려면 다음과 같이 코드를 작성합니다.
swift
Copy code
let intSize = MemoryLayout<Int>.size
print(intSize)
이 코드는 Int 자료형의 크기를 바이트 단위로 출력합니다. 이와 같은 방법으로 다른 자료형의 크기도 구할 수 있습니다.
var x =""
print(type(of:x))
let s = MemoryLayout.size(ofValue: x)
let t = MemoryLayout<Int>.size
print(s, t)
//String
//16 8
일반적으로 초깃값을 주지 않을 경우에만 자료형을 쓴다.
var x : Int =1090
print(x)
print("x")
print("\(x)")
print("값은 \(x)입니다.")
print("Int64 Min = \(Int64.min) Int64 Max = \(Int64.max)")
// 1090
// x
// 1090
// 값은 1090입니다.
// Int64 Min = -9223372036854775808 Int64 Max = 9223372036854775807
var myChar3 : Character ="X"
주의 여기서 : Character 생략불가, 생략하면 String형으로 인식
let myTuple = (10, 12.1, "김동현")
var myString = myTuple.2
print(myString) //출력되는 값은? 김동현
print(type(of:myTuple))//(Int, Double, String)
let myTuple = (count: 10, length: 12.1, message: "Hi") //과제 : myTuple의 자료형
print(type(of:myTuple))//(count: Int, length: Double, message: String)
func logMessage(_ s: String) { // {앞에 ->Void나 ->() 생략
print("Message: \(s)")
}
let logger: (String) ->Void = logMessage //여기서 ->Void는 생략 불가
logger("Hello")//Message: Hello
var y : Int? =5 //y?
var z : Int!//z?
print(y)
print(z)
// Optional(5)
// nil
강제 추출 연산자 !는 피연산자와 꽉 묶이는(tightly associates) 높은 우선순위를 가진다.
즉, 대부분의 다른 연산자보다 먼저 계산되며, 다른 연산자와 함께 사용되는 표현식에서는
피연산자에 밀접하게(bind tightly) 결합되어, 표현식에서 다른 연산자와는 무관하게 즉시
적용된다.
예를 들어, let x = optionalValue! + 5 표현식에서 강제 추출 연산자 !는 덧셈 연산자
+보다 높은 우선순위를 가지므로, 옵셔널 값이 5에 더해지기 전에 먼저 추출된다.
그러나 옵셔널 값이 nil인 경우 런타임 오류가 발생할 수 있으므로, 가능한한 강제 추출
대신 옵셔널 바인딩 또는 옵셔널 체인을 사용하는 것이 좋다.
이렇게 하면 코드를 보다 견고하게 만들어 crash를 피할 수 있다.
optional binding
if let constantName = optionalName{
//옵셔널 변수가 값이 있다면 언래핑해서 일반 상수 constantName에 대입하고 if문 실행
//값이 없다면 if문의 조건이 거짓이 되어 if문을 실행하지 않음
}
if var variableName = optionalName {
//옵셔널 변수가 값이 있다면 언래핑해서 일반 변수 varibleName에 대입하고 if문 실행
//값이 없다면 if문의 조건이 거짓이 되어 if문을 실행하지 않음
}
var x : Int?
x =10
if let xx = x { //옵셔널 변수 x가 값(10)이 있으므로 언래핑해서 일반 상수 xx에 대입하고 if문 실행
print(x,xx)
}
else {
print("nil")
}
var x1 : Int?
if let xx = x1 { //옵셔널 변수 x1이 값이 없어서 if문의 조건이 거짓이 되어 if문 실행하지 않고 else로 감
print(xx)
}
else {
print("nil")
}
Swift 5.7부터는 if let x 라고 써도 됨
//short form of if-let to the Optional Binding
var pet1: String?
var pet2: String?
pet1 ="cat"
pet2 ="dog"
if let pet1, let pet2 {
print(pet1, pet2)
} else {
print("nil")
}
Any
var x: Any ="Hi"
print(x, type(of:x))
x =10
print(x, type(of:x))
x =3.5
print(x, type(of:x))
// Hi String
// 10 Int
// 3.5 Double
let names = ["오", "이", "시", "쿠", "나", "레"]
for name in names[3...] {
print(name)
}
// 나
// 레
let defaultAge =1
var age : Int?
age =3
print(age) //Optional(3)
var myAge = age ?? defaultAge
print(myAge) //3
let defaultColor ="black"
var userDefinedColor: String? // defaults to nil
var myColor = userDefinedColor ?? defaultColor
print(myColor) //black
userDefinedColor ="red"
myColor = userDefinedColor ?? defaultColor
print(myColor)
//black
//red
상속 관계 클래스 끼리는 형 변환이 가능하다.
var x : Any ="Hi"
print(x, type(of:x))
x =10
var y : Int = x as!Int
var z : Int? = x as? Int
print(x, type(of:x))
print(y, type(of:y))
print(z, type(of:z))
// Hi String
// 10 Int
// 10 Int
// Optional(10) Optional<Int>
타입검사
let x =1
if x is Int {
print("Int!")
} //Int!
질문: 닐 합병 연산자를 이용하는 것도 옵셔널 바인딩이라고 할 수 있나요?
'2-1 > iOS프로그래밍 실무' 카테고리의 다른 글
iOS프로그래밍 실무 6주차 정리 (0) | 2023.04.12 |
---|---|
iOS프로그래밍 실무 5주차 정리 (0) | 2023.04.05 |
iOS프로그래밍 실무 4주차 정리 (0) | 2023.03.29 |
iOS프로그래밍 실무 3주차 정리 (0) | 2023.03.22 |
iOS프로그래밍 실무 1주차 정리 (0) | 2023.03.08 |