어떤 클래스 타입의 변수 또는 상수가 정말로 해당 클래스의 인스턴스를 참조하지 않을 수도 있습니다. 예를 들어 Latte 클래스의 인스턴스가 Coffee 클래스의 인스턴스인양 Coffee 행세를 할 수 있습니다.
라떼 타입의 인스턴스를 참조하는 커피?
라떼는 아니지만 라떼의 프로퍼티 또는 메서드를 가져와서 써야지 다방커피를 만들 수 있다.
캐스팅? 거기에 있는 프로퍼티를 가져다 사용할 수 있게 하기 위함
타입캐스팅은 실제로 인스턴스를 수정하거나 값을 변경하는 작업이 아닙니다.
인스턴스는 메모리에 똑같이 남아있을 뿐 입니다.
다만 인스턴스를 사용할 때 어떤 타입으로 다루고 어떤 타입으로 접근해야 할지 판단할 수 있도록 컴퓨터에 힌트를 주는 것 뿐입니다.
다운 캐스팅을 할 때는 타입캐스트 연산자 as?, as!를 사용
관계가 없는 상태인데 다운 캐스팅을 할수도 있음
as? 보통은 이렇게 씀
as! 부모, 자식 관계가 확실할 때는 이거 사용
cell은 uITableviewcell인데
OpenMarketTableViewCell 자식인 척 하는 부모 클래스
객체지향
다형성 ⭐️⭐️⭐️
커피머신 클래스 만듦
외부에서 객체를 받아서 뭐하고 싶음
import UIKit
class Coffee {
let name: String
let shot: Int
let price: Int
var description: String {
return "\(name) \(shot)샷 나왔습니다. \(price)원 입니다."
}
init(name: String, shot: Int, price: Int) {
self.name = "cofee"
self.shot = shot
self.price = price
}
}
class Americano: Coffee {
var 원두타입: String
override var description: String {
return "\(원두타입) 아메리카노 \(shot)샷 나왔습니다. \(price)원 입니다."
}
init(원두타입: String, shot: Int, price: Int) {
self.원두타입 = 원두타입
super.init(name: "아메리카노", shot: shot, price: price)
}
}
class Latte: Coffee {
var 우유: String
var 설탕: String
override var description: String {
return "\(설탕) 라떼 \(shot)샷 나왔습니다. \(price)원 입니다."
}
init(우유: String, 설탕: String, shot: Int, price: Int) {
self.우유 = 우유
self.설탕 = 설탕
super.init(name: "라떼", shot: shot, price: price)
}
}
// 어떤 클래스타입의 변수 또는 상수가 정말로 해당 클래스의 인스턴스를 참조하지 않을 수도 있습니다. 예를들어 Latte 클래스의 인스턴스가 Coffee 클래스의 인스턴스인양 Coffee 행세를 할 수 있습니다.
// 라떼는 아니지만 라떼 행세를하면 라떼의 프로퍼티 또는 메서드를 가져와서 사용할 수 있습니다.
// 타입캐스팅은 실제로 인스턴스를 수정하거나 값을 변경하는 작업이 아닙니다. 인스턴스는 메모리에 똑같이 남아있을 뿐 입니다 다만 인스턴스를 사용할 때 어떤 타입으로 다루고 어떤 타입으로 접근해야 할지 판단할 수 있도록 컴퓨터에 힌트를 주는 것뿐 입니다. [출처]: 야곰책
let 다방커피: Coffee = Latte(우유: "메일우유", 설탕: "백설탕", shot: 2, price: 3000)
// 다운 캐스팅을 할 때는 타입캐스트 연산자 as?, as!를 사용해요
let 찐커피 = Coffee(name: "맛 없는 커피", shot: 1, price: 800)
if let 라떼행세를하는그냥커피: Latte = 찐커피 as? Latte {
라떼행세를하는그냥커피.설탕
라떼행세를하는그냥커피.우유
}
if let 아메리카노행세를하는그냥커피: Americano = 찐커피 as? Americano {
아메리카노행세를하는그냥커피.원두타입
}
struct 커피머신 {
var coffee: Coffee
}
// 스타벅스에는 메뉴가 6개인데 각 각 메뉴의 메서드를 만들지 않고 Coffee라는 타입을 통해 여러커피를 만들 수 있다. 다형성의 매직
let 써니의커피머신 = 커피머신(coffee: Latte(우유: "오늘우유", 설탕: "서얼탕", shot: 3, price: 555555))
프로젝트 코드에서 다운 캐스팅을 하는 이유
cell.itemName.text 이런 식으로 적용을 하려면
따로 만든 커스텀 클래스인 OpenMarketTableViewCell을 적용해야 함
(만국박람회에서는 커스텀 셀을 안쓰고
그냥 기본 셀에다가
cell.textLabel?.text = item.koreanTitle 이런 식으로 바로 적용해줬음)
원래 자식 클래스는 부모 클래스의 프로퍼티, 메서드를 가져다 쓰는게 됨
역으로 부모 클래스에서는 그게 안됨
UITableViewCell에서 cell.itemName.text 이런 식으로
자식 클래스 OpenMarketTableViewCell의 속성을 적용해주기 위해서
다운 캐스팅을 적용함!
guard let cell: OpenMarketTableViewCell = tableView.dequeueReusableCell(withIdentifier: "OpenMarketTableViewCell") as? OpenMarketTableViewCell else { return UITableViewCell() }
cell.itemName.text = "MacBook Pro"
cell.itemPrice.text = "1800000"
return cell
class OpenMarketTableViewCell: UITableViewCell {
@IBOutlet weak var itemThumbnail: UIImageView!
@IBOutlet weak var itemName: UILabel!
@IBOutlet weak var itemPrice: UILabel!
@IBOutlet weak var itemDiscountedPrice: UILabel!
@IBOutlet weak var quantity: UILabel!
}
iOS 13-10 Swift 강좌 : 세그먼트 콘트롤(segmented control)사용법
Swift Tutorial: Container View Controllers for Beginners (Swift 5, Xcode 11, iOS)
로딩바 해줘야 하는데
외부라이브러리 쓰면 안됨
그럼 어떻게?
원래 있는거 가져다 쓰기!
lazy var activityIndicator: UIActivityIndicatorView = {
let activityIndicator = UIActivityIndicatorView()
activityIndicator.frame = CGRect(x: 0, y: 0, width: 50, height: 50)
activityIndicator.color = .gray
activityIndicator.center = self.view.center
activityIndicator.hidesWhenStopped = true
activityIndicator.stopAnimating()
return activityIndicator
}()
잔여 수량 옆에 화살표 > 액세서리 뷰에 해줘야함!
How? Main.storyboard → (테이블 뷰 안의) cell 선택 → Accessory → Disclosure indicator 선택
실행해보면 셀마다 오른쪽에 꺽쇠 기호가 생긴 걸 확인할 수 있음
Q. 셀의 상하폭이 너무 길다
스토리보드에서 UIImageView를 선택하고 Constraints 들어가서 높이 대략 50으로 설정했더니 해결됨!!