[Review] (4주차) 실습
2022.07.10 - [Dev/Swift] - [Xcode] iOS Swift 앱 개발 Byte Degree - week.04
[Xcode] iOS Swift 앱 개발 Byte Degree - week.04
[Review] (3주차) 실습 2022.07.01 - [Swift] - [Xcode] iOS Swift 앱 개발 Byte Degree - week.03 [Xcode] iOS Swift 앱 개발 Byte Degree - week.03 [Review] (2주차) 실습 2022.06.26 - [Swift] - [Xcode] iOS..
sarahee.tistory.com
애플 프레임워크 모달 - 상세뷰로 진입하거나, 새로운 뷰 띄워보기
// 위임 self
override func viewOldLoad() {
collectionView.delegate = self
}
extension FrameworkListViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let framework = list[indexPath.item]
print(">>> selected: \(framework.name)")
// FrameworkDetailViewController 띄우고자 함
let storyboard = UIStoryboard(name: "Detail", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "FrameworkDetailViewController")
as! FrameworkDetailViewController
vc.framework = framework
present(vc, animated: true)
}
}
멀티라인으로 설정하기 위해서는..
Label의 Lines: 1 → 0
Combine Overview
주요 컴포넌트 3가지
Publisher: 생산자, 크리에이터
Subscriber: 소비자, 구독자
Operator: 변경시키는 사람, 가공하는 사람
-
실습
Class: QuickFocusListViewController, Subclass of: UIViewController 추가
Class: QuickFocusCell, Subclass of: UICollectionViewCell 추가
//
// QuickFocusListViewController.swift
// HeadSpaceFocus
//
// Created by sehee on 2022/07/21.
//
import UIKit
class QuickFocusListViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
let breathingList = QuickFocus.breathing
let walkingList = QuickFocus.walking
enum Section: CaseIterable {
case breathe
case walking
var title: String {
switch self {
case .breathe: return "Breathing exercises"
case .walking: return "Mindful walks"
}
}
}
typealias Item = QuickFocus
var datasource: UICollectionViewDiffableDataSource<Section, Item>!
override func viewDidLoad() {
super.viewDidLoad()
// enum Section CaseIterable 생성한 코드가 다음 내용과 동일
// Section.allCases
// let allItems: [Section] = [.breathe, .walking]
// 생성 코드가 다음과 같이 쓰일 수 있음
// let section: Section = .breathe
// section.title
// Presentation
datasource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView, cellProvider: { collectionView, indexPath, item in
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "QuickFocusCell", for: indexPath) as? QuickFocusCell else {
return nil
}
cell.configure(item)
return cell
})
// Data
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.breathe, .walking])
// 위의 코드와 동일
// snapshot.appendSections(Section.allCases)
snapshot.appendItems(breathingList, toSection: .breathe)
snapshot.appendItems(walkingList, toSection: .walking)
datasource.apply(snapshot)
// Layout
collectionView.collectionViewLayout = layout()
}
private func layout() -> UICollectionViewCompositionalLayout {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .estimated(50))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(50))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 2)
let section = NSCollectionLayoutSection(group: group)
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}
}
코드를 연결하기 위해, FocusViewController의 Layout에 다음 코드 추가
collectionView.delegate = self
하단 코드 연결
extension FocusViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let item = items[indexPath.item]
print(">>> \(item.title)")
let storyboard = UIStoryboard(name: "QuickFocus", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "QuickFocusListViewController") as! QuickFocusListViewController
present(vc, animated: true)
}
}
좌우 padding
1) section.contentInsets
2) section.interGroupSpacing, group.interItemSpacing
private func layout() -> UICollectionViewCompositionalLayout {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .estimated(50))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(50))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 2)
group.interItemSpacing = .fixed(10)
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(top: 30, leading: 20, bottom: 30, trailing: 20)
section.interGroupSpacing = 20
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}
헤더 추가
+ > Collection Reusable View
해당 View의 custom class 생성 - Class: QuickFocusListHeaderView, Subclass of: UICollectionReusableView 추가
//
// QuickFocusHeaderView.swift
// HeadSpaceFocus
//
// Created by sehee on 2022/07/22.
//
import UIKit
class QuickFocusHeaderView: UICollectionReusableView {
@IBOutlet weak var titleLabel: UILabel!
func configure(_ title: String) {
titleLabel.text = title
}
}
QuickFocusListViewController 코드 삽입
datasource.supplementaryViewProvider = { (collectionView, kind, indexPath) in
guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "QuickFocusHeaderView", for: indexPath) as? QuickFocusHeaderView else {
return nil
}
let allSections = Section.allCases
let section = allSections[indexPath.section]
header.configure(section.title)
return header
}
QuickFocusListViewController 하단 UICollectionViewCompositionalLayout
let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(50))
let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)
section.boundarySupplementaryItems = [header]
Focus View Controller UI 클릭 후, Editor > Embed in > Navigation Controller
FocusViewController의 UICollectionViewDelegate
// 기존
present(vc, animated: true)
// 변경: Navigation - Back
navigationController?.pushViewController(vc, animated: true)
Navigation Bar의 ☑ Prefers Large Titles, Title 이름은 Focus로 설정
FocusViewController의 UICollectionViewDelegate 코드 추가
vc.title = item.title
QuickFocusListViewController의 Layout 코드 추가
self.navigationItem.largeTitleDisplayMode = .never
Navigation Bar의 Tint color: Default에서 White Color로 변경
최종 코드
//
// QuickFocusListViewController.swift
// HeadSpaceFocus
//
// Created by sehee on 2022/07/21.
//
import UIKit
class QuickFocusListViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
let breathingList = QuickFocus.breathing
let walkingList = QuickFocus.walking
enum Section: CaseIterable {
case breathe
case walking
var title: String {
switch self {
case .breathe: return "Breathing exercises"
case .walking: return "Mindful walks"
}
}
}
typealias Item = QuickFocus
var datasource: UICollectionViewDiffableDataSource<Section, Item>!
override func viewDidLoad() {
super.viewDidLoad()
// enum Section CaseIterable 생성한 코드가 다음 내용과 동일
// Section.allCases
// let allItems: [Section] = [.breathe, .walking]
// 생성 코드가 다음과 같이 쓰일 수 있음
// let section: Section = .breathe
// section.title
// Presentation
datasource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView, cellProvider: { collectionView, indexPath, item in
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "QuickFocusCell", for: indexPath) as? QuickFocusCell else {
return nil
}
cell.configure(item)
return cell
})
datasource.supplementaryViewProvider = { (collectionView, kind, indexPath) in
guard let header = collectionView.dequeueReusableSupplementaryView(ofKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "QuickFocusHeaderView", for: indexPath) as? QuickFocusHeaderView else {
return nil
}
let allSections = Section.allCases
let section = allSections[indexPath.section]
header.configure(section.title)
return header
}
// Data
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.breathe, .walking])
// 위의 코드와 동일
// snapshot.appendSections(Section.allCases)
snapshot.appendItems(breathingList, toSection: .breathe)
snapshot.appendItems(walkingList, toSection: .walking)
datasource.apply(snapshot)
// Layout
collectionView.collectionViewLayout = layout()
self.navigationItem.largeTitleDisplayMode = .never
}
private func layout() -> UICollectionViewCompositionalLayout {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.5), heightDimension: .estimated(50))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(50))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitem: item, count: 2)
group.interItemSpacing = .fixed(10)
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(top: 30, leading: 20, bottom: 30, trailing: 20)
section.interGroupSpacing = 20
let headerSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .absolute(50))
let header = NSCollectionLayoutBoundarySupplementaryItem(layoutSize: headerSize, elementKind: UICollectionView.elementKindSectionHeader, alignment: .top)
section.boundarySupplementaryItems = [header]
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}
}
//
// QuickFocusCell.swift
// HeadSpaceFocus
//
// Created by sehee on 2022/07/21.
//
import UIKit
class QuickFocusCell: UICollectionViewCell {
@IBOutlet weak var thumbnailImageView: UIImageView!
@IBOutlet weak var titleLabel: UILabel!
@IBOutlet weak var descriptionLabel: UILabel!
func configure(_ quickFocus: QuickFocus) {
thumbnailImageView.image = UIImage(named: quickFocus.imageName)
titleLabel.text = quickFocus.title
descriptionLabel.text = quickFocus.description
}
}
//
// FocusViewController.swift
// HeadSpaceFocus
//
// Created by sehee on 2022/07/10.
//
import UIKit
class FocusViewController: UIViewController {
@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var refreshButton: UIButton!
var curated: Bool = false
var items: [Focus] = Focus.list
typealias Item = Focus
enum Section {
case main
}
var datasource: UICollectionViewDiffableDataSource<Section, Item>!
override func viewDidLoad() {
super.viewDidLoad()
refreshButton.layer.cornerRadius = 10
// Presentation: Diffable Datasource + Cell Provider
datasource = UICollectionViewDiffableDataSource<Section, Item>(collectionView: collectionView, cellProvider: { collectionView, indexPath, item in
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "FocusCell", for: indexPath) as? FocusCell else {
return nil
}
cell.configure(item)
return cell
})
// Data: Snapshot
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.main])
snapshot.appendItems(items, toSection: .main)
datasource.apply(snapshot)
// Layout
collectionView.collectionViewLayout = layout()
collectionView.delegate = self
updateButtonTitle()
}
private func layout() -> UICollectionViewCompositionalLayout {
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(50))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .estimated(50))
let group = NSCollectionLayoutGroup.vertical(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.contentInsets = NSDirectionalEdgeInsets(top: 10, leading: 20, bottom: 10, trailing: 20)
section.interGroupSpacing = 10
let layout = UICollectionViewCompositionalLayout(section: section)
return layout
}
func updateButtonTitle() {
let title = curated ? "See All" : "See Recommendation"
refreshButton.setTitle(title, for: .normal)
}
@IBAction func refreshButtonTapped(_ sender: Any) {
curated.toggle()
self.items = curated ? Focus.recommendations : Focus.list
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
snapshot.appendSections([.main])
snapshot.appendItems(items, toSection: .main)
datasource.apply(snapshot)
updateButtonTitle()
}
}
extension FocusViewController: UICollectionViewDelegate {
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let item = items[indexPath.item]
print(">>> \(item.title)")
let storyboard = UIStoryboard(name: "QuickFocus", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "QuickFocusListViewController") as! QuickFocusListViewController
vc.title = item.title
// present(vc, animated: true)
navigationController?.pushViewController(vc, animated: true)
}
}
[Next] (6주차) 실습
2022.07.22 - [Development/Swift] - [Swift] iOS 앱 개발(Xcode) Byte Degree - week.06
[Swift] iOS 앱 개발(Xcode) Byte Degree - week.06
[Review] (5주차) 실습 2022.07.16 - [Dev/Swift] - [Xcode] iOS Swift 앱 개발 Byte Degree - week.05 [Xcode] iOS Swift 앱 개발 Byte Degree - week.05 [Review] (4주차) 실습 2022.07.10 - [Dev/Swift] - [Xco..
sarahee.tistory.com
'Development > Swift' 카테고리의 다른 글
[Swift] iOS 앱 개발(Xcode) Byte Degree - week.07 (0) | 2022.08.25 |
---|---|
[Swift] iOS 앱 개발(Xcode) Byte Degree - week.06 (0) | 2022.07.22 |
[Swift] iOS 앱 개발(Xcode) Byte Degree - week.04 (0) | 2022.07.10 |
[Swift] iOS 앱 개발(Xcode) Byte Degree - week.03 (0) | 2022.07.01 |
[Swift] iOS 앱 개발(Xcode) Byte Degree - week.02 (0) | 2022.06.26 |