
출처 : smileHan - iOS 프로그래밍기초
앱의 진입점이며, 앱의 생명 주기를 관리하는 역할을 합니다.
import UIKit // UIKit 프레임워크를 가져와서 UI 관련 기능을 사용 가능하게 함
@main // 앱의 진입점임을 나타내는 애노테이션
class AppDelegate: UIResponder, UIApplicationDelegate { // UIApplicationDelegate 프로토콜을 구현하는 AppDelegate 클래스 정의
// 앱이 시작될 때 호출되는 메서드
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// 앱이 실행된 후 추가적인 설정을 할 수 있음
return true // 기본적으로 앱 실행을 정상적으로 완료했다고 반환
}
// MARK: UISceneSession Lifecycle
// 새로운 씬 세션이 생성될 때 호출되는 메서드
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// 새로운 씬을 설정하는 역할을 함
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role) // 기본 설정을 반환
}
// 사용자가 앱에서 씬을 제거했을 때 호출되는 메서드
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// 사용자가 실행 중이던 씬을 닫았을 때 해당 리소스를 정리할 수 있음
}
}
func application(
_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions
) -> UISceneConfiguration
//1. 메서드의 역할
//UIApplicationDelegate 프로토콜의 필수 메서드 중 하나입니다.
//새로운 씬(Scene)을 설정하기 위한 UISceneConfiguration 객체를 반환합니다.
//앱이 멀티 윈도우(멀티 씬)를 지원할 경우 각 씬에 맞는 설정을 적용하는 역할을 합니다.
//_는 왜 사용했을까?
//Swift에서 _는 파라미터 이름 생략을 의미합니다. 이 메서드에서 application 앞에 _가 //붙은 이유는 다음과 같습니다:
//2. 외부 파라미터 이름 생략
//Swift 함수는 기본적으로 파라미터에 외부 이름(external name)과 내부 이름(internal //name)을 가질 수 있습니다.
//외부 이름은 함수를 호출할 때 사용되고, 내부 이름은 함수 내부에서 사용됩니다.
//_를 사용하면 외부에서 이 파라미터 이름을 생략할 수 있습니다.
configurationForConnecting connectingSceneSession:
//여기서 configurationForConnecting connectingSceneSession: //UISceneSession은 하나의 파라미터를 정의하는 구문입니다. 이걸 분리해서 이해하면:
//configurationForConnecting: 외부 파라미터 이름 (External Parameter Name)
//connectingSceneSession: 내부 파라미터 이름 (Internal Parameter Name)
//: UISceneSession: 파라미터의 타입
씬(화면)의 상태를 관리하는 역할을 합니다.
import UIKit // UIKit 프레임워크를 가져와서 UI 관련 기능을 사용 가능하게 함
class SceneDelegate: UIResponder, UIWindowSceneDelegate { // UIWindowSceneDelegate 프로토콜을 구현하는 SceneDelegate 클래스 정의
var window: UIWindow? // 앱의 UI를 담당하는 UIWindow 인스턴스 선언
// 새로운 씬이 연결될 때 호출되는 메서드
func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
// 스토리보드를 사용하는 경우 자동으로 window가 설정됨
guard let _ = (scene as? UIWindowScene) else { return } // UIWindowScene이 존재하는지 확인 후 실행
}
// 씬이 해제될 때 호출되는 메서드
func sceneDidDisconnect(_ scene: UIScene) {
// 시스템이 씬을 정리할 때 호출됨 (백그라운드에서 제거될 때 등)
}
// 씬이 활성 상태(Active)로 전환될 때 호출되는 메서드
func sceneDidBecomeActive(_ scene: UIScene) {
// 일시 정지되었던 작업을 재개하거나 필요한 설정을 초기화할 때 사용됨
}
// 씬이 비활성화(Inactive) 상태로 전환될 때 호출되는 메서드
func sceneWillResignActive(_ scene: UIScene) {
// 전화 수신 등의 이유로 앱이 일시적으로 비활성화될 때 수행할 작업
}
// 씬이 포그라운드(화면)로 전환될 때 호출되는 메서드
func sceneWillEnterForeground(_ scene: UIScene) {
// 백그라운드에서 다시 앱으로 돌아왔을 때 수행할 작업
}
// 씬이 백그라운드로 전환될 때 호출되는 메서드
func sceneDidEnterBackground(_ scene: UIScene) {
// 데이터를 저장하고 리소스를 해제하는 등의 작업 수행
}
}
앱의 기본 화면을 담당하는 뷰 컨트롤러입니다.
import UIKit // UIKit 프레임워크를 가져와서 UI 관련 기능을 사용 가능하게 함
class ViewController: UIViewController { // UIViewController를 상속받는 ViewController 클래스 정의
override func viewDidLoad() { // 뷰가 메모리에 로드된 후 호출되는 메서드
super.viewDidLoad() // 부모 클래스의 viewDidLoad 메서드를 호출하여 기본 설정 유지
// 추가적인 초기 설정을 여기에 작성할 수 있음
}
}
#include <stdio.h>
void Fun( int param ) // parameter(매개변수, 인자), 형식 매개변수(formal parameter)
{
printf("%d",param);
}
int main()
{
Fun( 10 ); // 10은 argument(전달인자), 실 매개변수(actual parameter)
return 0;
}
정의: 함수 정의에서 사용하는 형식 매개변수(formal parameter)로, 함수가 받을 값을 나타내는 변수입니다.
정의: 함수 호출 시 실제로 전달되는 값으로, 실 매개변수(actual parameter)라고도 합니다.
func sayHello() -> Void {
print("Hello, World!")
}
sayHello()
//함수명 : sayHello()
//반환형 : Void (생략 가능)

func add(first x:Int, second y:Int) -> Int{
print(#function)
return x+y
}
print(add(first:110,second:201))
func add(x:Int, y:Int) -> Int{
print(#function)
return x+y
}
print(add(x:10,y:20))
func add(_ x:Int, _ y:Int) -> Int{
print(#function)
return x+y
}
print(add(120,230))
func add(_ x:Int, yy y:Int) -> Int{
print(#function)
return x+y
}
print(add(13,yy:24))
print(#function)을 사용하면 그 함수의 이름을 알 수 있습니다.
위에는 기능은 같지만 서로다른 이름을 가지고 있습니다.
func application(
_ application: UIApplication,
configurationForConnecting connectingSceneSession: UISceneSession,
options: UIScene.ConnectionOptions
) -> UISceneConfiguration
✅ 함수의 기본 이름(Base Name):
👉 application
✅ 전체 함수 시그니처(Full Name, 공식적으로는 "Function Name"):
👉 application(_:configurationForConnecting:options:)
즉, Swift에서 함수의 공식적인 이름은 기본 이름(Base Name) + 모든 매개변수 레이블을 포함한 형태입니다.
@MainActor
func tableView(
_ tableView: UITableView,
numberOfRowsInSection section: Int
) -> Int
📌 함수의 역할
class Man{
var age : Int = 0
}
swift에서는 클래스안의 변수를 프로퍼티라고 한다.
그리고 그 프로퍼티의 초깃값이 존재해야한다.
class Man{
var age : Int = 1 //직접 지정
var weight : Double = 3.5
}
class Man{
var age : Int? //옵셔널 변수는 nil로 자동 초기화
var weight : Double! //옵셔널 변수는 nil로 자동 초기화
}
class Man{
var age : Int
var weight : Double
init(){ //initializer로 초기화
age = 1
weight = 3.5
}
}
Designated initializer는 클래스에서 모든 저장 속성(stored properties)을 초기화하는 책임을 지는 주요 생성자입니다.// 클래스를 정의합니다. 'Man'이라는 이름의 클래스를 생성.
class Man {
// 'age'라는 정수형 저장 속성(property)을 선언하고 기본값 1로 초기화.
var age: Int = 1
// 'weight'라는 실수형(Double) 저장 속성을 선언하고 기본값 3.5로 초기화.
var weight: Double = 3.5
// 'display'라는 메서드를 정의. 객체의 나이와 몸무게를 출력하는 기능.
func display() {
// 문자열 보간법을 사용해 'age'와 'weight'를 출력.
print("나이=\(age), 몸무게=\(weight)")
}
// Designated Initializer(지정 생성자)를 정의.
// 이 생성자는 'age'와 'weight'를 파라미터로 받아 객체를 초기화.
init(age: Int, weight: Double) {
// 'self.age'는 클래스의 속성 'age'를 의미하며, 파라미터 'age' 값을 할당.
self.age = age
// 'self.weight'는 클래스의 속성 'weight'를 의미하며, 파라미터 'weight' 값을 할당.
self.weight = weight
} // 이 생성자는 모든 저장 속성을 초기화하므로 designated initializer임.
}
// 'kim'이라는 변수에 'Man' 클래스의 인스턴스를 생성하고 할당.
// 생성자에 'age: 25', 'weight: 60000'을 전달해 초기화.
var kim: Man = Man(age: 25, weight: 60000)
// 'kim' 객체의 'age' 속성을 출력. 결과는 25가 나옴.
print(kim.age)
자식클래스에서 부모클래스의 메서드를 재정의 하고싶다면 오버라이드를 사용합니다.
// 'Man'이라는 부모 클래스를 정의합니다.
class Man {
// 'age'라는 정수형 저장 속성(property)을 선언. 초기값 없음.
var age: Int
// 'weight'라는 실수형(Double) 저장 속성을 선언. 초기값 없음.
var weight: Double
// 'display' 메서드를 정의. 객체의 나이와 몸무게를 출력하는 기능.
func display() {
// 문자열 보간법을 사용해 'age'와 'weight'를 출력.
print("나이=\(age), 몸무게=\(weight)")
}
// Designated Initializer(지정 생성자)를 정의.
// 'age'와 'weight'를 파라미터로 받아 객체의 속성을 초기화.
init(age: Int, weight: Double) {
// 'self.age'는 클래스의 속성 'age'를 의미하며, 파라미터 'age' 값을 할당.
self.age = age
// 'self.weight'는 클래스의 속성 'weight'를 의미하며, 파라미터 'weight' 값을 할당.
self.weight = weight
}
}
// 'Student'라는 자식 클래스를 정의. 'Man' 클래스를 상속받음.
class Student: Man {
// 'name'이라는 문자열형 저장 속성을 선언. 초기값 없음.
var name: String
// 부모 클래스 'Man'의 'display' 메서드를 오버라이드(재정의).
override func display() {
// 'name', 'age', 'weight'를 출력. 'age'와 'weight'는 부모 클래스에서 상속됨.
print("이름=\(name), 나이=\(age), 몸무게=\(weight)")
}
// 'Student' 클래스의 Designated Initializer를 정의.
// 'age', 'weight', 'name'을 파라미터로 받아 초기화.
init(age: Int, weight: Double, name: String) {
// 'self.name'은 'Student' 클래스의 속성 'name'을 의미하며, 파라미터 'name' 값을 할당.
self.name = name
// 부모 클래스 'Man'의 Designated Initializer를 호출해 'age'와 'weight'를 초기화.
super.init(age: age, weight: weight) // 이 줄이 없으면 에러 발생.
} // 주석: 이 줄이 없으면 "super.init이 호출되지 않았다"는 에러 발생.
// 이유: 자식 클래스는 부모의 초기화를 반드시 호출해야 모든 속성이 초기화됨.
}
// 'Student' 클래스의 인스턴스를 생성하고 'lee' 변수에 할당.
// 'age: 20', 'weight: 65.2', 'name: "홍길동"'을 전달해 초기화.
var lee: Student = Student(age: 20, weight: 65.2, name: "홍길동")
// 'lee' 객체의 'display' 메서드를 호출.
// 'Student'에서 오버라이드된 메서드가 실행됨. 출력: "이름=홍길동, 나이=20, 몸무게=65.2"
lee.display()
// 'lee' 객체의 'display' 메서드를 다시 호출.
// 동일하게 "이름=홍길동, 나이=20, 몸무게=65.2" 출력.
lee.display()
한 객체가 특정 작업이나 이벤트를 처리할 때, 그 작업을 직접 수행하지 않고 다른 객체(델리게이트)에게 "위임"하는 패턴
핵심 : 객체 A가 어떤 일을 해야 할 때, 그 일을 객체 B에게 맡기고, 객체 B가 대신 처리한 뒤 필요하면 결과를 객체 A에게 돌려줍니다.


protocol Runnable { //대리하고 싶은 함수 목록 작성
var x : Int {get set} //읽기와 쓰기 가능 프로퍼티,{get}은 읽기 전용
//property in protocol must have explicit { get } or { get set } specifier
func run() //메서드는 선언만 있음
}
class Man : Runnable { //채택, adopt
var x : Int = 1 //준수, conform
func run(){print("달린다~")} //준수, conform
}
let han = Man()
GPT : Swift에서 상속(Inheritance)과 프로토콜(Protocol)을 동시에 사용하는 쉬운 예제를 만들어 설명해드릴게요. 초보자도 이해하기 쉽게 간단한 상황을 설정하고, 코드와 함께 각 부분을 자세히 풀어볼게요.
// 프로토콜 정의: 전시 가능한 동물이 따라야 할 규칙
protocol Exhibitable {
func showOff() // 전시 동작
}
// 부모 클래스: 동물
class Animal {
var name: String
init(name: String) {
self.name = name
}
func makeSound() {
print("동물이 소리를 냅니다.")
}
}
// 자식 클래스: 강아지 (상속 + 프로토콜 준수)
class Dog: Animal, Exhibitable {
// 부모로부터 name 속성과 makeSound() 메서드를 상속받음
// 부모의 메서드를 오버라이드
override func makeSound() {
print("\(name)가 짖습니다: 멍멍!")
}
// 프로토콜 요구사항 구현
func showOff() {
print("\(name)가 꼬리를 흔들며 전시됩니다!")
}
}
// 사용
let myDog = Dog(name: "바둑이")
myDog.makeSound() // "바둑이가 짖습니다: 멍멍!" (상속받아 오버라이드)
myDog.showOff() // "바둑이가 꼬리를 흔들며 전시됩니다!" (프로토콜 준수)
Exhibitable 프로토콜은 동물원에서 전시 가능한 동물이 따라야 할 규칙을 정의해요.
showOff() 메서드를 필수로 구현해야 함.
비유: 동물원에서 "전시 동작"을 어떻게 할지 규칙을 정한 것.
Animal 클래스는 모든 동물의 기본 속성과 동작을 정의.
name 속성과 makeSound() 메서드를 가짐.
비유: 모든 동물이 공통적으로 가지는 기본 특성(이름, 소리).
Dog는 Animal을 상속받아 name과 makeSound()를 물려받음.
makeSound()를 오버라이드해서 강아지 특유의 소리("멍멍")를 출력.
동시에 Exhibitable 프로토콜을 준수하며 showOff()를 구현.
비유: 강아지는 동물의 기본 특성을 물려받고, 추가로 전시 규칙을 따름.
Dog 객체(myDog)를 생성하고, 상속받은 메서드와 프로토콜 메서드를 호출.
상속: makeSound() → 부모로부터 물려받아 오버라이드.
프로토콜: showOff() → 전시 규칙을 따름.
상속: Dog가 Animal의 기본 특성(name, makeSound)을 물려받아 재사용하고, 필요에 따라 수정(오버라이드).
프로토콜: Dog가 동물원에서 전시 가능한 동물로 동작하기 위해 Exhibitable 규칙을 따름.
비유로 이해
상속: 강아지는 동물이라는 큰 카테고리에 속해서 기본 특성(이름, 소리)을 물려받음.
프로토콜: 동물원에서 전시하려면 "전시 동작"이라는 규칙을 따라야 함. 강아지는 꼬리를 흔드는 방식으로 전시.
바둑이가 짖습니다: 멍멍!
바둑이가 꼬리를 흔들며 전시됩니다!