📕 iOS/UIKit

[iOS App Dev Tutorials - UIKit] Ch.1 UIKit essentials

이오🐥 2023. 7. 5. 15:12

UIKit 프로젝트를 시작했는데, 여전히 익숙하지 않은 것 같아서

애플의 튜토리얼을 해보려고 한다!

 

저번 프로젝트에서 느낀건데, 나중에 기록해야지! 하면 안하게 된다..

바로바로 하면서 기록해야지!


 

 Chapter 1. UIKit essentials 

 

Develop apps for iOS | Apple Developer Documentation

Learn the basics of Xcode, SwiftUI, and UIKit to create compelling iOS apps.

developer.apple.com


 Getting started with Today 

UIKit overview

UIKit은 Apple 플랫폼의 앱을 만들기 위한 graphical framework이다.

  • Extensive API coverage
  • Compositional layouts
  • Precise UI display
  • Legacy app support
  • Strong community adoption
  • Interoperability with SwiftUI

 

Tour of the app

튜토리얼로 진행할 Today 앱의 기능을 살펴보자!

  • Reminder list
    • 메인 화면에서는 사용자의 리마인더들이 리스트로 보여진다.
    • 상단에서는 segment control로 Today, Future, All을 확인할 수 있다.
    • 완료버튼을 눌러 진행률을 표시하는 원을 채울 수 있다.
    • 그리고, + 버튼으로 새로운 리마인더를 추가할 수 있다.
  • Reminder view and editing modes
    • 상세 화면에서는 리마인더의 제목, 기한, 추가 노트를 확인할 수 있다.
    • Edit버튼으로 상세 내용을 수정할 수 있다.
  • Add reminder screen
    • 메인 화면에서 +버튼을 누르면 나타난다.
    • Edit 화면과 cell들을 공유한다.
    • 하지만, modal로 나타난다.

 

Tips for success

해보면서 공부하자. 적극적으로 공부하자! 최신버전의 Xcode를 사용하자ㅎㅎ

 

Time to build the app

파이팅!

 


 Creating a list view 

이번에는 app의 root view를 만들고,

user의 daily reminder를 보여주기위한 list layout을 collection view로 만들자.

 

collection view를 구성하고, cell의 내용을 구성하자.

그리고, 각 cell에 데이터를 연결해서 데이터가 바뀌면 UI가 업데이트되도록 하자.

 

 Section 1. Create a project 

Today라는 이름의 프로젝트를 생성하고,

Simulator를 실행해보자!

 

실행 버튼을 클릭하면,

Xcode는 선택한 대상에 대해 앱을 컴파일하고,

framwork를 연결하고, resource를 bundle하고,

시뮬레이터에 앱을 배포한다.

 

 

 Section 2. Add a collection view controller 

이제 storyboard에 view controller를 추가한다.

View controller는 view와 data model간의 다리 역할을 한다.

각각의 view controller는 view 계층을 관리하고, view의 내용을 업데이트하고, 사용자의 이벤트에 반응한다.

 

Interface Builder를 이용해 collection view controller를 만든다.

Collection view는 grid, 열, 행, table을 표현할 수 있다.

 

Collection View Controller를 만들고, cell template은 지운다.

이 View controller를 initial view controller로 설정해준다.

 

 Section 3. Create a reminder model 

UIKit의 일반적인 디자인 패턴인 MVC(Model-View-Controller)의 구조로 만든다.

View는 시간적인 표현을 나타내고, Model은 데이터와 business logic을 관리한다.

View controller를 이용해 model이 직접적으로 view와 model이 서로 직접 영향을 미치지 않도록 한다.

import Foundation

struct Reminder {
    var title: String
    var dueDate: Date
    var notes: String? = nil
    var isComplete: Bool = false
}
  • Project 안에 Models 폴더를 생성하고, Reminder.swift 파일을 만든다.
    • property에 대한 Initializer를 만들 필요가 없다.
    • Swift compiler는 자동으로 각 structure에 대한 memberwise initializer를 제공한다.
#if DEBUG
extension Reminder {
	static var sampleData = [
        Reminder(
            title: "Submit reimbursement report",
            dueDate: Date().addingTimeInterval(800.0),
            notes: "Don't forget about taxi receipts"),
        Reminder(
            title: "Code review",
            dueDate: Date().addingTimeInterval(14000.0),
            notes: "Check tech specs in shared folder",
            isComplete: true)
    ]
}
#endif

 

  • Sample Data를 추가한다.
  • #if DEBUG
    • release를 위한 build를 하면 complie할 때 이 코드를 포함하지 않는다.
    • sample data, test를 위한 code를 작성할 때, 사용할 수 있다.

 

 Section 4. Configure the collection as a list 

Compositional layout을 이용해 collection view를 구성한다.

Compositional layout은 section, group, item과 같은 다양한 요소를 결합해 view를 만들 수 있다.

Section은 item group의 바깥 container view이다.

class ReminderListViewController: UICollectionViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        
        let listLayout = listLayout()
        collectionView.collectionViewLayout = listLayout
    }

    private func listLayout() -> UICollectionViewCompositionalLayout {
        var listConfiguration = UICollectionLayoutListConfiguration(appearance: .grouped)
        listConfiguration.showsSeparators = false
        listConfiguration.backgroundColor = .clear
        return UICollectionViewCompositionalLayout.list(using: listConfiguration)
    }
}
  • ViewController를 ReminderListViewController로 변경하고, UICollectionViewController를 상속한다.
  • UICollectionViewCompositionalLayout을 return하는 method listLayout()을 만든다.
  • viewDidLoad()에 listLayout을 선언해준다.
    • View Controller가 view hierarchy를 로드하고, viewDidLoad가 호출된다.

 

 Section 5. Configure the data source 

Collection View에 cell을 만들고, content configuration을 이용해 cell의 모양을 정하고, data source와 연결한다.

diffable data source를 사용하여 데이터가 바뀌면 UI를 업데이트한다.

typealias DataSource = UICollectionViewDiffableDataSource<Int, String>

var dataSource: DataSource!
// cell의 내용과 모양을 구성
let cellRegistration = UICollectionView.CellRegistration {
    (cell: UICollectionViewListCell, indexPath: IndexPath, itemIdentifier: String) in
    // 항목에 해당하는 미리 알림 가져오기
    let reminder = Reminder.sampleData[indexPath.item]
    // cell의 기본 구성 가져오기
    var contentConfiguration = cell.defaultContentConfiguration()
    contentConfiguration.text = reminder.title
    cell.contentConfiguration = contentConfiguration

}

dataSource = DataSource(collectionView: collectionView) {
    (collectionView: UICollectionView, indexPath: IndexPath, itemIdentifier: String) in
    return collectionView.dequeueConfiguredReusableCell(using: cellRegistration, for: indexPath, item: itemIdentifier)
}
  • Cell registration은 cell의 내용과 모양을 구성한다.
  • item에 해당하는 항목을 가져온다.
  • defaultContentConfiguration()은 이미 정의되어 있는 시스템 스타일이다.
  • reminder의 title을 text로 정의한다.
  • diffable data source을 위한 typealliase를 추가한다.
    • typealliase로 기존 type을 더 잘 표현할 수 있다.
  • DataSouce를 implicitly unwrap하는 dataSource를 만든다.
    • 값을 가질 것을 알 때만 implicitly unwrapped opionals를 사용해야한다.
    • 그렇지 않으면, 런타임 에러와 함께... 앱이 종료될 것이다..
  • dataSource에 값을 할당한다.
  • cell을 dequeue하고 return한다.
    • 매번 새로운 cell을 만들 수 있지만, 초기화하느라 앱의 성능을 저하시킬 것이다.
    • cell을 재사용하면 많은 item을 사용하더라도 앱이 잘 수행할 것이다.

 

 Section 6. Apply a Snapshot 

Diffable data source는 snapshot으로 데이터 상태를 관리한다.

Snapshot은 특정 시점의 데이터 상태를 나타낸다. Snapshot을 이용해 데이터를 나타내려면, snapshot을 만들어 표시할 데이터의 상태로 snapshot을 채우고, UI에 snapshot을 적용한다.

typealias Snapshot = NSDiffableDataSourceSnapshot<Int, String>
var snapshot = Snapshot()
snapshot.appendSections([0])
snapshot.appendItems(Reminder.sampleData.map { $0.title })
dataSource.apply(snapshot)

collectionView.dataSource = dataSource
  • DiffableDataSourceSnapshot에 대한 typealias를 추가한다.
  • snapshot을 만들고, 단일 섹션을 추가한다.
  • reminder의 제목만 포함하는 새 배열을 만들어 snapshot 항목으로 추가한다.
  • snapshot을 dataSource에 적용한다.
  • collectionView에 dataSource를 지정한다.
  • 앱을 빌드한다!!


으음.. 여전히 snapshot은 잘 모르겠다! 조금 더 찾아봐야지

'📕 iOS > UIKit' 카테고리의 다른 글

[소소한 UIKit] UILabel에서 여러 줄 입력하기  (0) 2023.11.06
[UIKit] UIComponent  (0) 2023.03.21