1) BoxOfficeProject
1. Movie
라는 이름의 Model 파일 생성
Movie.swift
struct Movie {
let title: String
let releaseDate: String
let runtime: Int
let overview: String
let rate: Double
}
MovieInformation
이라는 이름의 data를 가진 파일 생성MovieInformation.swift
struct MovieInformation {
let movie: [Movie] = [
Movie(title: "암살", releaseDate: "2020.02.02", runtime: 139, overview: "줄거리줄거리", rate: 9),
Movie(title: "암살", releaseDate: "2020.02.02", runtime: 139, overview: "줄거리줄거리", rate: 9)
Movie(title: "암살", releaseDate: "2020.02.02", runtime: 139, overview: "줄거리줄거리", rate: 9)
]
}
let movieInformation = MovieInformation()
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return movieInformation.movie.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
// 타입 캐스팅
guard let cell = tableView.dequeueReusableCell(withIdentifier: BoxOfficeTableViewCell.identifier, for: indexPath) as? BoxOfficeTableViewCell else {
return UITableViewCell()
}
let row = movieInformation.movie[indexPath.row]
cell.posterImageView.image = UIImage(named: row.title)
cell.titleLabel.text = row.title
cell.releaseDateLabel.text = row.releaseDate
cell.overviewLabel.text = row.overview
cell.overviewLabel.numberOfLines = 0
return cell
}
// Keyword, 예약어 -> 변수로 인식이 안됨, 평소에는 사용을 지양하지만 ... // 이렇게 묶어주면 사용할 수 있음~! let `switch` = movieInformation.movie[indexPath.row]
2) MemoProject
1. 스토리보드에 Segmented Control 추가
2. Memo.swift
파일 생성 및 Struct 코드 작성
enum Category: Int {
case business = 0, perosnal, others
var description: String {
switch self {
case .business:
return "업무"
case .perosnal:
return "개인"
case .others:
return "기타"
}
}
}
struct Memo {
var content: String
var category: Category
}
var list: [Memo] = [] {
didSet {
saveData()
}
}
if let text = memoTextView.text {
// Textview에 text가 있는 경우에
let segmentIndex = categorySegmentedControl.selectedSegmentIndex
// segmented control에서 사용자가 마지막으로 터치한 index값을 int로 가져옴
let segmentCategory = Category(rawValue: segmentIndex)!
// 해당 int를 rawvalue로 가지고 있는 category 객체를 할당
let memo = Memo(content: text, category: segmentCategory)
// 받은 정보를 기반으로 Memo 인스턴스 생성
list.append(memo)
// list에 객체 추가
} else {
print("내용 입력해주세요.")
func saveData() {
// 구조체 배열은 바로 저장할 수 없음 ➡️ format 맞춰줘야함
var memo: [[String:Any]] = []
// [["content": "어쩌구", "category": 8], ["content": "어쩌구", "category": 8]] 이런 형태로 UserDefaults에 저장해줄 예정
// 우리가 생성한 struct로는 userdefaults에 저장할 수 없어서 기본 자료형을 이용해서 저장해줘야함
// 현재 list에 있는 Memo 객체를 하나씩 불러와서
// category값은 i.category.rawValue (카테고리도 커스텀열거형이기 때문에 rawValue로 저장해주기)
// memo라는 [[String: Any]]형식의 배열에 저장해줌
for i in list {
let data: [String: Any] = [
"category": i.category.rawValue,
"content": i.content
]
memo.append(data)
}
// for문을 모두 돌고난 후에는 UserDefaults에 해당 list를 저장해주고
let userDefaults = UserDefaults.standard
userDefaults.set(memo, forKey: "memoList")
// 새로운 항목이 추가되었기 때문에 이를 반영하기 위해서 tableView를 reload해준다.
tableView.reloadData()
}
func loadData() {
let userDefaults = UserDefaults.standard
// 만약에 값이 있고 타입 변환이 된다면
if let data = userDefaults.object(forKey: "memoList") as? [[String:Any]]{
// 먼저 구조체로 변환해줘야함
// 구조체 타입의 객체를 갖는 빈 리스트를 선언해주고
var memo = [Memo]()
// UserDefault에 저장해둔 데이터를 불러온 뒤 객체를 하나하나씩 본다.
for datum in data {
guard let category = datum["category"] as? Int else {
// alert 띄워주기도 함 사용자에게 알려주기 위해서
return}
guard let content = datum["content"] as? String else { return }
let enumCategory = Category(rawValue: category) ?? .others
// 받아온 데이터를 사용하여 Memo 객체를 생성하고 memo 리스트에 append하고
memo.append(Memo(content: content, category: enumCategory))
}
컨트롤러 내부의 data를 가진 리스트에 업데이트 시켜준다.
self.list = memo
}
}
let row = list[indexPath.row]
switch row.category {
case .business:
cell.imageView?.image = UIImage(systemName: "building.2")
case .perosnal:
cell.imageView?.image = UIImage(systemName: "person")
case .others:
cell.imageView?.image = UIImage(systemName: "square.and.pencil")
}
cell.imageView?.tintColor = .black
cell.textLabel?.text = row.content
cell.detailTextLabel?.text = row.category.description
cell.textLabel?.textColor = .blue
cell.textLabel?.font = .italicSystemFont(ofSize: 13)
UIViewController+Extension.swift
파일 생성extension UIViewController {
func setBackgroundColor() {
view.backgroundColor = .red
}
}
extension UIViewController {
func showAlert(t: String, msg: String, style: UIAllertController.Style) {
let alert = UIAlertController(title: t, message: msg, preferredStyle: style)
let ok = UIAlertAction(title: "확인", style: .default, handler: nil)
present(alert, animated: true, completion: nil)
}
}
extension UITextField {
func borderColor() {
self.layer.borderColor = UIColor.black.cgColor
}
}
override func viewDidLoad() {
super.viewDidLoad()
heightTextField.borderColor()
}
mutating
키워드를 작성해줘야한다.struct Point {
var x = 0.0
var y = 0.0
mutating func moveBy(x: Double, y: Double) {
self.x += x
self.y += y
}
}
var somePoint = Point()
somePoint.moveBy(x: 3.0, y: 5.0)
print("POINT: \(somePoint.x), \(somePoint.y)")
static
이라는 키워드를 사용한다.class User {
static let nickname = "고래밥"
static var totalOrderCount = 0 {
didSet {
print("총 주문횟수: \(oldValue) -> \(totalOrderCount)로 증가")
}
}
static var orderProduct: Int {
get {
return totalOrderCount
}
set {
totalOrderCount += newValue
}
}
}
User.nickname // 고래밥
User.totalOrderCount // 0
User.orderProduct // 0
// 사용되기 전에는 0을 가지고 있음
User.orderProduct = 10
// computed property에 값을 할당 ➡️ setter 동작 ➡️ totalOrder에 할당된 newValue 더하기
User.totalOrderCount // 10
User.orderProduct = 20
User.totalOrderCount // 30
static
으로 작성한 타입 메서드는 상속한 후 재정의가 불가능하다.class
를 작성해줘야한다.class Coffee {
static var name = "아메리카노"
static var shot = 2
static func plusShot() {
shot += 1
}
class func minusShot() {
shot -= 1
}
func hello() {
}
}
class Latte: Coffee {
override class func minusShot() {
print("타입 메서드를 상속받아 재정의 하고 싶을 경우, 부모 클래스에서 타입 메서드 선언할 때 static 아니라 class 사용하면 됨.")
}
}
Latte.minusShot()
class UserDefaultsHelper {
static let shared = UserDefaultsHelper()
let userDefaults = UserDefaults.standard
enum Key: String {
case nickname, age, rate
}
var userNickname: String? {
get {
return userDefaults.string(forKey: Key.nickname.rawValue)
}
set {
userDefaults.set(newValue, forKey: Key.nickname.rawValue)
}
}
var userAge: Int? {
get {
return userDefaults.integer(forKey: Key.age.rawValue)
}
set {
userDefaults.set(newValue, forKey: Key.age.rawValue)
}
}
// 접근제어자, 초기화 구문을 제한하는 구문
// 타입으로만 사용하도록 제한하고 싶은데 까먹고
// let user = UserDefaultsHelper()
// user.userNickname = "dfa"
// 다음과 같이 인스턴스를 만들어서 접근할 수도 있다.
// 하나만 만들어서 조절하고싶은 우리의 목적이 달성되지 못할 수 있기 때문에 인스턴스를 생성하지 못하도록 제한할 수 있음
private init() {
}
}
UserDefaultsHelper.shared.userNickname
// 처음에 실행하면 nil
UserDefaultsHelper.shared.userAge
// 0
UserDefaultsHelper.shared.userNickname = "고래밥"
UserDefaultsHelper.shared.userAge = 15
UserDefaultsHelper.shared.userNickname // 고래밥
UserDefaultsHelper.shared.userAge // 15
override func viewDidLoad() {
super.viewDidLoad()
memoTableView.rowHeight = UITableView.automaticDimension
}
안드로이드 탭바
라고 부른다.