▶ 클래스 메서드
클래스 자체에 속한 함수이다. 이 메서드들은 클래스의 인스턴스가 아니라 클래스 자체에 호출되며, 클래스의 모든 인스턴스에서 공유된다. 클래스 메서드를 정의할 때는 class 키워드를 사용하거나, 상속된 메서드를 재정의하지 않을 경우 static 키워드를 사용할 수 있다.
class MyClass {
class func myClassMethod() {
// 클래스 메서드 구현
}
}
static 키워드를 사용한 예시는 다음과 같다
class MyClass {
static func myStaticClassMethod() {
// static 클래스 메서드 구현
}
}
-스태틱 키워드를 사용하는 이유
Swift를 비롯한 많은 프로그래밍 언어에서 변수나 메서드가 타입 자체에 속함을 나타내기 위해 사용된다. static으로 선언된 프로퍼티나 메서드는 해당 타입의 인스턴스가 아니라 타입 자체에 속하며, 따라서 인스턴스를 생성하지 않고도 접근할 수 있다.
> 데이터 공유: static 변수는 모든 인스턴스에 걸쳐 공유되는 데이터를 저장하는 데 사용된다. 이는 모든 인스턴스가 같은 정보를 보거나 수정할 필요가 있을 때 유용하다. 예를 들어, 어플리케이션의 설정 정보나 상태를 관리하는 데 static 변수가 자주 사용된다.
> 유틸리티 함수: static 메서드는 인스턴스 없이 호출할 수 있는 유틸리티 함수를 정의하는 데 사용된다. 이러한 메서드는 특정 인스턴스에 종속되지 않는 일반적인 작업을 수행하며, 전역 함수와 유사하게 사용될 수 있다. 예를 들어, 수학 계산이나 문자열 처리와 같은 기능을 제공하는 데 static 메서드가 활용된다.
> 싱글턴 패턴 구현: static 변수는 싱글턴 패턴을 구현하는 데 필수적이다. 싱글턴 패턴에서는 클래스의 단일 인스턴스만 생성되어야 하며, 이 인스턴스에 대한 전역 접근 지점이 필요하다. static으로 선언된 프로퍼티를 통해 이러한 전역 인스턴스를 저장하고 관리할 수 있다.
> 메모리 효율성: static 프로퍼티와 메서드는 타입 자체에 속하기 때문에, 해당 타입의 각 인스턴스마다 별도로 메모리를 할당하지 않는다. 이는 특히 데이터를 많이 사용하거나 반복적으로 사용되는 프로퍼티와 메서드에 있어 메모리 사용량을 줄이는 데 도움이 된다.
> 이름 공간 관리: static을 사용하면 타입의 이름 공간 내에서 프로퍼티와 메서드를 정의할 수 있다. 이는 코드의 구조를 명확하게 하고, 관련 기능을 타입에 더 가깝게 묶어서 관리할 수 있게 한다.
클래스 메서드의 호출
MyClass.myClassMethod()
MyClass.myStaticClassMethod()
▶ 싱글턴(Singleton) 패턴
싱글턴 패턴은 클래스의 인스턴스가 단 하나만 생성되어야 할 때 사용하는 디자인 패턴이다. 이 패턴을 사용하면 전역적으로 접근 가능한 단일 인스턴스를 생성할 수 있으며, 이 인스턴스는 애플리케이션의 생명 주기 동안 유일하게 유지된다. 싱글턴 패턴은 설정, 네트워킹 작업, 데이터베이스 관리 등 애플리케이션 전반에 걸쳐 공유 리소스에 접근해야 하는 경우에 유용하게 사용된다. 다음은 싱글턴 패턴을 구현하는 기본적인 방법이다.
- 생성자를 private으로 선언하여 외부에서 인스턴스를 생성하는 것을 방지한다.
- 클래스 내부에 정적(static) 변수로 유일한 인스턴스를 저장한다.
- 공개적으로 접근 가능한 정적 메서드를 제공하여, 이 메서드를 통해 유일한 인스턴스에 접근할 수 있도록 한다.
class MySingleton {
static let shared = MySingleton()
private init() {
// 초기화 코드
}
func doSomething() {
// 싱글턴 인스턴스의 기능
}
}
// 싱글턴 인스턴스에 접근
MySingleton.shared.doSomething()
▶ 오버라이딩(Overriding)
서브클래스가 슈퍼클래스의 메서드, 프로퍼티, 또는 서브스크립트의 구현을 자신의 컨텍스트에 맞게 재정의할 수 있게 해주는 기능이다. 오버라이딩을 통해 상속받은 기능을 확장하거나 변경할 수 있으며, 다형성을 구현하는 데 중요한 역할을 한다.
class Animal {
func makeSound() {
print("Some generic sound")
}
}
class Dog: Animal {
override func makeSound() {
print("Woof")
}
}
let myDog = Dog()
myDog.makeSound() // 출력: "Woof"
여기서 Dog 클래스는 Animal 클래스로부터 makeSound 메서드를 상속받지만, override 키워드를 사용하여 이 메서드의 구현을 "Woof"라는 소리를 출력하도록 재정의한다.
▶ 오버로딩(Overloading)
같은 이름을 가진 함수나 메서드가 여러 개 있지만, 매개변수의 타입이나 개수가 다른 경우를 말한다. 이를 통해 같은 기능을 수행하지만, 다른 타입이나 매개변수를 가진 입력에 대응할 수 있게 된다. 오버로딩은 프로그래밍 언어에서 다형성(polymorphism)의 한 형태를 제공한다. 오버로딩의 특징은 다음과 같다.
- 이름의 재사용: 같은 이름의 함수나 메서드를 여러 가지 매개변수로 사용할 수 있어, 프로그래머가 함수 이름을 기억하기 쉽게 한다.
- 작업의 일관성: 비슷한 종류의 작업을 수행하는 여러 함수나 메서드가 하나의 이름으로 그룹화되어, 코드의 가독성이 향상된다.
- 유연성: 다양한 타입의 입력을 처리할 수 있어, 함수나 메서드의 사용이 유연해진다.
import Foundation
class MathOperations {
// 정수 더하기 메서드
func add(_ a: Int, _ b: Int) -> Int {
return a + b
}
// 실수 더하기 메서드
func add(_ a: Double, _ b: Double) -> Double {
return a + b
}
// 세 개의 정수 더하기 메서드
func add(_ a: Int, _ b: Int, _ c: Int) -> Int {
return a + b + c
}
// 문자열로 된 숫자 더하기 메서드
func add(_ a: String, _ b: String) -> Int? {
guard let numA = Int(a), let numB = Int(b) else {
return nil
}
return numA + numB
}
}
let operations = MathOperations()
// 정수 더하기
print(operations.add(2, 3)) // 출력: 5
// 실수 더하기
print(operations.add(2.5, 3.5)) // 출력: 6.0
// 세 개의 정수 더하기
print(operations.add(1, 2, 3)) // 출력: 6
// 문자열로 된 숫자 더하기
if let result = operations.add("10", "20") {
print(result) // 출력: 30
} else {
print("숫자 변환에 실패했습니다.")
}
위 예시에서 MathOperations 클래스는 add라는 이름을 가진 네 가지 메서드를 오버로딩하여 제공한다. 각 메서드는 매개변수의 타입이나 개수가 다르기 때문에, Swift 컴파일러는 메서드를 호출할 때 제공된 인자의 타입과 개수를 기반으로 적절한 메서드를 선택하여 실행한다.
▶ self
현재 인스턴스를 가리키는 데 사용된다. 다시 말해, self는 클래스 혹은 구조체 내부에서 해당 인스턴스 자신을 참조할 때 사용되는 변수이다. 이 키워드는 주로 인스턴스의 프로퍼티나 메서드에 접근하거나, 현재 인스턴스를 명시적으로 가리키고자 할 때 사용된다.
- 프로퍼티와 메서드 이름 구분: 클래스나 구조체 내부에서 매개변수나 로컬 변수의 이름이 인스턴스의 프로퍼티 이름과 같을 때, 이들을 구별하기 위해 self를 사용할 수 있습니다.
class Person {
var name: String
init(name: String) {
self.name = name // 여기서 self.name은 인스턴스 프로퍼티를, name은 생성자의 매개변수를 가리킨다.
}
}
- 메서드에서 현재 인스턴스 반환: 어떤 메서드가 현재 인스턴스를 반환해야 할 때, self를 사용하여 현재 인스턴스를 명시적으로 반환할 수 있다.
class Calculator {
var value: Int = 0
func add(_ number: Int) -> Calculator {
self.value += number
return self // 현재 인스턴스 반환
}
}
-클로저 내에서 인스턴스 멤버에 접근: 클로저 내부에서 인스턴스의 프로퍼티나 메서드에 접근할 때 self를 사용하여 해당 인스턴스 멤버임을 명시해야 한다. 이는 클로저가 캡처리스트에서 self를 캡처할 수 있게 하여, 메모리 관리와 관련된 문제를 명확히 할 수 있도록 한다.
class Task {
var description: String
init(description: String) {
self.description = description
}
func update(description: String) {
DispatchQueue.main.async { [weak self] in
self?.description = description
}
}
}
▶ init
클래스, 구조체(struct), 혹은 열거형(enum)의 인스턴스가 생성될 때 초기화를 위해 호출되는 특별한 메서드이다. 이 함수는 해당 타입의 새 인스턴스가 메모리에 할당된 직후, 그 인스턴스의 프로퍼티가 올바른 초기 값으로 설정되도록 보장하는 역할을 한다. 프로그래밍 언어에 따라 생성자(constructor)라고도 불리며, 인스턴스가 사용될 준비가 되도록 초기화 과정을 담당한다.
class Person {
var name: String
var age: Int
// init 함수 정의
init(name: String, age: Int) {
self.name = name // self 키워드를 사용하여 인스턴스 프로퍼티와 init 함수의 매개변수를 구분
self.age = age
}
// 기능 수행 메서드
func introduce() {
print("Hello, my name is \(name) and I am \(age) years old.")
}
}
// Person 클래스의 인스턴스 생성
let person = Person(name: "John", age: 30)
// 메서드 호출
person.introduce() // 출력: "Hello, my name is John and I am 30 years old."
Person 클래스는 name과 age 두 개의 프로퍼티를 가지며, init(name:age:) 함수를 통해 인스턴스가 생성될 때 이 두 프로퍼티에 초기값을 할당한다. 이처럼 init 함수는 인스턴스의 초기 상태를 설정하는 데 필수적인 역할을 한다.
▶ 슈퍼 클래스 vs 서브 클래스
- 슈퍼 클래스: 슈퍼 클래스, 또는 부모 클래스(parent class)는 다른 클래스에 기능이나 특성을 상속해주는 클래스이다. 슈퍼 클래스는 보다 일반적이고 기본적인 속성과 행동을 정의한다. 다른 클래스(서브 클래스)는 이 슈퍼 클래스로부터 상속을 받아, 기본적인 속성과 행동을 가지면서 추가적인 특성 또는 수정된 행동을 구현할 수 있다.
- 서브 클래스: 서브 클래스, 또는 자식 클래스(child class)는 슈퍼 클래스로부터 상속받아 생성되는 클래스이다. 서브 클래스는 슈퍼 클래스의 모든 특성(프로퍼티)과 행동(메소드)을 물려받으며, 필요에 따라 추가적인 특성이나 행동을 정의하거나 기존의 행동을 수정(오버라이딩)할 수 있다.
// 슈퍼 클래스 정의
class Vehicle {
var currentSpeed = 0.0
var description: String {
return "traveling at \(currentSpeed) miles per hour"
}
func makeNoise() {
// 기본적으로 차량은 소음을 내지 않음
}
}
// 서브 클래스 정의
class Bicycle: Vehicle {
var hasBasket = false
}
// 서브 클래스에서 슈퍼 클래스의 메소드 오버라이딩
class Car: Vehicle {
var gear = 1
override func makeNoise() {
print("Beep! Beep!")
}
}
위 예제에서 Vehicle 클래스는 슈퍼 클래스로, 여러 종류의 차량에 공통적인 특성과 행동을 정의한다. Bicycle과 Car 클래스는 Vehicle 클래스로부터 상속받은 서브 클래스들이며, 각각 자전거와 자동차의 특성을 추가로 정의한다. Car 클래스는 Vehicle의 makeNoise 메소드를 오버라이딩하여, 자동차에 특화된 소음을 낼 수 있도록 한다.
▶ 접근 제어자(Access Modifier)
클래스, 구조체, 열거형 등의 타입 뿐만 아니라 이들 타입의 프로퍼티, 메서드, 이니셜라이저 등의 멤버에 대한 접근 수준을 지정하는 데 사용된다. Swift의 접근 제어자는 코드의 일부를 다른 코드에서 사용할 수 있는 범위를 제한하여, 데이터 캡슐화, API 사용의 세부 사항 숨김, 그리고 모듈 간의 인터페이스를 관리할 수 있도록 도와준다. Swift에는 다음과 같은 접근 제어 수준이 있다.
- open과 public
> open: 가장 낮은 제한 수준으로, 다른 모듈에서도 상속하거나 오버라이딩할 수 있다. 주로 프레임워크의 공개 인터페이스에서 사용된다.
> public: open과 유사하지만, 다른 모듈에서는 상속하거나 오버라이딩할 수 없다. 모듈 외부에서 사용할 수 있지만, 해당 타입을 상속하거나 멤버를 오버라이딩하는 것은 제한된다.
- internal: 기본 접근 수준으로, 같은 모듈 내에서만 사용할 수 있습니다. 다른 모듈에서는 접근할 수 없다. 개발 중인 애플리케이션의 내부 구조를 설계할 때 주로 사용된다.
- fileprivate: 선언된 파일 내에서만 사용할 수 있는 접근 수준이다. 같은 파일 내의 다른 타입이나 함수에서는 접근할 수 있지만, 파일 외부에서는 접근할 수 없다.
- private: 가장 제한적인 접근 수준으로, 선언이 포함된 범위(예: 클래스, 구조체, 열거형, 확장) 내에서만 사용할 수 있다. 이 범위의 외부에서는 접근할 수 없다.
public class PublicClass {
fileprivate func fileprivateMethod() {}
private func privateMethod() {}
}
internal class InternalClass {} // internal은 기본 접근 수준이므로 생략 가능
fileprivate class FileprivateClass {}
private class PrivateClass {}
let publicInstance = PublicClass()
// publicInstance.fileprivateMethod() // 에러: 같은 파일 내에서만 접근 가능
// publicInstance.privateMethod() // 에러: 클래스 내부에서만 접근 가능
▶ Delegate나 DataSource를 사용하는 UI 컴포넌트
UI 컴포넌트 | Delegate 사용 여부 | Delegate 설명 | DataSource 사용 여부 | DataSource 설명 |
UITableView | O | 셀 선택, 편집, 고정 등 사용자 인터랙션과 테이블 뷰의 시각적인 변화를 관리 | O | 테이블에 표시될 데이터의 개수와 셀에 표시될 데이터를 제공 |
UICollectionView | O | 셀 선택, 편집, 레이아웃 변화 등 사용자 인터랙션과 컬렉션 뷰의 시각적인 변화를 관리 | O | 컬렉션에 표시될 데이터의 개수와 셀에 표시될 데이터를 제공 |
UIPickerView | O | 각 컴포넌트(열)의 선택된 항목을 관리 | O | 각 컴포넌트(열)의 행 개수와 각 행의 데이터를 제공 |
UIScrollView | O | 스크롤뷰의 스크롤 이벤트, 확대/축소 등의 사용자 인터랙션을 관리 | X | - |
UIPageViewController | O | 페이지 전환과 같은 사용자 인터랙션을 관리 | O | 표시할 페이지(뷰 컨트롤러)를 제공 |
UISearchBar | O | 검색 바의 텍스트 변경, 검색 버튼 클릭 등 사용자 인터랙션을 관리 | X | - |
UITextView | O | 텍스트 변경, 편집 시작/종료 등의 사용자 인터랙션을 관리 | X | - |
UITextField | O | 텍스트 필드의 텍스트 변경, 편집 시작/종료 등의 사용자 인터랙션을 관리 | X | - |
▶ 간단한 맛집 리스트 만들기
'프로그래밍 > iOS' 카테고리의 다른 글
[iOS] Swift 공부 - 18 (0) | 2024.04.18 |
---|---|
[iOS] Swift 공부 - 17 (0) | 2024.04.11 |
[iOS] Swift 공부 - 15 (0) | 2024.03.28 |
[iOS] Swift 공부 - 14 (0) | 2024.03.14 |
[iOS] Swift 공부 - 13 (0) | 2024.03.07 |