Notice
Recent Posts
Recent Comments
Link
«   2024/07   »
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 31
Archives
Today
Total
관리 메뉴

브래의 슬기로운 코딩 생활

iOS 프로그래밍 실무 2주차 정리 본문

2-1/iOS프로그래밍 실무

iOS 프로그래밍 실무 2주차 정리

김브래 2023. 3. 12. 16:24

이번 주차는 엠티 때문에 동영상 강의로 대체되었다.

주된 내용은 지난학기에 배운 내용 복습이었다.

 

데이터 타입(자료형, 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!

 

 

 

질문: 닐 합병 연산자를 이용하는 것도 옵셔널 바인딩이라고 할 수 있나요?