카테고리 없음

iOS 프로그래밍실무 4주차

sw0913 2025. 3. 26. 16:46

AppDelegate

import UIKit  // UIKit 프레임워크를 가져옵니다. iOS 앱 개발에 필요한 기본적인 UI 요소와 기능을 제공합니다.

@main  // 앱의 진입점을 나타내는 속성입니다. Swift 5.3 이상에서 사용됩니다.
class AppDelegate: UIResponder, UIApplicationDelegate {  // AppDelegate 클래스를 정의합니다. UIResponder를 상속하고 UIApplicationDelegate 프로토콜을 채택합니다.

    // 앱이 처음 시작될 때 호출되는 메서드입니다.
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // 앱 실행 후 추가적인 설정을 위한 지점입니다.
        return true  // 앱이 정상적으로 시작되었음을 나타냅니다.
    }

    // MARK: UISceneSession Lifecycle  // UISceneSession 생명주기 관련 메서드들을 구분하는 마크입니다.

    // 새로운 UISceneSession이 생성될 때 호출되는 메서드입니다.
    func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
        // 새로운 scene 세션이 생성될 때 호출됩니다.
        // 이 메서드를 사용하여 새 scene을 생성할 구성을 선택합니다.
        return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)  // 기본 구성으로 새 UISceneConfiguration을 반환합니다.
    }

    // 사용자가 scene 세션을 버릴 때 호출되는 메서드입니다.
    func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
        // 앱이 실행되지 않는 동안 scene 세션이 버려진 경우, 이 메서드는 application:didFinishLaunchingWithOptions 직후에 호출됩니다.
        // 이 메서드를 사용하여 버려진 scene에 특정한 리소스를 해제합니다. 해당 scene들은 다시 돌아오지 않기 때문입니다.
    }

}  // AppDelegate 클래스의 끝

SceneDelegate

import UIKit  // UIKit 프레임워크를 가져옵니다. iOS 앱의 사용자 인터페이스와 이벤트 처리를 위한 핵심 프레임워크입니다.

class SceneDelegate: UIResponder, UIWindowSceneDelegate {  // SceneDelegate 클래스를 정의합니다. UIResponder를 상속하고 UIWindowSceneDelegate 프로토콜을 채택합니다.

    var window: UIWindow?  // 앱의 윈도우를 저장하는 옵셔널 변수입니다. 이 윈도우는 앱의 뷰 계층 구조의 루트가 됩니다.

    // 새로운 UIWindowScene이 앱에 연결될 때 호출되는 메서드입니다.
    func scene(_ scene: UIScene, willConnectTo session: UISceneSession, options connectionOptions: UIScene.ConnectionOptions) {
        // 이 메서드를 사용하여 UIWindow `window`를 선택적으로 구성하고 제공된 UIWindowScene `scene`에 연결할 수 있습니다.
        // 스토리보드를 사용하는 경우, `window` 속성이 자동으로 초기화되고 scene에 연결됩니다.
        // 이 델리게이트는 연결되는 scene이나 세션이 새로운 것임을 의미하지 않습니다 (대신 `application:configurationForConnectingSceneSession`을 참조하세요).
        guard let _ = (scene as? UIWindowScene) else { return }  // scene이 UIWindowScene인지 확인합니다. 아니면 메서드를 종료합니다.
    }

    // scene이 시스템에 의해 해제될 때 호출되는 메서드입니다.
    func sceneDidDisconnect(_ scene: UIScene) {
        // 이는 scene이 백그라운드로 들어가거나 세션이 폐기될 때 shortly after 발생합니다.
        // 이 scene과 관련된 리소스 중 다음에 scene이 연결될 때 다시 생성할 수 있는 것들을 해제하세요.
        // scene은 나중에 다시 연결될 수 있습니다. 세션이 반드시 폐기된 것은 아닙니다 (대신 `application:didDiscardSceneSessions`를 참조하세요).
    }

    // scene이 비활성 상태에서 활성 상태로 전환될 때 호출되는 메서드입니다.
    func sceneDidBecomeActive(_ scene: UIScene) {
        // scene이 비활성 상태일 때 일시 중지되었거나 아직 시작되지 않은 작업을 다시 시작하려면 이 메서드를 사용하세요.
    }

    // scene이 활성 상태에서 비활성 상태로 전환될 때 호출되는 메서드입니다.
    func sceneWillResignActive(_ scene: UIScene) {
        // 이는 일시적인 중단(예: 수신 전화)으로 인해 발생할 수 있습니다.
    }

    // scene이 백그라운드에서 포그라운드로 전환될 때 호출되는 메서드입니다.
    func sceneWillEnterForeground(_ scene: UIScene) {
        // 백그라운드로 들어갈 때 made 변경 사항을 취소하려면 이 메서드를 사용하세요.
    }

    // scene이 포그라운드에서 백그라운드로 전환될 때 호출되는 메서드입니다.
    func sceneDidEnterBackground(_ scene: UIScene) {
        // 이 메서드를 사용하여 데이터를 저장하고, 공유 리소스를 해제하고, scene을 현재 상태로 복원하기에 충분한 scene별 상태 정보를 저장하세요.
    }

}  // SceneDelegate 클래스의 끝

ViewController

import UIKit  // UIKit 프레임워크를 가져옵니다. iOS 앱 개발에 필요한 사용자 인터페이스 요소와 기능을 제공합니다.

class ViewController: UIViewController {  // ViewController 클래스를 정의합니다. UIViewController를 상속받아 뷰 컨트롤러의 기능을 구현합니다.

    // 뷰 컨트롤러의 뷰가 메모리에 로드된 후 호출되는 메서드입니다.
    override func viewDidLoad() {
        // 부모 클래스(UIViewController)의 viewDidLoad 메서드를 먼저 호출합니다.
        super.viewDidLoad()

        // 뷰가 로드된 후 추가적인 설정을 수행할 수 있습니다.
        // 예를 들어, 뷰의 초기 설정, 데이터 로딩, UI 요소 구성 등을 여기서 수행할 수 있습니다.
    }

}  // ViewController 클래스의 끝
#include <stdio.h>
void Fun( int param ) // parameter(매개변수, 인자), 형식 매개변수(formal parameter)
{
printf("%d",param);
}
int main()
{
Fun( 10 ); // 10은 argument(전달인자), 실 매개변수(actual parameter)
return 0;
}

함수를 호출할때 사용하는 것은 argument(전달인자)

함수 내부에서 작동하는것은 parameter(매개변수, 인자)

파라미터(Parameter):

  • 파라미터(Parameter):
    함수나 메서드를 정의할 때 사용되는 변수입니다.
    함수 내부에서 값을 받아 처리하기 위한 이름 또는 변수라고 볼 수 있습니다.
  • 아규먼트(Argument):
    함수를 호출할 때 전달하는 실제 값입니다.
    파라미터에 대입되는 값으로, 함수 실행 시 사용됩니다.

swift에서 함수의 리턴값이 없으면 void()를 생략하여 사용 할 수 있습니다.

import UIKit

func sayHello() -> Void {
    print("Hello")
}
sayHello()
//함수 정의와 함수 호출에 관한 내용
func add(x:Int, y:Int) -> Int {
    return x+y
}
print(add(x: 10,y: 20))

var x = 10
print(type(of: x))
print(type(of: add))

함수의 자료형을 알아 보는 코드에요

30

Int

(Int, Int) -> Int

함수의 타입 (자료형,자료형,…) -> 리턴형 (Int, Int) -> Int 리턴형이 Void형이면 ()

func add(first x: Int, second y: Int) -> Int {
//외부 내부:자료형,외부 내부:자료형 -> 리턴형
return(x+y) //함수 정의할 때는 내부 매개변수명을 사용
} //return(first+second)은 오류
add(first:10, second:20) //add(x:10, y:20)은 오류
//함수 호출할 때는 외부 매개변수명을 사용

first와 second는 argument lable 외부 매개변수 명이고

x와 y는 parameter lable 내부매개 변수형입니다

외부 매개변수명 생략하면 내부 매개변수명이 외부 매개변수명까지 겸함

아래의 함수들의 이름은 다 달라요

func add(first x:Int, second y:Int) -> Int {
    print(#function)
    return x+y
}
print(add(first: 5, second: 10))

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(1,2))

func add(_ x:Int, with y:Int) -> Int {
    print(#function)
    return x + y
}
print(add(5,with:3))

프로퍼티는 클래스, 구조체, 열거형에서 소속된 변수 및 속성을 지칭하는 개념입니다

init은 자동으로 생략되는 경우가 있어요 (주의)

designated initializer

Designated initializer는 Swift에서 클래스의 기본적인 초기화 메서드입니다. 주요 특징은 다음과 같습니다:

  1. 클래스의 모든 저장 프로퍼티를 완전히 초기화합니다
  2. 필요한 경우 상위 클래스(superclass)의 initializer를 호출하여 상속 체인을 따라 초기화 과정을 이어갑니다
  3. 클래스는 최소한 하나의 designated initializer를 가져야 합니다
  4. 일반적으로 클래스는 적은 수의 designated initializer를 가지며, 많은 경우 하나만 갖습니다
  5. 초기화 과정의 "funnel point" 역할을 합니다. 즉, 모든 초기화 경로가 이 지점을 통과하게 됩니다
// Man 클래스를 정의합니다.
class Man {
    // age라는 이름의 Int 타입 저장 프로퍼티를 선언하고 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) {
        // 매개변수 age 값을 프로퍼티 age에 대입합니다.
        // self.을 사용하여 프로퍼티와 매개변수를 구분합니다.
        self.age = age

        // 매개변수 weight 값을 프로퍼티 weight에 대입합니다.
        self.weight = weight
    }
}

// Man 클래스의 인스턴스를 생성하고 kim이라는 변수에 할당합니다.
// age는 10, weight는 20.5로 초기화합니다.
var kim : Man = Man(age:10, weight:20.5)

// kim 인스턴스의 display 메서드를 호출합니다.
kim.display()

상속과 오버라이드

// Man 클래스를 정의합니다.
class Man {
    // age라는 이름의 Int 타입 저장 프로퍼티를 선언합니다.
    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
        self.weight = weight
    }
}

// Man 클래스를 상속받는 Student 클래스를 정의합니다.
class Student : Man {
    // name이라는 이름의 String 타입 저장 프로퍼티를 선언합니다.
    var name : String

    // 부모 클래스의 display 메서드를 오버라이드합니다.
    override func display() {
        // name, age, weight 값을 출력합니다.
        print("이름=\(name), 나이=\(age), 몸무게=\(weight)")
    }

    // Student 클래스의 Designated initializer를 정의합니다.
    init(age: Int, weight : Double, name : String) {
        // 자신의 프로퍼티인 name을 먼저 초기화합니다.
        self.name = name
        // 부모 클래스의 initializer를 호출하여 age와 weight를 초기화합니다.
        super.init(age:age, weight:weight)
    }
    // 주석: 이 줄을 쓰지 않으면 부모 클래스의 초기화가 이루어지지 않아 에러가 발생합니다.
    // 주석: 자식 클래스에서 designated initializer를 만들면 부모 init()이 자동으로 상속되지 않습니다.
}

// Student 클래스의 인스턴스를 생성하고 lee라는 변수에 할당합니다.
// age는 20, weight는 65.2, name은 "홍길동"으로 초기화합니다.
var lee : Student = Student(age:20, weight:65.2, name:"홍길동")

// lee 인스턴스의 display 메서드를 호출합니다.
// 이는 Student 클래스에서 오버라이드된 display 메서드가 실행됩니다.
lee.display()

Protocol

프로토콜에서 프로퍼티를 선언할 때 다음과 같은 규칙을 따라야 합니다:

  1. 프로퍼티는 항상 var로 선언해야 합니다.
  2. 읽기 전용 프로퍼티는 { get }으로 지정합니다.
  3. 읽기와 쓰기가 모두 가능한 프로퍼티는 { get set }으로 지정합니다.

프로토콜은 프로퍼티가 올 수는 있는데 get이나 set이 와야 합니다

함수에는 body가 없어야 해요

에러가 나타나는 이유가 뭘까요?

 

프로토콜의 정의

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
}
class Man에 x, run()정의 없다면
type 'Man' does not conform to protocol 'Runnable‘
et han = Man()

 

상속과 프로토콜을 동시에 사용하는 예시 코드)

// 동물 소리를 내는 프로토콜
protocol SoundMaker {
    func makeSound()
}

// 기본 동물 클래스
class Animal {
    var name: String
    
    init(name: String) {
        self.name = name
    }
    
    func eat() {
        print("\(name)이(가) 먹고 있습니다.")
    }
}

// 개 클래스: Animal을 상속받고 SoundMaker 프로토콜을 채택
class Dog: Animal, SoundMaker {
    func makeSound() {
        print("\(name): 멍멍!")
    }
    
    func fetch() {
        print("\(name)이(가) 물건을 가져옵니다.")
    }
}

// 사용 예
let myDog = Dog(name: "뽀삐")
myDog.eat()        // Animal 클래스의 메서드
myDog.makeSound()  // SoundMaker 프로토콜의 메서드
myDog.fetch()      // Dog 클래스의 고유 메서드

 

출처 - Smile Han