[Review] (2주차) 실습
2022.06.26 - [Swift] - [Xcode] iOS Swift 앱 개발 Byte Degree - week.02
[Xcode] iOS Swift 앱 개발 Byte Degree - week.02
iOS 아키텍처 패턴 중 애플에서는 기본적으로 MVC 패턴을 가이드함 Product Name: HelloiOS Organization Identifier: com.sehee Interface: Storyboard (other options: SwiftUI) Language: Swift (other option..
sarahee.tistory.com
Intro
Swift의 기본 기능, 리스트 및 그리드에 대해 알아보자
Xcode 실행시 기본 스토리보드
File > New > File (or command + n )
view controller 추가하기
Cocoa Touch Class > (Choose options for your new file) Class: StockRankViewController > Next > Create
좌측 Main Tab의 View Controller > 우측 Custom Class - Class 및 Identity - Storyboard ID: StockRankViewController 설정
* Storyboard ID에서 검색이 용이하도록(class 이름 자체가 unique한 id이므로 동일하게 설정해도 무방)
Main storyboard에서 우측 상단 + 버튼 클릭하여 UI components(objects) 선택
Collection View 추가
Auto rayout 설정
자식 뷰(Collection View)를 부모 뷰(View)에 연관되게 설정하기 위함
control 버튼을 누른 상태에서 Collection View → Vie w 드래그
Shift를 누른 상태에서 클릭하여 다중 선택(상단 네개 Space to Safe Area 모두 클릭) 이후 Enter
View를 Code로 연결하기
해당하는 스토리보드(Collection View) 클릭 후 우측 상단 =(리스트) 아이콘 클릭
Assistant 클릭하여 새로운 view 생성
control 누른 상태에서 연결하고 싶은 뷰(Collection View) → 코드 드래그
name: collectionView > connect
import UIKit
class StockRankViewController : UIViewController {
@IBOutlet weak var collectionView: UICollectionView !
override func viewDidLoad () {
super .viewDidLoad()
}
}
Connection View Cell 내에 Label, Image View 추가 (option 누르고 드래그할 경우 복제)
Image View는 우측 Image View > Image에서 검색하여 변경 (e.g. heart.fill)
적용: option + command + =
import UIKit
class StockRankViewController : UIViewController {
let stockList: [StockModel ] = StockModel .list
@IBOutlet weak var collectionView: UICollectionView !
override func viewDidLoad () {
super .viewDidLoad()
collectionView.dataSource = self
collectionView.delegate = self
}
}
extension StockRankViewController : UICollectionViewDataSource {
func collectionView (_ collectionView : UICollectionView , numberOfItemsInSection section : Int ) -> Int {
return stockList.count
}
func collectionView (_ collectionView : UICollectionView , cellForItemAt indexPath : IndexPath ) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "StockRankCollectionViewCell" , for: indexPath)
return cell
}
}
extension StockRankViewController : UICollectionViewDelegateFlowLayout {
}
}
extension StockRankViewController : UICollectionViewDelegateFlowLayout {
func collectionView (_ collectionView : UICollectionView , layout collectionViewLayout : UICollectionViewLayout , sizeForItemAt indexPath : IndexPath ) -> CGSize {
return CGSize (width: collectionView.bounds.width, height: 80 )
}
}
StockRankCollectionViewCell code - data update
import UIKit
class StockRankCollectionViewCell : UICollectionViewCell {
@IBOutlet weak var rankLabel: UILabel !
@IBOutlet weak var companyIconImageView: UIImageView !
@IBOutlet weak var companyNameLabel: UILabel !
@IBOutlet weak var companyPriceLabel: UILabel !
@IBOutlet weak var diffLabel: UILabel !
func configure (_ stock : StockModel ) {
rankLabel.text = "\(stock.rank) "
companyIconImageView.image = UIImage (named: stock.imageName)
companyNameLabel.text = stock.name
companyPriceLabel.text = "\(stock.price) 원"
diffLabel.text = "\(stock.diff) %"
}
}
StockRankViewController code - data update
import UIKit
class StockRankViewController : UIViewController {
let stockList: [StockModel ] = StockModel .list
@IBOutlet weak var collectionView: UICollectionView !
override func viewDidLoad () {
super .viewDidLoad()
collectionView.dataSource = self
collectionView.delegate = self
}
}
extension StockRankViewController : UICollectionViewDataSource {
func collectionView (_ collectionView : UICollectionView , numberOfItemsInSection section : Int ) -> Int {
return stockList.count
}
func collectionView (_ collectionView : UICollectionView , cellForItemAt indexPath : IndexPath ) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "StockRankCollectionViewCell" , for: indexPath) as? StockRankCollectionViewCell else {
return UICollectionViewCell ()
}
let stock = stockList[indexPath.item]
cell.configure(stock)
return cell
}
}
extension StockRankViewController : UICollectionViewDelegateFlowLayout {
func collectionView (_ collectionView : UICollectionView , layout collectionViewLayout : UICollectionViewLayout , sizeForItemAt indexPath : IndexPath ) -> CGSize {
return CGSize (width: collectionView.bounds.width, height: 80 )
}
}
가격 표현(쉼표 추가)
import UIKit
class StockRankCollectionViewCell : UICollectionViewCell {
@IBOutlet weak var rankLabel: UILabel !
@IBOutlet weak var companyIconImageView: UIImageView !
@IBOutlet weak var companyNameLabel: UILabel !
@IBOutlet weak var companyPriceLabel: UILabel !
@IBOutlet weak var diffLabel: UILabel !
func configure (_ stock : StockModel ) {
rankLabel.text = "\(stock.rank) "
companyIconImageView.image = UIImage (named: stock.imageName)
companyNameLabel.text = stock.name
companyPriceLabel.text = "\(convertToCurrencyFormat(price: stock.price)) 원"
diffLabel.text = "\(stock.diff) %"
}
func convertToCurrencyFormat (price : Int ) -> String {
let numberFormatter = NumberFormatter ()
numberFormatter.numberStyle = .decimal
numberFormatter.maximumFractionDigits = 0
let result = numberFormatter.string(from: NSNumber (value: price)) ?? ""
return result
}
}
(추가) 사용자 UI 반영 - 마이너스일 때 파란색 표시, 플러스일 때는 기본 빨간색 표시
# sol1
var color: UIColor
if stock.diff > 0 {
color = UIColor .systemRed
} else {
color = UIColor .systemBlue
}
diffLabel.textColor = color
# sol2
diffLabel.textColor = stock.diff > 0 ? UIColor .systemRed : UIColor .systemBlue
최종 코드
import UIKit
class StockRankViewController : UIViewController {
let stockList: [StockModel ] = StockModel .list
@IBOutlet weak var collectionView: UICollectionView !
override func viewDidLoad () {
super .viewDidLoad()
collectionView.dataSource = self
collectionView.delegate = self
}
}
extension StockRankViewController : UICollectionViewDataSource {
func collectionView (_ collectionView : UICollectionView , numberOfItemsInSection section : Int ) -> Int {
return stockList.count
}
func collectionView (_ collectionView : UICollectionView , cellForItemAt indexPath : IndexPath ) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "StockRankCollectionViewCell" , for: indexPath) as? StockRankCollectionViewCell else {
return UICollectionViewCell ()
}
let stock = stockList[indexPath.item]
cell.configure(stock)
return cell
}
}
extension StockRankViewController : UICollectionViewDelegateFlowLayout {
func collectionView (_ collectionView : UICollectionView , layout collectionViewLayout : UICollectionViewLayout , sizeForItemAt indexPath : IndexPath ) -> CGSize {
return CGSize (width: collectionView.bounds.width, height: 80 )
}
}
import UIKit
class StockRankCollectionViewCell : UICollectionViewCell {
@IBOutlet weak var rankLabel: UILabel !
@IBOutlet weak var companyIconImageView: UIImageView !
@IBOutlet weak var companyNameLabel: UILabel !
@IBOutlet weak var companyPriceLabel: UILabel !
@IBOutlet weak var diffLabel: UILabel !
func configure (_ stock : StockModel ) {
rankLabel.text = "\(stock.rank) "
companyIconImageView.image = UIImage (named: stock.imageName)
companyNameLabel.text = stock.name
companyPriceLabel.text = "\(convertToCurrencyFormat(price: stock.price)) 원"
diffLabel.textColor = stock.diff > 0 ? UIColor .systemRed : UIColor .systemBlue
diffLabel.text = "\(stock.diff) %"
}
func convertToCurrencyFormat (price : Int ) -> String {
let numberFormatter = NumberFormatter ()
numberFormatter.numberStyle = .decimal
numberFormatter.maximumFractionDigits = 0
let result = numberFormatter.string(from: NSNumber (value: price)) ?? ""
return result
}
}
기본 제공 코드
import Foundation
struct StockModel {
let rank: Int
let imageName: String
let name: String
let price: Int
let diff: Double
}
extension StockModel {
static let list: [StockModel ] = [
StockModel (rank: 1 , imageName: "TSLA" , name: "테슬라" , price: 1_238_631 , diff: 0.04 ),
StockModel (rank: 2 , imageName: "AAPL" , name: "애플" , price: 238_631 , diff: 1.04 ),
StockModel (rank: 3 , imageName: "NFLX" , name: "넷플릭스" , price: 438_631 , diff: - 0.04 ),
StockModel (rank: 4 , imageName: "GOOG" , name: "알파벳 A" , price: 3_176_631 , diff: 0.04 ),
StockModel (rank: 5 , imageName: "AMZN" , name: "아마존" , price: 3_538_631 , diff: 0.04 ),
StockModel (rank: 6 , imageName: "NIKE" , name: "나이키" , price: 158_631 , diff: 0.04 ),
StockModel (rank: 7 , imageName: "DIS" , name: "디즈니" , price: 138_631 , diff: 0.04 ),
StockModel (rank: 8 , imageName: "TSLA" , name: "테슬라" , price: 1_238_631 , diff: 0.04 ),
StockModel (rank: 9 , imageName: "AAPL" , name: "애플" , price: 238_631 , diff: 1.04 ),
StockModel (rank: 10 , imageName: "NFLX" , name: "넷플릭스" , price: 438_631 , diff: - 0.04 ),
StockModel (rank: 11 , imageName: "GOOG" , name: "알파벳 A" , price: 3_176_631 , diff: 0.04 ),
StockModel (rank: 12 , imageName: "AMZN" , name: "아마존" , price: 3_538_631 , diff: 0.04 ),
StockModel (rank: 13 , imageName: "NIKE" , name: "나이키" , price: 158_631 , diff: 0.04 ),
StockModel (rank: 14 , imageName: "DIS" , name: "디즈니" , price: 138_631 , diff: 0.04 ),
]
}
[Next] (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