iOS 프로그래밍 실무 2주차

2025. 3. 17. 22:05📱 모바일 프로그래밍/iOS 프로그래밍 실무

  • 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 프로그래밍 실무 강의 자료