본문 바로가기

iOS

iOS_week13

1) 새 ViewController 추가 (Shift + cmd + l )

2) TabBar에서 Ctrl 키 누르고 새 컨트롤러로 드래그 -> Relationship segue 의 view Controllers 클릭

=> Item Scene으로 변경됨

3) Item의 별표를 클릭하여 Web으로 변경 -> Web Scene으로 변경됨, 이미지도 network로 

4) 새 파일 Cocoa Touch Class 로 만듦 -> 이름 WebViewController, 부모 클래스 : UIViewClass

5) WebScene의 identity Inspector에서 클래스 연결

 

 

deprecated :  부정적인 의미 O, 하지만 기술적·관리적 이유로 “정중하게 폐기 예정”이라는 느낌

Legacy: 부정적 의미 강함, “구닥다리”, “낡아서 바꾸고 싶지만 아직 쓰는 중”

 

//
//  Web1ViewController.swift
//  B_BMIYOO
//
//  Created by Induk-cs on 2025/11/24.
//버튼을 눌렀을때 naver로 이동하는 코드 - gpt

import UIKit
import WebKit

class Web1ViewController: UIViewController {
    
    @IBOutlet weak var webView: WKWebView!
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Do any additional setup after loading the view.
    }
    
    @IBAction func goNaver(_ sender: UIButton) {
        if let url = URL(string: "https://m.naver.com") {
            let request = URLRequest(url: url)
            webView.load(request)
        }
    }
}

URL Protocol만 바꿔줘도 다양한 앱이나 웹을 실행할 수 있음.

 

웹사이트를 열기 위한 과정

1) URL 설정

2) URLRequest : 서버에 응답요청

- 함수의 매개변수가 진하게 되어있는거는 반드시 명시해야되는 것이고, 흐릿한 부분은 디폴트값이 있어서 안써도됨.

url은 failable initializer라서 옵셔널형임

 

** 원래는 아래의 과정을 통해서 WebKit.framework를 추가해야 컴파일 시에 에러안나고 동작함. **

현재 사용버전인 14버전이 자동으로 해주기 때문에 따로 하지않아도 잘 동작하는 것임 -> 시험에 나올 수 있음

강제 언래핑은 url이 없을 시 동작을 안함.

첫번째 방법으로 언래핑

옵셔널이 풀려있는 것을 확인가능

url만 필수, 나머지는 디폴트값이 존재

 

- Web Tab을 클릭시 내 블로그 화면이 바로 뜨도록 하는 코드 추가

//
//  Web1ViewController.swift
//  B_BMIYOO
//
//  Created by Induk-cs on 2025/11/24.
//

import UIKit
import WebKit

class Web1ViewController: UIViewController {
    
    @IBOutlet weak var webView: WKWebView!
    override func viewDidLoad() {
        super.viewDidLoad()
        guard let url1 = URL(string:"https://dunoning52.tistory.com") else { return }
       let request = URLRequest(url: url1)
        webView.load(request)
        // Do any additional setup after loading the view.
    }
    
    @IBAction func goNaver(_ sender: UIButton) {
        guard let url1 = URL(string:"https://m.naver.com") else { return }
        //모바일 사이트는 www. 대신에 m.만 써도 됨
       let request = URLRequest(url: url1)
        webView.load(request)
        }
    }

//리펙토링 코드 -> gpt
import UIKit
import WebKit

class Web1ViewController: UIViewController {
    
    @IBOutlet weak var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        loadURL("https://dunoning52.tistory.com")
    }
    
    @IBAction func goNaver(_ sender: UIButton) {
        loadURL("https://m.naver.com")
    }
}

// MARK: - URL 로딩 기능 분리
extension Web1ViewController {
    /// 입력한 URL 문자열을 로드하는 공통 메서드
    func loadURL(_ urlString: String) {
        guard let url = URL(string: urlString) else {
            print("❌ 잘못된 URL: \(urlString)")
            return
        }
        let request = URLRequest(url: url)
        webView.load(request)
    }
}

 

시뮬레이터를 돌려보면 UI가 화면에 맞지 않음 -> 앱 스토어 출시 불가.

경고가 뜨는 이유가 이것 때문임. 화면 디자인을 제대로 하지 않았다.

Align 이라고 하는 auto-layout 메뉴임

"이 버튼은 가로 세로로 돌려도 항상 가운데에 위치하도록 하겠다" 라는 의미.

add constraints 누르면 적용

 

Xcode에서 오토 레이아웃을 설정하는 방법 - 시험 범위는 아님

더보기

Xcode에서 오토 레이아웃(Auto Layout) 을 설정하는 방법을 가장 쉽게 이해할 수 있도록 단계별로 정리해줄게.
(초보자용 + 실무에서 바로 쓰는 방식 둘 다 포함!)


🚀 1. 오토 레이아웃이란?

화면 크기가 달라도 UI가 깨지지 않도록
제약(Constraints) 을 걸어서 위치와 크기를 고정하거나 비율로 유지하는 시스템.


2. Xcode에서 오토 레이아웃 적용하는 기본 흐름

Step 1. 스토리보드에서 View 선택

오토레이아웃을 설정하려는 버튼/라벨/이미지 등을 클릭.


Step 2. 아래쪽의 "Add New Constraints" 버튼 클릭

스토리보드 아래에 있는 버튼들 중:

🔧 아이콘 순서 중 가운데 있는 것

⬜️ | ⬛️
처럼 생긴 Constraints 추가 버튼 클릭.


Step 3. 여백(Spacing) 설정하기

팝업이 뜨면…

  • 상 / 하 / 좌 / 우 여백
  • Width(가로) / Height(세로)

등을 넣을 수 있음.

예:

  • 좌우 간격 20
  • 위에서 100
    등.

여백 값을 입력하면 선이 빨갛게 → 선택된 상태.


Step 4. “Add Constraints” 버튼 클릭

선택된 제약이 실제로 적용됨.


3. Auto Layout의 기본 원리

오토레이아웃은 위치 + 크기가 결정되어야 한다.

따라서 보통 아래 2개 이상을 잡아야 문제 없음:

  • 좌우 거리 or 가운데 정렬
  • 위/아래 거리
  • width/height or content 기반 크기

📌 4. 제일 많이 쓰는 Auto Layout 조합 예시

✔ 버튼을 화면 가운데 놓기

  1. 버튼 선택
  2. 아래쪽 Align 메뉴 클릭 (두 번째 아이콘)
  3. Horizontally in Container 체크
  4. Vertically in Container 체크
  5. Add 2 Constraints 클릭 → 끝

✔ 이미지뷰 화면 전체에 꽉 채우기

  1. 이미지뷰 선택
  2. Add Constraints 클릭
  3. 상/하/좌/우 모두 0 입력
  4. Add Constraints → 끝

✔ UI를 상단에 고정하고 여백 주기

  1. 위(Top) = 20
  2. Leading(왼쪽) = 16
  3. Trailing(오른쪽) = 16
  4. 높이(Height) 44

끝!


🧭 5. Auto Layout 설정 버튼들 설명

버튼 기능
⬜️⇄⬛️ (Add New Constraints) 상/하/좌/우 여백, Width/Height 설정
🟦↔️🟦 (Align) 가운데 정렬, 좌/우 정렬, baseline 정렬
↔️⟷↔️ (Resolve Auto Layout Issues) 경고 수정, 프레임 업데이트
➕ (Pin) 오브젝트 간 간격 고정

⚠️ 6. 자주 발생하는 오류 + 해결법

❓ “Ambiguous Layout”

제약이 부족해서 위치/크기 확정 불가
제약을 하나 더 추가해라 (특히 width/height 또는 양 끝 여백)

❓ “Conflicting Constraints”

서로 모순되는 제약
➡ 둘 중 하나 삭제

❓ 프레임이 안 맞음

➡ “Update Frames” 클릭


✔️ 필요하면 내가 UI 모양 보고 정확한 오토레이아웃 제약 조합도 잡아줄 수 있음

(예: 로그인 화면, 상단바, WebView fullscreen 등)

UI 스크린샷 보여주면 직접 제약 세팅해줄까?

4가지 방법이 존재 - Stack View를 많이 사용함

 

-문법 설명 p.72 (시험에 무조건 출제)

present(_:animated:completion:) 함수.

func present( _ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil )

UIViewController에 속해있는 함수로, 화면에 무언가를 보여줄 때 사용

더보기

아주 좋다!
아래에서 present(_:animated:completion:) 함수가 무엇이고, 어떤 상황에서 어떻게 쓰는지 기초 → 중급 → 실전 예시 순으로 가장 이해하기 쉽게 설명해줄게.


🚀 1. 이 함수는 뭐하는 함수인가?

present(_:animated:completion:) 는
현재 화면(ViewController) 위에 새로운 화면을 모달로 띄우는 기능이다.

즉:

  • 전체 화면으로 띄우기
  • 바텀시트처럼 올리기
  • 팝업처럼 띄우기
    모두 이 함수로 가능!

🧩 2. 함수 구조 다시 보기

func present(
    _ viewControllerToPresent: UIViewController,
    animated flag: Bool,
    completion: (() -> Void)? = nil
)

파라미터 설명

파라미터 설명
viewControllerToPresent 화면에 띄울 뷰 컨트롤러
animated 전환 애니메이션을 사용할지 여부
completion 화면 표시가 끝난 뒤 실행할 코드 (옵션)

🎯 3. 가장 기본적인 사용법 (정석)

예: SecondViewController 화면을 모달로 띄우기

let vc = SecondViewController()
present(vc, animated: true)

이렇게 하면 자동으로 화면이 위로 올라오며 표시됨.


🎯 4. 스토리보드 기반 사용법

스토리보드에서 “SecondVC” 라는 Identifier가 있다면:

let storyboard = UIStoryboard(name: "Main", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "SecondVC")
present(vc, animated: true)

🎯 5. 전체화면으로 띄우기 (iOS13 이후 권장)

모달이 카드 형태로 뜨는 게 싫다면:

let vc = SecondViewController()
vc.modalPresentationStyle = .fullScreen
present(vc, animated: true)

🎯 6. completion 사용 예시

화면을 띄운 후 특정 작업을 하고 싶을 때 사용.

예: 화면 띄운 후 알림 띄우기

let vc = SecondViewController()
present(vc, animated: true) {
    print("화면 표시 완료!")
}

또는:

present(vc, animated: true) {
    self.showToast("화면이 열렸습니다!")
}

🎯 7. 버튼 누르면 화면 전환 예시

@IBAction func openNext(_ sender: UIButton) {
    let vc = SecondViewController()
    vc.modalPresentationStyle = .fullScreen
    present(vc, animated: true)
}

🎯 8. 바텀시트처럼 띄우기

let vc = SecondViewController()
vc.modalPresentationStyle = .pageSheet
present(vc, animated: true)

🎯 9. 팝업 스타일로 띄우기

let vc = PopupViewController()
vc.modalPresentationStyle = .overCurrentContext
vc.modalTransitionStyle = .crossDissolve
present(vc, animated: true)

🎯 10. dismiss로 닫기

모달로 띄운 화면은 dismiss로 닫는다.

dismiss(animated: true)

🧠 정리

present() 는 다음과 같은 상황에서 사용한다:

✔ 새로운 화면 모달로 열기
✔ 하단에서 올리는 형태 구현
✔ 전체 화면 전환
✔ 반투명 팝업 띄우기
✔ completion으로 후처리 실행


원하면

  • NavigationController push 방식과의 차이
  • 모달 스타일들(.formSheet, .popover, .overFullScreen 등) 비교
  • 실제 UI 스토리로 연결된 예제

도 더 자세히 설명해줄게!

completion은 디폴트 값이 존재

completion : 화면을 보여준 후에 할 일을 작성

AVPlayer 는 모든 로직 담당, AVPlayerViewController는 시각적을 보여주기 위한 기능 -> 기능을 분담하고 있다.

세 코드의 차이점을 알아둘 것. -> 세번째 코드가 가장 안정적인 UI를 가짐

 

** 클로저 ** => 익명함수

func add(x: Int, y: Int) -> Int {
    return(x+y)
}
let add1 = {(x: Int, y: Int) -> Int in
    return(x+y)
}

print(add(x:10,y:20))
print(add1(30,40)) //argument label 사용 X, 쓰면 에러남

 

let multiply = {(a: Int, b: Int) -> Int in
    return a * b
}
var result = multiply(10, 20)
print(result)

let add = {(a: Int, b: Int) -> Int in
    return a + b
}
result = add(10, 20)
print(result)

func math(x: Int, y: Int, cal: (Int, Int) -> Int) -> Int {
    return cal(x, y)
}
result = math(x: 10, y: 20, cal: add)
//cal에서 해당 클로저를 입력받아서 math 함수가 그 결과값을 출력
print(result)
result = math(x: 10, y: 20, cal: multiply)
print(result)
let multiply = {(a: Int, b: Int) -> Int in
    return a * b
}
var result = multiply(10, 20)

let add = {(a: Int, b: Int) -> Int in
    return a + b
}
result = add(10, 20)

func math(x: Int, y: Int, cal: (Int, Int) -> Int) -> Int {
    return cal(x, y)
}
result = math(x: 10, y: 20, cal: add)
//cal에서 해당 클로저를 입력받아서 math 함수가 그 결과값을 출력
print(result)
result = math(x: 10, y: 20, cal: multiply)
print(result)

result = math(x: 10, y: 20, cal: {(a: Int, b: Int) in
    return a + b
}) //cal 부분에 클로저 자체를 삽입, -> Int 를 생략가능
print(result)

result = math(x: 10, y: 20, cal: { //cal을 다 삭제 후 $로 받는것도 가능
    return $0 + $1
}) //$를 사용한 것을 매개변수 생략한 단축인자(shorthand argument name)라고 함
//$0이 첫번째, $1이 두번째 인자
print(result)

result = math(x: 10, y: 20, cal: { $0 + $1 }) //return도 생략가능
print(result)

위의 코드와 한꺼번에 실행
result = math(x: 10, y: 20, cal: {(a: Int, b: Int) -> Int in
    return a + b
}) //클로저 소스를 매개변수에 직접 작성
print(result)

result = math(x: 10, y: 20) {(a: Int, b: Int) -> Int in
return a + b
}//trailing closure
print(result)

result = math(x: 10, y: 20) {(a: Int, b: Int) in
return a + b
} //trailing closure, 리턴형 생략
print(result)

result = math(x: 10, y: 20) { return $0 + $1 } //trailing closure, 매개변수 생략하고 단축인자사용
print(result)

result = math(x: 10, y: 20) { $0 + $1 } //return 생략
print(result)

'iOS' 카테고리의 다른 글

iOS_3grade - 1주차  (1) 2026.03.03
iOS_프로젝트  (1) 2025.12.08
iOS_week12  (0) 2025.11.17
iOS_week10  (0) 2025.11.03
iOS_week9  (0) 2025.10.27