[Swift] 문법 정리

승민·2025년 3월 17일

Swift

목록 보기
2/10
post-thumbnail

지금까지 학습한 내용을 다시 정리하는 시간이에요.
공부했던 내용을 더 빠르고 세부적으로 되짚어 볼게요.

CamelCase

CamelCase는 프로그래밍에서 변수, 함수, 클래스 등의 이름을 지을 때 사용되는 명명 규칙이에요.
기본적으로 단어단위로 구분하고 공백이나 밑줄(_), 하이픈(-) 없이 대문자로 구문하는 것이 특징이에요.

UpperCamelCase

  • UpperCamelCase는 아래 내용과 같이 첫 글자를 대문자로 시작해요.
var MyVariableName // UpperCamelCase
// 첫 글자를 포함한 각 단어가 대문자로 시작

lowerCamelCase

  • 반대로 lowerCamelCase는 첫 글자를 소문자로 시작해요. 단, 다음 단어는 그대로 대문자로 시작해요.
var myVariableName // lowerCamelCase
// 첫 글자를 제외한 각 단어가 대문자로 시작, 첫 글자는 소문자

변수와 상수

Swift는 데이터 값을 저장할 때 크게 두 가지의 방식을 사용해요. 선언 후 변경 가능한 값(var)과 불가능한 값(let)으로 나눠져요.

변수 var

  • 변수(variable)는 프로그램 동작 시에 메모리에 저장할 데이터가 실행 중 변할 수 있다는 것을 의미해요.
var myVar = 10
print(myVar)
myVar = 20 // 변경가능
print(myVar)

상수 let

  • 상수(constant)는 변수와 반대로 실행 중 변할 수 없다는 것을 의미해요.
let myVar = 10
print(myVar)
myVar = 20 // 에러 발생
print(myVar)

  • let의 내용을 사용하고 싶은 경우 다음과 같이 복사해서 사용할 수 있어요.
let myVar = 10
print(myVar)
let myVar2 = myVar + 10 // 값 복사해서 사용 가능
print(myVar2)

타입 추론

  • 위 예제에서 봤듯이 Swift에서 따로 자료형을 지정해 주지 않으면 컴파일러가 타입 추론(type inference)을 통해 자동으로 클래스를 지정 해줘요.

데이터 타입

Swift에서 사용가능한 자료형은 다음과 같이 있어요.

  • Bool, Character, Int, Float, Double, String, Void

Bool

  • true 또는 false의 값을 저장해요.
  • 타입 추론에 의해 초기값을 true 또는 false로 지정하면 자동적으로 Bool 형으로 지정해요.
var valueOfBool = true
print(type(of:valueOfBool))

Character

  • 문자, 숫자, 문장 부호, 심볼 등의 유니코드(Unicode) 문자 하나를 저장해요.
  • Character 형으로 지정하고 싶은 경우 따로 명시를 해줘야 해요.
var valueOfCharacter : Character = "a"
print(type(of:valueOfCharacter))
// 미지정 시
var valueOfCharacter2 = "a"
print(type(of:valueOfCharacter2))

Int

  • 정수 값을 저장해요.
  • 저장 방식에 따라 양수, 0, 음수를 포함하거나 0과 양수만 포함하는 방식으로 저장할 수 있어요.
  • 자료형 크기에 따라 저장할 수 있는 값의 크기가 달라져요.
var signedInt8: Int8 = -128
var maxSignedInt8: Int8 = 127
print("Int8: \(signedInt8) to \(maxSignedInt8)")

var signedInt16: Int16 = -32768
var maxSignedInt16: Int16 = 32767
print("Int16: \(signedInt16) to \(maxSignedInt16)")

var signedInt32: Int32 = -2147483648
var maxSignedInt32: Int32 = 2147483647
print("Int32: \(signedInt32) to \(maxSignedInt32)")

var signedInt64: Int64 = -9223372036854775808
var maxSignedInt64: Int64 = 9223372036854775807
print("UInt64: \(signedInt64) to \(maxSignedInt64)")

var uInt8: UInt8 = 0
var maxUInt8: UInt8 = 255
print("UInt8: \(uInt8) to \(maxUInt8)")

var uInt16: UInt16 = 0
var maxUInt16: UInt16 = 65535
print("UInt16: \(uInt16) to \(maxUInt16)")

var uInt32: UInt32 = 0
var maxUInt32: UInt32 = 4294967295
print("UInt32: \(uInt32) to \(maxUInt32)")

var uInt64: UInt64 = 0
var maxUInt64: UInt64 = 18446744073709551615
print("UInt64: \(uInt64) to \(maxUInt64)")

Flaot, Double

  • 소수점이 있는 숫자를 저장해요.
  • 32비트로 저장하는 Float과 64비트로 저장하는 Double이 있어요.
  • 형지정을 하지 않은 데이터는 기본값으로 Double이 지정돼요.
var value = 10.5
print(type(of:value))

var valueOfFloat : Float = 12.5
print(type(of:valueOfFloat))

String

  • 문자열을 저장하는 역할이에요.
  • String 타입의 경우 저장, 검색, 비교, 연결, 수정 등의 기능을 수행할 수 있어요.

    관련 문서 : Swift - String

var value = "gsmin"
print(type(of:value))

var value2 = "Hello"
print("\(value2) \(value)")

튜플

  • 튜플은 여러 개의 값을 하나로 묶어놓는 방법이에요.
  • 하나의 튜플로 묶인 각 요소는 모두 타입이 달라도 돼요.
  • 인덱스를 통해 값을 호출할 수 있으며, 시작 인덱스는 0이에요.
let valueOfTuple = (25, 3.16, "Hello")
print(valueOfTuple.2)
print(type(of:valueOfTuple.2))
print(type(of:valueOfTuple))

옵셔널

  • 옵셔널은 오류 발생 가능성이 있는 데이터를 옵셔널 타입으로 감싸서 반환하는 것을 의미해요.
  • 값의 부재나 숫자형 자료형에 문자를 넣거나, init되지 않은 값을 호출하려고 할 때 활용할 수 있어요.
  • 옵셔널에 해당하는 경우 반환값은 nil이에요.

언래핑 방법

  • 옵셔널 타입으로 감싸진 데이터는 언래핑을 통해서 데이터에 접근해야 해요.
  • 이러한 언래핑 방법은 다음과 같이 존재해요.

강제 언래핑

  • 강제 안래핑(forced unwarpping)은 값의 유무를 따지지 않고 언래핑하는 방법이에요.
  • 오류가 발생하는 값에 강제 언래핑을 하게 되면 프로그램이 바로 종료돼요.
var x : Int?
x = 10
var x1 : Int?
if x != nil {
  print(x!)
} else {
  print("nil")
}
if x1 != nil {
  print(x1!)
} else {
  print("nil")
}

옵셔널 바인딩

  • 강제 언래핑을 하는 다른 방법이에요.
  • 옵셔널 바인딩(Optional binding)을 통해서 값을 할당하는 방식이에요.
var x : Int?
x = 10
var x1 : Int?
if let x = x {
  print(x)
} else {
  print("nil")
}
if let xx = x1 {
  print(xx)
} else {
  print("nil")
}

여러 옵셔널 언래핑

  • 하나의 구문 안에서 여러 옵셔널을 언래핑하고 싶은 경우 콤마를 통해서 여러값을 한번에 언래핑할 수 있어요.
var pet1: String?
var pet2: String?
pet1 = "cat"
pet2 = "dog"
if let pet1, let pet2 {
  print(pet1, pet2)
} else {
  print("nil")
}

nil 병합 연산자

  • nil 병합 연산자(nil-Coalescing Operator)는 명시적으로 언래핑 실패 시 할당할 값을 지정해줘요.
  • 실패 시 값을 명시적으로 전달하기 때문에 조금 더 안전한 언래핑 방법이에요.
let defaultValue = "fish"
var userDefinedValue : String?

var selctValule = userDefinedValue ?? defaultValue
print(selctValule)

userDefinedValue = "chips"
selctValule = userDefinedValue ?? defaultValue
print(selctValule)

언래핑 여러 방법

  • guard-let을 제외한 여러 언래핑 방법을 한번에 확인해볼게요.
var value : String? = "Hello"
print(value, value!)
if let value {
  print(value)
}
let value2 = value ?? ""
print(value2)
let value3 = value!.count
print(type(of:value3), value3)
let value4 = value?.count
print(type(of:value4), value4, value4!)

암묵적 언래핑

  • 옵셔널이 항상 유효한 값을 가지는 경우에 암묵적 언래핑(implicitly unwrapped)이 되도록 할 수 있어요.
  • 클래스의 아웃렛(IBOutlet) 변수 초기화에서 많이 사용해요.
  • 암묵적 언래핑으로 생성된 경우 강제 언래핑이나 옵셔널 바인딩을 하지 않아도 값에 접근할 수 있어요.
  • 암묵적 언래핑으로 선언할 경우에 물음표(?) 대신 느낌표(!)를 사용해요.
let value1 : Int! = 1
let value2 : Int = value1
let value3 : Int = value1!
let value4 = value1
let value5 = value1 + 1
print(value1, value2, value3, value4, value5)
print(type(of:value1), type(of:value2), type(of:value3), type(of:value4), type(of:value5))

nil

  • 위에서 설명한 옵셔널이 오류 발생 가능성 있는 데이터를 명시하는 값이에요.
  • 옵셔널 변수에 nil을 할당하면 값이 없는 상태(valueless state)에요.
  • 옵셔널이 아닌 타입에는 nil을 할당할 수 없어요.
let value1 : Int? = nil
var value2 : Int?
value2 = nil
// 에러 없이 정상 종료

옵셔널은 연관 값을 갖는 enum

  • 옵셔널은 열거형으로 nonesome(<generic>)으로 존재해요.
  • 여기서 generic은 특정 타입에 의존하지 않는다는 뜻이에요.
  • 이 같은 특징으로 옵셔널은 다음과 같이 구문을 실행할 수도 있어요.
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)

아래는 요청하신 형식에 따라 Swift에서 사용하는 연산자의 종류별로 설명과 간단한 실습 예제 코드를 포함한 내용입니다.


연산자

Swift에서 사용하는 연산자의 종류에 대해 알아볼게요.

대입 연산자

  • 대입 연산자(=)는 오른쪽 값을 왼쪽 변수나 상수에 할당하는 데 사용해요.
  • Swift에서는 단일 대입 연산자만 제공되며, 다중 대입은 지원하지 않아요.
var number = 10
print(number)
number = 20
print(number)

산술 연산자

  • 산술 연산자(+, -, *, /, % 등)는 숫자에 대한 기본적인 연산을 수행해요.
  • 보통 두 개의 피연산자를 받는 이항(binary) 연산자에요.
let a = 10
let b = 3

print(a + b)
print(a - b)
print(a * b)
print(a / b)
print(a % b) // a를 b로 나눈 나머지

복합 대입 연산자

  • 복합 대입 연산자(+=, -=, *=, /=, %= 등)는 연산과 대입을 한 번에 수행해요.
  • 변수의 기존 값을 연산한 뒤 결과를 다시 변수에 저장하는 방식이에요
var score = 5
score += 3 // score = score + 3
print(score)

score *= 2 // score = score * 2
print(score)

증감 연산자

  • 다른 언어에서 흔히 볼 수 있는 ++, -- 연산자는 Swift에서 지원하지 않아요.
  • 사용하고 싶은 경우는 명시적으로 x = x + 1 또는 x += 1의 방식으로 작성해야 해요.

비교 연산자

  • 비교 연산자(==, !=, <, >, <=, >=)는 두 값을 비교하여 불리언 값(true 또는 false)을 반환해요.
let x = 5
let y = 8

print(x == y)
print(x != y)
print(x < y)
print(x >= y)

논리 연산자

  • 논리 연산자(&&, ||, !)는 불리언 값에 대한 논리 연산을 수행해요.
  • &&는 AND, ||는 OR, !는 NOT을 의미해요.
let isSunny = true
let isWarm = false

print(isSunny && isWarm)
print(isSunny || isWarm)
print(!isSunny)

범위 연산자

  • 범위 연산자(..., ..<)는 연속된 값의 범위를 나타내요.
  • ...는 닫힌 범위(끝 포함), ..<는 반열린 범위(끝 제외)를 의미해요.
for i in 1...3 {
    print(i) // 출력: 1, 2, 3
}

for j in 1..<3 {
    print(j) // 출력: 1, 2
}

let names = ["A","B","C","D"]
for name in names[2...] {
  print(name)
}

삼항 연산자

  • 삼항 연산자(?:)는 조건에 따라 두 값 중 하나를 선택하는 것을 의미해요.
  • 조건 ? 참일때값 : 거짓일때값 형식으로 사용돼요.
let age = 20
let message = age >= 18 ? "성인" : "미성년자"
print(message) // 출력: 성인

병합 연산자

  • 병합 연산자는 위에서 설명한 nil 병합 연산자와 같은 것을 의미해요.(nil-Coalescing Operator)
  • 중복되는 내용이여서 따로 작성하진 않았어요.

반복문

Swift의 반복문에 대해서 알아볼게요.
for문, while문 등이 해당해요.

for-in 반복문

  • for-in 반복문은 컬렉션 또는 숫자 범위 내에 있는 목록을 반복해요.
  • for문 다음에 중괄호({})는 필수적으로 사용해야 해요.
  • 참조체를 생략하고 싶은 경우 _로 생략할 수 있어요.
for i in 1...5 {
  print("\(i)번째 내용")
}
for _ in 1...5 {
  print("안녕")
}

  • 배열의 항목을 반복문을 통해 접근하고 싶은 경우 다음과 같이 할 수 있어요.
let animals = ["cat", "dog", "Eagle", "Tiger", "Whale"]
for animal in animals {
    print(animal)
}

  • 딕셔너리의 keyvalue를 가져오고 싶은 경우에는 다음과 같이 할 수 있어요.
let numberOfLegs = ["Spider": 8, "Ant": 6, "Dog": 4]
for (animalName, legCount) in numberOfLegs {
  print("\(animalName)s have \(legCount) legs")
}

while 반복문

  • while 반복문은 특정 조건을 만족할 때까지 반복하고 싶은 경우 사용하기 좋아요.
var cnt = 0
while cnt < 100 {
    cnt+=1 // cnt++ 불가
}
print(cnt)

repeat while 반목문

  • 스위프트의 이전 반목문인 do while문을 대신하는 반복문이에요.
  • while문과 달리 최초 1회 실행하는 특징을 가져요.
var cnt = 10
repeat {
    cnt -= 1 // i-- 불가
    print(cnt)
} while(cnt > 0)

break

  • 반복문에서 반복 중 특정 조건에서 빠져나오고 싶으면 다음과 같이 할 수 있어요.
for i in 1..<10 {
    if i > 5 {
        break
    }
    print(i)
}

continue

  • 반복문에서 반복 중 특정 조건을 만나면 다음 반복으로 건너뛰게 하고 싶은 경우 다음과 같이 할 수 있어요.
for i in 1...10 {
  if i % 2 == 0 {
    continue
  }
  print(i)
}

조건문

Swift의 조건문에 대해서 알아볼게요.
if문, guard문, switch-case문 등이 해당해요.

if 문

  • if 조건 결과가 불리언(ture 또는 false) 중 true인 경우 중괄호 내용을 실행하는 기능을 수행해요.
var num = 10
if num > 5 {
    print("5보다 커요")
}

  • if let 으로 여러 값을 옵셔널 바인딩 할 때는 조건나열(condition-list)로 해결할 수 있어요.
  • 불리언 조건을 맞추기 위해 && 연산자를 사용할 경우 에러가 나요.
var num1 : Int? = 10
var num2 : Int? = 20
print(num1, num2)
if let num1, let num2 { // 콤마 대신 && 사용시 에러 발생
    print(num1, num2)
}

다중 if else 문

  • 여러 조건을 처리해야 하는 경우 다중 if else문을 통해서 처리할 수 있어요.
  • 위에서부터 순서대로 조건이 맞는지 판단해요.
let planet = "화성"
let oxygen = 5

if planet == "지구" {
    print("지구에 왔어요, 숨 쉬기 좋아요!")
} else if planet == "화성" && oxygen < 20 {
    print("화성 도착! 산소 \(oxygen)%라 우주복 필수!")
} else if planet == "금성" {
    print("금성이에요, 위험하니 떠나세요!")
} else {
    print("미지의 행성 \(planet)이네요, 탐험 시작!")
}

guard 문

  • guard문은 조건문이 거짓(false)일 때 else 다음 구문을 실행하는 구문이에요.
  • else 문을 반드시 포함해야 해요.
func checkGameAccess(age: Int, playTime: Int) {
    guard age >= 19 else {
        print("19세 미만은 접속 할 수 없어요.")
        return
    }
    guard playTime < 5 else {
        print("5시간 이상 플레이했어요. 휴식하세요!")
        return
    }
    print("즐겁게 플레이하세요!")
}

checkGameAccess(age: 15, playTime: 2)
checkGameAccess(age: 20, playTime: 3)
checkGameAccess(age: 21, playTime: 6)
checkGameAccess(age: 25, playTime: 1)

guard let~else 옵셔널 바인딩

  • guard let 문을 통해서 옵셔널 바인딩을 할 수 있어요.
  • guard문에서 언래핑되면 구문 다음에도 해당 내용을 사용할 수 있는 특징이 있어요.
  • if문은 해당 구문 내에서만 동작하지만 guard문은 조건문 아래에서 계속 사용할 수 있기 때문에 코드 가동성이 더욱 좋아져요.
func checkLibrary(bookTitle: String?, stock: Int) {
    guard let title = bookTitle else {
        print("책 제목을 입력하세요!")
        return
    }
    guard stock > 0 else {
        print("재고가 없습니다.")
        return
    }
    print("'\(title)' 대출 가능합니다!")
}
checkLibrary(bookTitle: nil, stock: 3)
checkLibrary(bookTitle: "iOS", stock: 0)
checkLibrary(bookTitle: "Swift", stock: 2)

switch case 문

  • swich case문은 해당 조건이 만족될 때, 해당 case 구문을 실행시켜요.
  • case문은 break가 자동으로 들어 있어요.
func checkWeather(_ condition: String) {
    switch condition {
    case "sunny":
        print("날씨 맑음! 선글라스를 챙겨요.")
    case "rainy":
        print("비 와요. 우산 필요!")
    case "windy":
        print("바람이 강해요! 모자 조심!")
    default:
        print("알 수 없어요..")
    }
}

checkWeather("sunny")
checkWeather("rainy")
checkWeather("storm")

  • 조건을 여러개 하고 싶은 경우 콤마를 통해서 결합할 수 있어요.
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("월을 잘못 입력하셨습니다")
}

  • case에 대해서 추가적인 조건도 설정할 수 있어요.
  • case의 조건을 우선적으로 검사하고, 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")
}

  • 다른 언어에서 switch 문의 break를 쓰지 않으면 다음 case 내용도 출력돼요.
    -swift에서는 해당 기능을 fallthrough를 통해 구현할 수 있어요.
var value = 4
switch (value) {
case 4:
  print("4")
  fallthrough
case 3:
  print("3")
  fallthrough
case 2:
  print("2")
  fallthrough
default:
  print("1")
}

함수

  • 함수는 특정 작업 체계가 반복적으로 사용될 때, 반복되는 요소를 줄이기 위한 방법이에요.
  • 입력과 처리, 출력으로 구분이 돼요.
    • 입력 또는 출력 중 하나는 생략될 수 있어요.

parameter, argument

  • 입력값은 바라보는 관점에 따라 다르게 불러요.
    • 정의 시 받는 입력값은 parameter(매개변수), 호출 시 보내주는 입력값은 argument(전달인자)라고 불러요.

method

  • method는 클래스, 구조체, 열거형 내의 함수를 의미해요.
  • 함수를 클래스 내에 선언하면 메서드라고 불러요.

함수 선언 형식

  • swift에서 함수를 선언하는 형식은 다음과 같아요.
  • 반환값 타입이 Void인 경우 따로 명시하지 않아도 돼요.
func <함수명> (<매개변수 이름>:<매개변수 타입>, ...)
	-> <반환값 타입> {
  // 처리 과정을 위한 코드
}
func sayHello() {
    print("Hello")
}
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)
}
add(x:10, y:20)
  • 위 예제를 보면 알 수 있듯이 선언 방식도 다르지만, 호출 방식도 달라요.
  • C언어에서는 매개변수의 이름을 따로 적어주지 않지만, Swfit에서는 매개변수의 이름을 명시하고 있어요.
  • 가장 많이 헷갈릴 수 있는 부분이기에 조심해야 해요.

함수의 자료형

  • Swift에서는 함수의 입력 타입과 출력 타입을 확인할 수 있어요.
func add(x: Int, y: Int) -> Int {
  return (x+y)
}
print(type(of:add))

  • (Int, Int) -> Int
    • 두 입력값의 자료형이 Int이고, 출력값의 자료형이 Int라는 뜻이에요.

정리

  • Swift의 문법들을 빠르게 훑어봤어요.
  • 간단한 예제를 통한 동작 방식을 이해할 수 있었어요.

출처 : Smile Han - iOS 프로그래밍 기초

0개의 댓글