📱 모바일 프로그래밍/iOS 프로그래밍 실무
iOS 프로그래밍 실무 2주차
SA성아
2025. 3. 17. 22:05
- var x= 10 // err
주의: = 양쪽의 공백이 같아야 한다.
자료형의 종류와 크기가 궁금해요
- 종류
var x = 10
print(type(of:x)) // Int
- 크기
let s = MemoryLayout.size(ofValue: x)//8
let t = MemoryLayout<Int>.size
print(s, t)
//swift memory size
자료형
자료형 | 설명 | 예시 |
Int | 정수형 | let age: Int = 25 |
Double | 배정밀도 부동소수점형 | let height: Double = 1.75 |
Float | 단정밀도 부동소수점형 | let weight: Float = 65.5 |
String | 문자열형 | let name: String = "홍길동" |
Bool | 불리언형 (참/거짓) | let isStudent: Bool = true |
Array | 배열형 (같은 자료형의 집합) | let scores: [Int] = [90, 85, 78] |
Dictionary | 키-값 쌍의 집합 | let person: [String: String] = ["name": "홍길동", "city": "서울"] |
Set | 중복 없는 집합 | let uniqueNumbers: Set<Int> = [1, 2, 3, 1] |
\(출력하고 싶은 변수나 상수)
var x : Int = 10
print(x); // 10
print("x"); // x
print("\(x)"); // 10
print("값은 \(x)입니다."); // 값은 10입니다.
과제 : Int형의 min과 max는?
print("Int32 Min = \(Int32.min) Int32 Max = \(Int32.max)")
// Int32 Min = -2147483648 Int32 Max = 2147483647
부동 소수점 데이터 타입: Double vs Float
var myWeight = 58.5
print(type(of:myWeight)) // Double
부울 데이터 타입 : Bool
var orangesAreOrange : Bool = true
print(orangesAreOrange) // true
문자 데이터 타입: Character
var myChar1 : Character
var myChar2 : Character = ":"
var myChar3 : Character = "X"
Character 생략불가, 생략하면 String형으로 인식
var myChar4 = "\u{0058}"
print(myChar4) // x
문자열 데이터 타입 : String
var userName : String = "Kim" // : String 생략하는 것이 일반적임
var age = 20
var message = "\(userName)의 나이는 \(age)입니다."
print(message) // Kim의 나이는 20입니다.
상수와 변수 선언하기
- 변수는 var 키워드를 이용하여 선언되며, 변수를 생성할 때에 값을 가지고 초기화할 수도 있음
var userCount = 10
var userCount : Int?
- 상수는 let 키워드를 사용하여 선언, 선언하는 시점에서 상수에 값이 할당되어 초기화되고, 할당된 값을 수정할 수 없음
let maxUserCount = 20
maxUserCount = 30 // err
let maximumNumber = 10
let π = 3.14159
let 🐶🐮 = "dogcow"
변수나 상수 명은 영문자, 숫자, Unicode(이모티콘, 중국어, 한글 등)도 가능
상수의 값 할당
- 상수를 선언할 때도 타입 어노테이션을 사용하면 나중에 코드에서 값을 할당할 수 있음
let bookTitle: String
var book = true
if book {
bookTitle = "iOS"
} else {
bookTitle = "Android"
}
print(bookTitle) // iOS
튜플(Tuple)
let myTuple = (10, 12.1, "Hi")
- 여러 값을 하나의 개체에 일시적으로 묶는 방법
let myTuple = (10, 12.1, "Hi")
var myString = myTuple.2
print(myString) // Hi
- 인덱스 2 위치를 추출하고 그 값을 새로운 문자열 변수에 할당
let myTuple = (10, 12.1, "Hi")
let (myInt, myFloat, myString) = myTuple
print(type(of:myTuple)) // (Int, Double, String)
let myTuple = (count: 10, length: 12.1, message: "Hi" )
print(type(of:myTuple)) // (count: Int, length: Double, message: String)
print(myTuple.message, myTuple.2) // Hi Hi
typealias Void = ()
- ()는 빈 튜플(empty tuple)
- 함수(메서드)를 선언할 때 반환 값이 없으면 반환형을 지정할 필요 없음
- 그러나 함수, 메서드 또는 클로저의 형(type)에는 반환형 반드시 작성
- 리턴값이 없는 함수의 형을 작성할 때는 반드시 Void 지정
- 반환값이 없는 클로저, 함수(메서드)를 선언할 때는 Void나 빈 튜플(())을 반환 형으로 사용
func logMessage(_ s: String) { // {앞에 ->Void나 ->() 생략
print("Message: \(s)") // Message: Hello
}
let logger: (String)->Void = logMessage //여기서는 함수 자료형이라 ->Void 생략 불가
logger("Hello")
Int형 vs Optional Int형
var x : Int = 10
print(x) // 출력: 10
var y : Int? = 20
print(y) // 출력: Optional(20)
Optional 변수 선언
: 자료형 뒤에 물음표(?)를 붙인다.
사용하려면 풀어야함
푸는 방법
: 변수뒤에 느낌표(!)
var y : Int?
print(y) // 출력: nil
- nil: 값이 없다
var y : Int?
print(y!)
- error: Execution was interrupted, reason: EXC_BREAKPOINT (code=1, subcode=0x105fb7200).
- 값이 있을 때만 풀 수 있다.
var y : Int? = 20
y = y! + 1
print(y) // 출력: Optional(21)
- Optional 변수는 그냥 사용하지 못하고 풀어서 사용해야 한다.
- 푸는 방법은 !를 붙이는 것이고, 마지막에 들어갈 때는 Optional로 들어간다.
optional binding
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")
}
// 출력
// Optional(10) 10
// nil
- if let x = x 라고 써도 됨
- Swift 5.7부터는 if let x라고 써도 됨 - short form of if-let to the Optional Binding
Optional binding(여러 옵셔널 값 동시에 언래핑)
var x : Int?
var y : Int?
x = 10
y = 20
if let xx = x, let yy = y {
print(xx, yy)
}
else {
print("nil")
}
중요:옵셔널을 언래핑하는 여러가지 방법(guard-let제외)
var x : String? = "Hi"
// forced unwrapping : unsafe
print(x!) // Hi
// optional binding : safe
if let a = x {
print(a) // Hi
}
// nil coalescing operator : safe
let c = x ?? ""
print(c) // Hi
// optional chaining : safe
// 옵셔널 변수 다음에 물음표하는 것을 옵셔널 체이닝이라 함
// String 구조체의 count 프로퍼티는 문자의 개수
let b = x?.count
Implicitly Unwrapped Optional
var x : Int? = 10
var y : Int! = 20
var z : Int = 1
print(x, y, z) // Optional(10), Optional(20), 1
z = x!
print(z) // 10
z = y
print(z) // 20
if let x, let y {
print(x, y) // 10, 20
}
- 형 다음에 ?가 아닌 !를 쓰는 옵셔널 형
- 먼저 일반 옵셔널 값으로 사용하려고 하지만, optional로 사용할 . 수없는 경우 Swift는 값을 자동으로 강제로 품
- Optional로 사용할 수 없으면 자동으로 unwrap함
두 가지 Optional 형 : Int? vs Int!
let x : Int? = 1
let y : Int = x! // 강제 언래핑
let z = x //
print(x,y,z) // Optional(1) 1 Optional(1)
print(type(of:x),type(of:y),type(of:z))
// Optional<Int> Int Optional<Int>
let a : Int! = 1 // Implicitly Unwrapped Optional
let b : Int = a //Optional로 사용되지 않으면 자동으로 unwrap함
let c : Int = a!
let d = a //Optional로 사용될 수 있으므로 Optional형임
let e = a + 1
print(a,b,c,d,e) // Optional(1) 1 1 Optional(1) 2
print(type(of:a),type(of:b),type(of:c),type(of:d),type(of:e))
// Optional<Int> Int Int Optional<Int> Int
Int!형을 property로 갖는 클래스
class MyAge {
var age : Int!
init(age: Int) {
self.age = age
}
func printAge() {
print(age) // Optional(1)
print(age + 1) // 2
let age1 : Int = age
print(age1) // 1
let age2 = age + 2
print(age2) // 3
}
}
var han = MyAge(age:1)
han.printAge()
nil
- 상수나 변수가 값이 없는 상태가 존재한다면 옵셔널 타입으로 선언
- 옵셔널 변수에 초깃값을 할당하지 않으면 자동으로 nil이 할당됨
y, z 값은 nil
var x : Int // 항상 값이 존재
var y : Int? // 옵셔널 변수, 값이 없을 수도 있음
var z : Int! // 옵셔널 변수, 값이 없을 수도 있음
옵셔널은 연관 값(associated value)을 갖는 enum
var x : Int? = 20 //.some(20)
var y : Int? = Optional.some(10)
var z : Int? = Optional.none
var x1 : Optional<Int> = 30
print(x, y, z, x1) // Optional(20) Optional(10) nil Optional(30)
Any와 AnyObject
var x: Any = "Hi"
print(x, type(of:x)) // Hi String
x = 10
print(x, type(of:x)) // 10 Int
x = 3.5
print(x, type(of:x)) // 3.5 Double
대입 연산자
- 왼쪽에 있는 피연산자는 값이 할당되는 변수 또는 상수이며, 오른쪽에 있는 피연산자는 할당할 값
- 오른쪽 피연산자는 주로 산술식 또는 논리식을 수행하는 표현식이며, 그 결과는 왼쪽 피연산자인 변수나 상수에 할당
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 = x + 1 // x변수의 값을 1 증가시킴
x = x - 1 // x변수의 값을 1 감소시킴
위의 표현식은 x의 값을 1 증감
이러한 방법 대신 ++ 연산자와 --연산자를 사용할 수도 있었음
Swift 3에서 없어짐
// Swift
x += 1
x -= 1
비교 연산자
비교의 결과로 불리언(Boolean) 값을 반환
불리언 논리 연산자
NOT(!), AND(&&), OR(||), XOR(^)
범위 연산자
- 닫힌 범위 연산자(closed range operator)
- 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 Ranges
let names = ["A", "B", "C", "D"]
for name in names[...2]
print(name)
}
// A
// B
// C
let names = ["A", "B", "C", "D"]
for name in names[..<2] {
print(name)
}
// A
// B
삼항 연산자 ?:
var x = 1
var y = 2
print("더 큰 값은 \(x > y ? x : y)") // 더 큰 값은 2
nil-coalescing operator(nil병합연산자) ??
var x : Int? //= 10
var y : Int = 0
y = x ?? 1
print(x, y) // nil, 1
let defaultAge = 1
var age : Int?
age = 20
print(age) // optional(20)
var myAge = age ?? defaultAge
//age가 nil이 아니므로 언래핑된 값이 나옴
print(myAge) // 20
var x : Int? = 1
var y = x ?? 0
print(y) // 1
클래스 vs. 객체 vs. 인스턴스
for-in 반복문
- for 문 다음의 실행 코드가 한 줄이라도 괄호({})를 필수적으로 사용
for index in 1...5 {
print(index)
}
// 1
// 2
// 3
// 4
// 5
_로 참조체(i) 생략 가능
for i in 1...5 {
print("\(i) 안녕")
}
// 1 안녕
// 2 안녕
// 3 안녕
// 4 안녕
// 5 안녕
for _ in 1...5 {
print("안녕")
}
// 안녕
// 안녕
// 안녕
// 안녕
// 안녕
배열의 항목 접근
let names = ["A", "B", "C", "D"]
for name in names {
print(name)
}
// A
// B
// C
// D
dictionary의 항목 접근
let numberOfLegs = ["Spider": 8, "Ant": 6, "Dog": 4]
//dictionary는 key:value형식의 배열
for (animalName, legCount) in numberOfLegs {
print("\(animalName)s have \(legCount) legs")
}
// Spiders have 8 legs
// Ants have 6 legs
// Dogs have 4 legs
while 반복문
var myCount = 0
while myCount < 1000 {
myCount+=1
}
print(myCount) // 1000
repeat~while 반복문
var i = 10
repeat {
i=i-1
print(i) // 4 3 2 1 0
} while (i > 0)
반복문에서 빠져나오기(break)
- if 문 다음의 실행 코드가 한 줄이라도 괄호({})를 필수적으로 사용
for i in 1..<10 {
if i > 5 {
break
}
print(i) // 1 2 3 4 5
}
continue문
for i in 1...10 {
if i % 2 == 0 {
continue
}
print(i) // 1 3 5 7 9
}
if문
- if 문 다음의 실행 코드가 한 줄이라도 괄호({})를 필수적으로 사용
var x = 10
if x > 5 {
print("5보다 큽니다") // 5보다 큽니다
}
if문 조건에서 콤마:조건나열(condition-list)
var x = 1
var y = 2
if x == 1 && y==2 { //논리식이 둘 다 참일 때
print(x,y) // 1 2
}
if x == 1, y==2 { //조건이 둘 다 참일 때, 두 조건을 콤마로 연결한 condition-list
print(x,y) // 1 2
}
var a : Int? = 1
var b : Int? = 2
print(a,b) // Optional(1) Optional(2)
if let a1=a, let b1=b { //a와 b가 nil이 아니면, 언래핑하여 a1과 b1에 대입
print(a1,b1) /; 1 2
}
if~else문
var x = 3
if x % 2 == 0 {
print("짝수입니다")
}else{
print("홀수입니다") // 홀수입니다
}
다중 if-else문
var num = 4
if num == 1 || num == 3 {
print("당신은 남성이군요!\n")
}else if num == 2 || num == 4 {
print("당신은 여성이군요!\n")
}else {
print("당신은 대한민국 사람이 아니군요!\n")
}
// 당신은 여성이군요!
다중 if-else문 : BMI 계산 결과 판정
let weight = 60.0
let height = 170.0
let bmi = weight / (height*height*0.0001) // kg/m*m
var body = ""
if bmi >= 40 {
body = "3단계 비만"
} else if bmi >= 30 && bmi < 40 {
body = "2단계 비만"
} else if bmi >= 25 && bmi < 30 {
body = "1단계 비만"
} else if bmi >= 18.5 && bmi < 25 {
body = "정상"
} else {
body = "저체중"
}
print("BMI:\(bmi), 판정:\(body)")
switch - case
let weight = 60.0
let height = 170.0
let bmi = weight / (height * height * 0.0001) // kg/m*m
var body = ""
switch bmi {
case ..<18.5:
body = "저체중"
case 18.5..<25:
body = "정상"
case 25..<30:
body = "1단계 비만"
case 30..<40:
body = "2단계 비만"
default:
body = "3단계 비만"
}
print("BMI:\(bmi), 판정:\(body)")
// BMI:20.761245674740486, 판정:정상
if ~ let vs. guard ~ let: guard let이 소스 보기가 편해요
func printName(firstName:String, lastName:String?) {
// if let
if let lName = lastName { // lastName이 nil이 아니면
print(lName, firstName)
}
else {
print("성이 없네요")
}
}
printName(firstName: "길동", lastName: "홍")
// 홍 길동: lastName이 홍이 전달돼 if문 실행
printName(firstName: "길동", lastName: nil)
// 성이 없네요: lastName이 nil이 전달돼 else문 실행
func printName(firstName:String, lastName:String?) {
// guard let
guard let lName = lastName else { // lastName이 nil이면
print("성이 없네요!")
return // early exit
}
print(lName, firstName)
}
printName(firstName: "길동", lastName: "홍")
// 홍 길동: lastName이 홍이 전달돼 print(lName, firstName) 출력
printName(firstName: "길동", lastName: nil)
// 성이 없네요!: lastName이 nil전달돼 print("성이 없네요!") 출력
guard let~else로 옵셔널 바인딩
func multiplyByTen(value: Int?) {
if let number = value {
print(number*10)
}
else {
print("nil")
}
}
multiplyByTen(value: 3) // 30
multiplyByTen(value: nil) // nil
func multiplyByTen(value: Int?) {
guard let number = value else { //조건식이 거짓(nil)일 때 else 블록 실행
print("nil")
return
}
print(number*10) //조건식이 참일 때 실행, 주의 : number를 guard문 밖인 여기서도 사용 가능
}
multiplyByTen(value: 3) // 30
- 언래핑된 number 변수를 guard문 밖에 있는 코드가 사용할 수 있다!
switch-case문 예제
var value = 0
switch (value)
{
case 0:
print("영")
case 1:
print("일")
case 2:
print("이")
case 3:
print("삼")
default:
print("4이상")
}
// 영
let someCharacter: Character = "z"
switch someCharacter {
case "a":
print("The first letter of the alphabet")
case "z":
print("The last letter of the alphabet")
default:
print("Some other character")
}
// The last letter of the alphabet
- switch-case문 주의 사항
let anotherCharacter: Character = "a"
switch anotherCharacter {
case "a": // 에러, case 다음에 실행문이 없음
case "A":
print("A글자")
default:
print("A글자 아님")
}
- switch-case문 결합하기 : 콤마 사용
var value = 3
var days : Int = 0
switch(value)
{
case 1,3,5,7,8,10,12:
print("31 일입니다")
case 4,6,9,11:
print("30 일입니다")
case 2:
print("28 or 29 일입니다")
default:
print("월을 잘못 입력하셨습니다")
} // 31일 입니다
- switch-case문에서의 범위 지정 매칭
let num = 25
let count : String
switch num {
case 0...9:
count = "한자리 수"
case 10...99:
count = "두자리 수"
case 100...999:
count = "세자리 수"
default:
count = "네자리 수 이상"
}
print("\(count)입니다.") // 두자리 수 입니다
- switch-case에서 where절 사용하기
where : 조건을 추가
var temperature = 60
switch (temperature)
{
case 0...49 where temperature % 2 == 0:
print("Cold and even")
case 50...79 where temperature % 2 == 0:
print("Warm and even")
case 80...110 where temperature % 2 == 0:
print("Hot and even")
default:
print("Temperature out of range or odd")
}
// Warm and even
let age = 20
switch age {
case 0...12 where age < 10:
print("어린이이고 나이가 10살 미만입니다.")
case 0...12 where age >= 10:
print("어린이이고 나이가 10살 이상입니다.")
case 13...19 where age % 2 == 0:
print("청소년이고 나이가 짝수입니다.")
case 13...19 where age % 2 != 0:
print("청소년이고 나이가 홀수입니다.")
case 20... where age % 2 == 0:
print("성인이고 나이가 짝수입니다.")
default:
print("성인이고 나이가 홀수입니다.")
}
// 성인이고 나이가 짝수입니다
fallthrough
var value = 4
switch (value)
{
case 4:
print("4")
fallthrough
case 3:
print("3")
fallthrough
case 2:
print("2")
fallthrough
default:
print("1")
}
// 4 3 2 1
함수
메서드
- 특정 클래스, 구조체, 열거형 내의 함수
- 함수를 클래스 내에 선언하면 메서드라 부름
func sayHello() -> Void { // 리턴값 없으면( -> Void) 지정하지 않아도 됨
print("Hello")
}
sayHello() // 함수 호출
- 매개변수를 받지 않으며 결과를 반환하지도 않고 오직 메시지만 출력
- 반환하지 않으면(Void) 반환값 타입(Void)과 -> 는 생략 가능
func messge(name: String, age: Int) -> String {
return("\(name) \(age)")
}
- 하나의 문자열과 하나의 정수를 매개변수로 받아서 문자열을 반환
Swift 함수 정의와 호출하기
func sayHello() { // 리턴값 없으면( -> Void) 지정하지 않아도 됨
print("Hello") // Hello
}
sayHello() // 함수 호출, Hello
print(type(of: sayHello())) // () -> ()
C언어에서 Swift 함수 변경
- C
int add(int x, int y) {
return(x+y)
}
add(10, 20);
- Swift
func add(x: Int, y: Int) -> Int {
return(x+y)
}
var z = add(x:10, y:20)
print(z) // 30
print(type(of:add)) // (Int, Int) -> Int
출처: iOS 프로그래밍 실무 강의 자료