iOS 6,7주차

2025. 10. 14. 17:52iOS 기초/수업 내용 및 수업 후 과제

반응형

중간고사 정리

 

앱 개발 기술 2가지

cross 기술은 안드로이드 iOS 둘 다 가능한 기술이다.

2주차

xcode swift문법을 공부할때는 playground를 통해서 한다.

튜플은 매년 시험에 낸다

 

3주차 옵셔널 중요

형 변환(as로 upcasting : 자식인스턴스를 부모클래스로 변환)

형 변환(as! as?로 downcasting:부모인스턴스를 자식클래스로 변환)

다운캐스팅은 부모 인스턴스를 자식 클래스로 변환하는 데 사용

p33~34 up,downcasting이 뭔지만 알아두기

 

 

4주차

bmi코드 이해

 

6주차 p5 아래 내용만 써도 된다

클래스는 구조체에 없는 추가적인 기능이 있음 (상속이 가능하다는것)

-> 클래스는 상속이 가능하지만 구조체는 상속이 안된다

 

프로퍼티는 클래스 내에 포함되는 변수(var)와 상수(let)이며 포함되는3가지가 있다

stored property (저장된 프로퍼티) 2학기때는 이것만 할 예정

computed property

type property

 

프로퍼티 주의 사항

1. 초기값이 있거나

2. init을 이용해서 초기화하거나

3. 옵셔널 변수(상수)로 선언(자동으로 nil로 초기화)

 

3번째 생성자를 이용하는 방법이 일반적인 방법이다.

 

class Man{
    var age : Int = 1
    var weight : Double = 3.5
    //init(){}
    //눈에 보이지 않지만 자동으로 만들어지는 default initializer
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
}
var kim : Man = Man() // ()는 init()호출하는 것
kim.display() //인스턴스 메서드는 인스턴스가 호출
print(kim.age)

실행결과
나이=1, 몸무게=3.5
1

: Man은 생략 가능하다

클래스를 만들면 아무 기능은 없지만 눈에 안보이는 생성자initializer init(){} 가 만들어진다
즉,init(){}은 생략가능하다
->눈에 보이지 않지만 자동으로 만들어지는 default initializer 시험에 나온적 있다

프로퍼티 2개 매소드1개

 

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

함수를 2가지 추가했는데 뜨지 않음

객체가 가지고 놀고

클래스가 가지고 논다

class키워드로 만든 클래스 메서드는 자식 클래스에서 override가능 함

 

다시 정리하면

두 이미지는 Swift Playground에서 class Man을 작성하고, 인스턴스(kim)와 클래스(Man)의 멤버 접근 차이를 확인하는 화면이에요.
말씀하신 “함수를 2가지 추가했는데 뜨지 않음”과 “인스턴스 변수와 객체가 가지고 논다 / 클래스가 가지고 논다”의 부분을 아래처럼 정리해드릴게요 👇


🧠 코드 전체 요약 (Swift 클래스 Man)

class Man {
    var age: Int = 1          // 인스턴스 변수
    var weight: Double = 3.5  // 인스턴스 변수

    func display() {          // 인스턴스 메서드
        print("나이=\(age), 몸무게=\(weight)")
    }

    class func cM() {         // 클래스 메서드 (클래스가 소유)
        print("cM은 클래스 메서드입니다.")
    }

    static func scM() {       // 정적 메서드 (클래스 전용, 오버라이딩 불가)
        print("scM은 클래스 메서드(static)입니다.")
    }
}

// 객체 생성
var kim = Man()
kim.display()
print(kim.age)

🧩 개념 설명

구분 선언 키워드 호출 주체 예시 설명

인스턴스 변수 (속성) var 객체(인스턴스)가 소유 kim.age, kim.weight 객체마다 다른 값을 가질 수 있음
인스턴스 메서드 func 객체(인스턴스)가 호출 kim.display() 객체의 속성(age, weight)에 접근 가능
클래스 메서드 class func 클래스 자체가 호출 Man.cM() 클래스 이름으로 직접 호출, 하위 클래스에서 오버라이딩 가능
정적 메서드 static func 클래스 자체가 호출 Man.scM() 클래스 이름으로 직접 호출, 하위 클래스에서 오버라이딩 불가

🧮 인스턴스 vs 클래스의 차이 (사진 속 코드 해석)

구분 예시 설명

kim. 인스턴스(객체)가 가지고 노는 것들 → kim 뒤에 age, weight, display() 등이 나옴.즉 “객체가 가지고 노는 것(인스턴스 변수/메서드)”
Man. 클래스가 가지고 노는 것들 → cM(), scM() 같은 클래스 메서드가 나옴.즉 “클래스가 가지고 노는 것(클래스 메서드, 정적 메서드)”

💬 정리 문장 (설명 완성형)

인스턴스 변수와 메서드는 ‘객체가 가지고 노는 것’이고,
클래스 메서드는 ‘클래스가 가지고 노는 것’이다.

즉,

  • kim. → 인스턴스가 가진 속성과 행동
  • Man. → 클래스 자체가 가진 기능

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

인스턴스 초기화하기 : init()

class Man{
    var age : Int
    var weight : Double
    init(){
        age = 1
        weight = 3.5
    }

    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    
}
var kim = Man() // ()는 init()호출하는 것
kim.display() //인스턴스 메서드는 인스턴스가 호출

실행결과
나이=1, 몸무게=3.5

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
class Man{
    var age : Int
    var weight : Double
    init(){
        age = 1
        weight = 3.5
    }

    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    
}
var kim = Man() // ()는 init()호출하는 것
kim.display() //인스턴스 메서드는 인스턴스가 호출
var kim1 = Man() // ()는 init()호출하는 것
kim1.display() //인스턴스 메서드는 인스턴스가 호출

실행결과
나이=1, 몸무게=3.5
나이=1, 몸무게=3.5
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

self는 언제쓰는지 : 현재 클래스 내 메서드나 프로퍼티를 가리킬 때 메서드나 프로퍼티 앞에 self.을 붙임

시험문제

새로운 이니셜라이져만들기self

class Man{
    var age : Int
    var weight : Double
    //    init(){
    //        age = 1
    //        weight = 3.5
    //    }
    
    init(age: Int, weight : Double){
        self.age = age
        self.weight = weight
    } //designated initializer
    
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    
}
var kim = Man(age: 2, weight: 4.5) // ()는 init()호출하는 것
kim.display() //인스턴스 메서드는 인스턴스가 호출

실행결과
나이=2, 몸무게=4.5

매개변수와
구분하기 위해 반드시 써야함

 

 

객체지향언어(OOP)에서 **this**와 **self**는 “현재 객체 자신”을 가리키는 참조(reference)입니다.
언어마다 이름과 동작 방식이 조금씩 다르므로 아래 표로 정리해드릴게요 👇


🧠 객체지향언어에서 this / self 비교표

언어 키워드 의미 사용 위치 특징 / 비고 예시

Java this 현재 객체(인스턴스 자기 자신) 인스턴스 메서드, 생성자 지역변수와 멤버변수를 구분할 때 자주 사용 java<br>class A {<br> int x;<br> A(int x){ this.x = x; }<br> }
C++ this 현재 객체의 포인터 인스턴스 메서드 내부 내부적으로 this는 포인터 (A* this) 형태 cpp<br>class A { int x; <br>void set(int x){ this->x = x; } };
C# this 현재 객체 참조 인스턴스 메서드, 생성자 클래스 자신을 나타내며, 다른 생성자 호출에도 사용 가능 (this()) csharp<br>class A { int x; A(int x){ this.x = x; } }
Swift self 현재 인스턴스 자신 모든 인스턴스 메서드 지역변수와 구분 필요할 때만 명시 swift<br>class A { var x=0; func setX(x:Int){ self.x = x } }
Python self 현재 객체를 나타내는 첫 번째 매개변수 모든 인스턴스 메서드의 첫 번째 인자 자동 전달되지 않음 → 명시적으로 정의해야 함 python<br>class A:<br> def __init__(self,x): self.x = x
Objective-C self 현재 객체 자신 인스턴스 메서드 클래스 메서드에서는 self가 클래스 자체를 가리킴 objc<br>- (void)setX:(int)x { self->x = x; }
Ruby self 현재 객체 자신 인스턴스 메서드, 클래스 메서드 문맥에 따라 인스턴스/클래스 자신을 가리킴 ruby<br>class A<br> def show; puts self; end<br>end
JavaScript this 현재 실행 문맥의 객체 함수, 메서드, 이벤트 핸들러 호출 방식에 따라 달라짐 (동적 바인딩) js<br>function f(){ console.log(this); }
PHP $this 현재 객체 자신 클래스 내부 정적 메서드에서는 사용 불가 php<br>class A { function show(){ echo $this->x; } }

💡 핵심 요약

구분 설명

공통점 객체 자신(현재 인스턴스)을 참조함
this 사용 언어 Java, C++, C#, JavaScript, PHP
self 사용 언어 Python, Swift, Ruby, Objective-C
포인터 vs 참조 차이 C++은 this가 포인터, 나머지는 참조(객체 그 자체)
Python의 특징 self는 예약어가 아니라 명시적으로 첫 인자로 전달해야 함
JavaScript의 특징 this가 호출 방식에 따라 가리키는 객체가 달라짐 (함수/이벤트/클래스 등)

중간고사 시험에 나온적 있음

designated initializer (지정 생성자)

    = 모든 프로퍼티(age, weight)를 다 초기화시키는 생성자

   //init()을 하나라도 직접 만들면 default initializer는 사라짐

 

default initializer

   = 눈에 보이지 않지만 자동으로 만들어지는 생성자

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

method overloading : 생성자 중첩

매개변수의 개수와 자료형이 다른 같은 이름의 함수를 여러 개 정의
매개변수가 다른 두 생성자를 통해 여러가지방법으로 인스턴스를 만들 수 있음

=> 편하게 객체를 만들 수 있기 때문에 한다.

class Man{
    var age : Int
    var weight : Double
    init(){
        age = 1
        weight = 3.5
    }//designated initializer
    
    init(age: Int, weight : Double){
        self.age = age
        self.weight = weight
    } //designated initializer
    
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    
}
var kim = Man(age: 2, weight: 4.5)
kim.display()
var kim1 = Man()
kim1.display()

실행결과
나이=2, 몸무게=4.5
나이=1, 몸무게=3.5

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

failable initializer( 실패 가능한 생성자: init?() )

Swift에서 init? — 즉, 물음표가 붙은 초기화 메서드(이니셜라이저) — 는 **“실패할 수 있는

초기화(Failable Initializer)”**를 의미합니다.


🧩 기본 개념

구문 의미

init() 항상 성공하는 일반 초기화
init?() 실패할 수도 있는 초기화 → 옵셔널(Optional) 반환

즉,
init?은 객체 생성(초기화) 중에 문제가 발생하면 nil을 반환해서 “객체를 만들지 않는다”는 뜻이에요.


✅ 예제 1: 일반 init (항상 성공)

class Person {
    var name: String

    init(name: String) {
        self.name = name
    }
}

let p1 = Person(name: "정상연")   // ✅ 항상 성공

init()은 실패 개념이 없어요.
무조건 객체가 생성됩니다.


⚠️ 예제 2: 실패 가능한 init? (init 뒤에 ?)

class Person {
    var name: String

    init?(name: String) {
        if name.isEmpty {
            return nil   // ❌ 실패 → 객체 생성 안됨
        }
        self.name = name
    }
}

let p1 = Person(name: "정상연")   // ✅ 성공 → p1은 Person 타입
let p2 = Person(name: "")         // ❌ 실패 → p2는 nil

👉 결과적으로

  • init?은 Person? (옵셔널) 타입을 반환해요.
  • 즉, 생성 결과가 nil이 될 수 있습니다.

🧠 사용 이유

init?은 초기화 도중 오류가 날 수 있는 상황에서 안전하게 실패를 표현하기 위해 사용합니다.

상황 예시

입력값이 잘못된 경우 음수 나이를 가진 사람, 빈 이름 등
파일, URL 등 외부 리소스 로드 실패 UIImage(named:), URL(string:) 등이 전형적인 init? 예
데이터 변환 실패 예: JSON → 객체 변환 실패

📌 실제 시스템 클래스 예시

클래스 초기화 메서드 설명

UIImage(named:) init?(named:) 이미지 이름이 틀리면 nil 반환
URL(string:) init?(string:) 잘못된 문자열이면 nil 반환
Int("123") init?(_ text: String) 문자열이 숫자로 변환 불가하면 nil
let img = UIImage(named: "not_exist")   // nil
let url = URL(string: "http://...")     // URL?
let number = Int("abc")                 // nil

💡 요약표

형태 의미 반환 타입 예시

init() 성공 보장 초기화 MyClass let a = MyClass()
init?() 실패 가능 초기화 MyClass? let a = MyClass() → nil 가능

✅ 결론

init?은 **객체 생성이 실패할 수 있는 경우에 사용하는 “실패 가능한 초기화 함수(Failable Initializer)”**입니다.
객체 생성이 실패하면 nil을 반환하며, 결과는 옵셔널 타입이 됩니다.


만약 나이가 음수인 사람의 인스턴를 만들려고 하면 nil을 반환

- 없는 파일로 이미지 인스턴스를 만들려고 하면 nil 반환

- 인스턴스를 만들 수 없는 상황이면 nil을 반환 

- init다음에 "?"가 있는 init?()는 인스턴스가 만들어져도 옵셔널형으로 만들어짐

- 사용하려면 옵셔널을 언래핑해야 함

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

failable initializer 만들기 1단계

init다음에 ? 붙이기

class Man{
    var age : Int
    var weight : Double

    init?(age: Int, weight : Double){
        self.age = age
        self.weight = weight
    }

    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    
}
var kim = Man(age: 2, weight: 4.5)
kim.display()

2단계
class Man{
    var age : Int
    var weight : Double
    
    init?(age: Int, weight : Double){
        if age <= 0 || weight <= 0.0 {
            return nil
        }
        else {
            self.age = age
            self.weight = weight
        }
    } // failable initializer
    
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    
}
var kim = Man(age: 2, weight: 4.5)
kim.display()

3단계 강제 언랩핑
class Man{
    var age : Int
    var weight : Double
    
    init?(age: Int, weight : Double){
        if age <= 0 || weight <= 0.0 {
            return nil
        }
        else {
            self.age = age
            self.weight = weight
        }
    } // failable initializer
    
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    
}
var kim = Man(age: 2, weight: 4.5)
kim!.display()

실행결과
나이=1, 몸무게=4.5
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
하지만 위험이 있다 crash가 날 수도 있기 때문에

3단계 다른방법

class Man{
    var age : Int
    var weight : Double
    
    init?(age: Int, weight : Double){
        if age <= 0 || weight <= 0.0 {
            return nil
        }
        else {
            self.age = age
            self.weight = weight
        }
    } // failable initializer
    
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    
}
var kim = Man(age: 2, weight: 4.5)!
kim.display()

여기서 kim은 그냥 Man형 (사진참고)
(그냥 옵셔널형)
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
3단계 옵셔널 바인딩
가장 안전한 방법
//1-1.옵셔널 형으로 선언
if let kim1 = kim { //1-2.옵셔널 바인딩
kim1.display()
}


class Man{
    var age : Int
    var weight : Double
    
    init?(age: Int, weight : Double){
        if age <= 0 || weight <= 0.0 {
            return nil
        }
        else {
            self.age = age
            self.weight = weight
        }
    } // failable initializer
    
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    
}
var kim = Man(age: 2, weight: 4.5)
if let kim1 = kim{
    kim1.display()
}

여기서
if let kim1 = kim{부분에서
1을 생략하고 kim = kim이라고 써도 되고
if let kim{
kim.display()}
이렇게 써도 된다

즉 3가지 방법이 있다
1.
if let kim1 = kim{
    kim1.display()
}

2.
if let kim1 = kim{
 kim1.display()
}

3.
if let kim{
  	kim.display()
}
ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
var kim = Man(age: 2, weight: 4.5)
    if let kim1 = kim{
    kim1.display()
}을 줄이는 방법


//2.인스턴스 생성과 동시에 옵셔널 바인딩
if let kim2 = Man(age:2, weight:5.5) {
kim2.display()
}


ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
정리 시험에 나옴
**Failable initializer(init?)**로 생성된 객체는 옵셔널(Optional) 타입이기 때문에,
사용하려면 반드시 “옵셔널을 풀어서(Unwrap)” 실제 객체로 접근해야 합니다.

이 옵셔널을 해제 하는 방법이 대표적으로 4가지가 있습니다.
var kim : Man? = Man(age:1, weight:3.5)을 바꾸는 방법 4가지
1,2번을 제일 좋은 방법

//1-1.옵셔널 형으로 선언
if let kim1 = kim { //1-2.옵셔널 바인딩
kim1.display()
}
//2.인스턴스 생성과 동시에 옵셔널 바인딩
if let kim2 = Man(age:2, weight:5.5) {
kim2.display()
}
//3.인스턴스 생성하면서 바로 강제 언래핑
var kim3 : Man = Man(age:3, weight:7.5)!
kim3.display()
//4.옵셔널 인스턴스를 사용시 강제 언래핑
var kim4 : Man? = Man(age:4, weight:10.5)
kim4!.display()

2번째에서 kim은 옵셔널 Man형

failable initializer에서 만들어진 객체는 일반형이 아닌 옵셔널형이 된다

 ->“failable initializer(init?)로 만들어진 객체는 옵셔널형(Man?)이 된다.”

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

super : 부모 메서드 호출 시 사용

class Man{
    var age : Int
    var weight : Double
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    init(age: Int, weight : Double){
        self.age = age
        self.weight = weight
    }
}
class Student : Man {
    var name : String
    func displayS() {
        print("이름=\(name), 나이=\(age), 몸무게=\(weight)")
    }
    init(age: Int, weight : Double, name : String){
        self.name = name //자식의 프로퍼티 먼저 초기화
        super.init(age:age, weight:weight)
    }
}
var kim = Man(age:10, weight:20.5)
kim.display()
//var kim1 = Student(age:10, weight:20.5)
//kim1.display

실행결과
나이=10, 몸무게=20.5
ㅡㅡㅡㅡㅡㅡㅡㅡㅡ
class Man{
    var age : Int
    var weight : Double
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    init(age: Int, weight : Double){
        self.age = age
        self.weight = weight
    }
}
class Student : Man {
    var name : String
    func displayS() {
        print("이름=\(name), 나이=\(age), 몸무게=\(weight)")
    }
    init(age: Int, weight : Double, name : String){
        self.name = name //자식의 프로퍼티 먼저 초기화
        super.init(age:age, weight:weight)
    }
}
var kim = Man(age:10, weight:20.5)
kim.display()
var kim1 = Student(age: 20, weight: 65.5, name: "KIM1")
kim1.display()
kim1.displayS()

실행결과
나이=10, 몸무게=20.5
나이=20, 몸무게=65.5
이름=KIM1, 나이=20, 몸무게=65.5


-> 자식이 새로 만든것을 출력하니까 이름까지 출력함

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
class Man{
    var age : Int
    var weight : Double
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    init(age: Int, weight : Double){
        self.age = age
        self.weight = weight
    }
}
class Student : Man {
    var name : String
    func displayS() {
        print("이름=\(name), 나이=\(age), 몸무게=\(weight)")
    }
    init(age1: Int, weight1 : Double, name : String){
        self.name = name //자식의 프로퍼티 먼저 초기화
        super.init(age:age1, weight:weight1)
    }
}
var kim = Man(age:10, weight:20.5)
kim.display()
var kim1 = Student(age1: 20, weight1: 65.5, name: "KIM1")
kim1.display()
kim1.displayS()

헷갈리지 않도록 변경
어디 어디가 똑같이 사용되는건지 확인

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ
class Man{
    var age : Int
    var weight : Double
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    init(age: Int, weight : Double){
        self.age = age
        self.weight = weight
    }
}
class Student : Man {
    var name : String
    func displayS() {
        print("이름=\(name), 나이=\(age), 몸무게=\(weight)")
    }
    init(age1: Int, weight1 : Double, name : String){
        
        super.init(age:age1, weight:weight1)
        self.name = name //자식의 프로퍼티 먼저 초기화
    }
}
var kim = Man(age:10, weight:20.5)
kim.display()
var kim1 = Student(age1: 20, weight1: 65.5, name: "KIM1")
kim1.display()
kim1.displayS()

이렇게 하면 오류가 나는데
        super.init(age:age1, weight:weight1)
        self.name = name //자식의 프로퍼티 먼저 초기화
        이 두개의 순서를 바꾸면 안된다 자식의 프로퍼티 먼저 초기화하고
        나머지를 부모쪽으로 넘겨서 처리해야하므로
        
        self.name = name //자식의 프로퍼티 먼저 초기화
        super.init(age:age1, weight:weight1)
        이렇게 써야한다

객체지향언어에서 본인이나 자식에게 접근할때는 this나 self사용

부모에게 접근할때는 super사용

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

override : 자식 클래스에서 메서드 재정의

위에 코드에서 displayS()에서 S를 빼려면
class Man{
    var age : Int
    var weight : Double
    func display(){
        print("나이=\(age), 몸무게=\(weight)")
    }
    init(age: Int, weight : Double){
        self.age = age
        self.weight = weight
    }
}
class Student : Man {
    var name : String
    override func display() { // 이부분
        print("이름=\(name), 나이=\(age), 몸무게=\(weight)")
    }
    init(age1: Int, weight1 : Double, name : String){
        self.name = name //자식의 프로퍼티 먼저 초기화
        super.init(age:age1, weight:weight1)
    }
}
var kim = Man(age:10, weight:20.5)
kim.display()
var kim1 = Student(age1: 20, weight1: 65.5, name: "KIM1")
kim1.display()
kim1.displayS()


 -> override func display() { // 이부분 이렇게 써야한다


즉, override func display() 는 
부모 클래스의 display() 메서드를 자식 클래스에서 다시 정의(재작성)할 때 사용하는 문법이다.

ㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡㅡ

ViewController.swift에서 Swift 문법 이해하기
import UIKit
class ViewController: UIViewController {
    @IBOutlet var lblHello: UILabel!
    @IBOutlet var txtName: UITextField!
    //Interface Builder Outlet(변수, 프로퍼티)
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    @IBAction func btnSend(_ sender: UIButton) {
        //Interface Builder Action(함수, 메서드)
        lblHello.text = "Hello, " + txtName.text!
    }
}


@IBOutlet,@IBAction는 몰라도 된다

좋아요 😊
이 코드는 iOS UIKit에서 가장 기본적인 “입력 → 출력” 앱 예제예요.
아래에 코드 + 실행 순서 + 출력 결과까지 한눈에 정리해드릴게요 👇


🧩 전체 코드

import UIKit

class ViewController: UIViewController {
    @IBOutlet var lblHello: UILabel!
    @IBOutlet var txtName: UITextField!
    // Interface Builder Outlet (화면의 UI 요소를 코드 변수로 연결)
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 화면이 처음 로드될 때 한 번 실행됨
    }
    
    @IBAction func btnSend(_ sender: UIButton) {
        // Interface Builder Action (버튼 클릭 시 실행)
        lblHello.text = "Hello, " + txtName.text!
    }
}

🧠 코드 동작 순서

순서 동작 내용 설명

앱 실행 → 화면 로드 viewDidLoad() 호출
사용자가 텍스트 필드(txtName)에 이름 입력 예: “정상연” 입력
버튼 클릭 (btnSend) 연결된 @IBAction func btnSend() 실행
코드 실행 → lblHello.text = "Hello, " + txtName.text! 라벨의 내용 변경
결과 출력 화면의 라벨에 "Hello, 정상연" 표시됨

🖥️ 실제 출력 결과 예시

입력(TextField) 버튼 클릭 후(Label 출력 결과)

John Hello, John
민수 Hello, 민수
정상연 Hello, 정상연

🔍 용어 간단 요약

구문 설명

@IBOutlet 스토리보드 UI 객체(라벨, 텍스트필드)를 코드 변수에 연결
@IBAction 스토리보드 UI 동작(버튼 클릭)을 코드 함수에 연결
viewDidLoad() 화면이 처음 표시될 때 자동 실행되는 초기화 함수
lblHello.text 라벨에 표시되는 문자열
txtName.text! 텍스트필드에 입력된 문자열 (옵셔널 강제 해제)

결론 한줄 요약:

사용자가 입력한 이름을 가져와 버튼을 누르면,
화면의 라벨에 “Hello, (입력한 이름)” 이 표시되는 간단한 iOS UIKit 프로그램이다.