๋ณธ๋ฌธ ๋ฐ”๋กœ๊ฐ€๊ธฐ

๐Ÿงฏ Troubleshooting

[Cheliz] View ๊ด€๋ จ ์žฌ์‚ฌ์šฉ์„ฑ ๋†’์ด๊ธฐ

 

์šฐ์„  ๊ตฌํ˜„ํ•œ ๋ฐฑ์—… ๋ฐ ๋ณต๊ตฌ ํ™”๋ฉด์€ ์•„๋ž˜์™€ ๊ฐ™๋‹ค!

 

(์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ๋ฅผ ์ž๊พธ ๋Œ๋ฆฌ๋‹ค ๋ณด๋‹ˆ ์•Œ๊ฒŒ ๋œ ์‚ฌ์‹ค ํ•œ ๊ฐ€์ง€.. iOS 16 ๋ฏธ๋งŒ์˜ ์‹œ๋ฎฌ๋ ˆ์ดํ„ฐ์—์„œ๋Š” home indicator์˜ ์˜ค๋ฅธ์ชฝ ๋ถ€๋ถ„์ด ํ๋ฆฌ๋‹ค….๊ฑฐ์Šฌ๋ฆผ)

 

 

์œ„ ํ™”๋ฉด์„ ์˜ˆ์‹œ๋กœ, View์™€ ๊ด€๋ จํ•˜์—ฌ ์ฝ”๋“œ์˜ ์žฌ์‚ฌ์šฉ์„ฑ์„ ๋†’์ด๊ธฐ ์œ„ํ•ด ๊ณ ๋ฏผํ•˜๊ณ  ๊ตฌํ˜„ํ–ˆ๋˜ ์ง€์ ๋“ค ์ค‘ ๋‘ ๊ฐ€์ง€๋ฅผ ์ ์–ด ๋ณด๋ ค ํ•œ๋‹ค..!

 

 

 

 

  Custom View with Parameters  

์œ„ ํ™”๋ฉด์— ๋ณด์ด๋Š” ๊ฒƒ๊ณผ ๊ฐ™์ด ๋ฐฑ์—…ํ•˜๊ธฐ ๋ฒ„ํŠผ๊ณผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋ฒ„ํŠผ์˜ ๋””์ž์ธ์ด ๋™์ผํ•˜๋ฏ€๋กœ,
์ปค์Šคํ…€ ๋ฒ„ํŠผ BackupAndRestoreButton์„ ๋งŒ๋“ค๊ณ 
๋ฐฑ์—…ํ•˜๊ธฐ ๋ฒ„ํŠผ๊ณผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋ฒ„ํŠผ์„ ๊ฐ๊ฐ ์ด BackupAndRestoreButton์˜ ์ธ์Šคํ„ด์Šค๋กœ ์ƒ์„ฑํ•˜์˜€๋‹ค.

 

 

class BackupAndRestoreButton: UIButton {
    // MARK: - Properties
    var title: String?

    // MARK: - Initializers
    init(title: String) {
        self.title = title
        super.init(frame: .zero)

	setUI()
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

 

setUI() ๋ฉ”์„œ๋“œ๊ฐ€ ๊ธธ์–ด ์œ„ ์ฝ”๋“œ์—์„œ๋Š” ์ƒ๋žตํ–ˆ์ง€๋งŒ,
๊ณตํ†ต๋˜๋Š” ๋ถ€๋ถ„(์—ฌ๊ธฐ์„œ๋Š” ๋””์ž์ธ)์„ ํ•˜๋‚˜์˜ ํด๋ž˜์Šค ๋‚ด์— ๊ตฌํ˜„ํ•˜๊ณ , ์ธ์Šคํ„ด์Šค๋ฅผ ๋งŒ๋“ค ๋•Œ๋งˆ๋‹ค ๋‹ฌ๋ผ์ง€๋Š” ๋ถ€๋ถ„(์—ฌ๊ธฐ์„œ๋Š” ๋ฒ„ํŠผ์˜ ํƒ€์ดํ‹€)์„ ๋”ฐ๋กœ ๊ตฌํ˜„ํ•  ์ˆ˜ ์žˆ๋„๋ก ๋ฏธ๋ฆฌ ์„ค์ •ํ•ด ๋‘์—ˆ๋‹ค๊ณ  ์ƒ๊ฐํ•˜๋ฉด ๋œ๋‹ค!

 

 

 

๋‚˜๋Š” setUI()์— ๊ณตํ†ต ๊ตฌํ˜„๋ถ€๋ฅผ ์ž‘์„ฑํ–ˆ๊ณ , initializer์˜ ํŒŒ๋ผ๋ฏธํ„ฐ๋กœ ๋ฐ›์•„์˜จ ๋ฒ„ํŠผ ํƒ€์ดํ‹€๋„ setUI()์—์„œ ์ฒ˜๋ฆฌ๋  ์ˆ˜ ์žˆ๋„๋ก ํ–ˆ๋‹ค. ๋ฒ„ํŠผ ๋””์ž์ธ์„ ๋ฉ”์„œ๋“œ ๋‚ด ์„ ์–ธ๋œ UIButton.Configuration ์ธ์Šคํ„ด์Šค๋ฅผ ์‚ฌ์šฉํ•ด์„œ ๊ตฌํ˜„ํ–ˆ๊ธฐ ๋•Œ๋ฌธ์—, title ๋˜ํ•œ ๊ฐ™์€ ์ธ์Šคํ„ด์Šค๋ฅผ ํ†ตํ•ด ๋‚˜ํƒ€๋‚ผ ์ˆ˜ ์žˆ๋„๋ก ํ•˜๊ธฐ ์œ„ํ•จ์ด๋‹ค! (์•„๋ž˜ ‘UIButton.Configuration์„ ์‚ฌ์šฉํ•˜๋Š” UIButton์˜ ํƒ€์ดํ‹€์— ํฐํŠธ ์ ์šฉํ•˜๊ธฐ’ ์ฐธ๊ณ )

 

 

 

// BackupAndRestoreView.swift

let backupButton = BackupAndRestoreButton(title: Notice.backup)
let importBackupFileButton = BackupAndRestoreButton(title: Notice.bring)

์œ„์ฒ˜๋Ÿผ ์ปค์Šคํ…€ Button ํด๋ž˜์Šค๋ฅผ ์ƒ์„ฑํ•˜๋ฉด, ํ•ด๋‹น ํด๋ž˜์Šค์˜ ์ธ์Šคํ„ด์Šค๋ฅผ ์ƒ์„ฑํ•  ๋•Œ๋งˆ๋‹ค ํƒ€์ดํ‹€๋งŒ ์ง€์ •ํ•˜๋ฉด

 

 

 

์ด๋ ‡๊ฒŒ ๊ฐ™์€ ๋””์ž์ธ์˜ ๋ฒ„ํŠผ ์—ฌ๋Ÿฌ ๊ฐœ๋ฅผ ์ˆœ์‹๊ฐ„์— ๋š๋”ฑ..! ๋งŒ๋“ค์–ด ๋‚ผ ์ˆ˜ ์žˆ๋‹ค!

์ง€๊ธˆ์€ 2 ๊ฐœ ๋ฟ์ด์ง€๋งŒ, ๊ฐ์ฒด ์ˆ˜๊ฐ€ ๋” ๋งŽ์ด ํ•„์š”ํ• ์ˆ˜๋ก ์ด๋Ÿฌํ•œ ์ปค์Šคํ…€ UI ํด๋ž˜์Šค์˜ ํ•„์š”์„ฑ๊ณผ ์žฅ์ ์„ ๋” ๋งŽ์ด ์ฒด๊ฐํ•  ์ˆ˜ ์žˆ์„ ๊ฒƒ ๊ฐ™๋‹ค.
๋‚œ 2 ๊ฐœ๋งŒ์œผ๋กœ๋„ ๋งŽ์ด ์ฒด๊ฐํ–ˆ๋Š”๋ฐ, ์ด ๋•Œ ๊ตฌํ˜„ํ•œ ๊ณตํ†ต๋ถ€๋Š” ์•„๋ž˜ ๊ธ€์—์„œ ํ™•์ธํ•  ์ˆ˜ ์žˆ๋‹ค.

 

 

 

 

 

  UIButton.Configuration์„ ์‚ฌ์šฉํ•˜๋Š” UIButton์˜ ํƒ€์ดํ‹€์— ํฐํŠธ ์ ์šฉํ•˜๊ธฐ  

  (์•„๋ž˜ ๋”๋ณด๊ธฐ ํด๋ฆญ)  

๋”๋ณด๊ธฐ

iOS 15 ์ด์ƒ์„ ๋Œ€์‘ํ•˜๋ฉด์„œ UIButton.Configuration์œผ๋กœ ๋ชจ๋“  ๋ฒ„ํŠผ์˜ ๋””์ž์ธ์„ ํ•˜๊ณ  ์žˆ๋Š”๋ฐ,
์ด Configuration์—๋Š” ๋”ฐ๋กœ font ํ”„๋กœํผํ‹ฐ๊ฐ€ ์กด์žฌํ•˜์ง€ ์•Š์•˜๋‹ค.

 

๋ฐฑ์—…ํ•˜๊ธฐ ๋ฒ„ํŠผ๊ณผ ๋ถˆ๋Ÿฌ์˜ค๊ธฐ ๋ฒ„ํŠผ ํƒ€์ดํ‹€์˜ ํฐํŠธ ์ ์šฉ์€ AttributeContainer์˜ font ํ”„๋กœํผํ‹ฐ์— ํฐํŠธ๋ฅผ ์ง€์ •ํ•˜๊ณ , 
Configuration์˜ attributedTitle ํ”„๋กœํผํ‹ฐ์—์„œ 
AttributeContainer์˜ attributes์— AttributeContainer๋ฅผ ์ง€์ •ํ•จ์œผ๋กœ์จ ํ•ด๊ฒฐํ•  ์ˆ˜ ์žˆ์—ˆ๋‹ค.

 

์œ„ BackupAndRestoreButton์— ์ƒ๋žต๋œ setUI() ๋ฉ”์„œ๋“œ๋Š” ๋‹ค์Œ๊ณผ ๊ฐ™๋‹ค.

// MARK: - Design Methods
    private func setUI() {
        guard let title = title else {
            print("No title for BackupAndRestoreButton")
            return
        }

        var container = AttributeContainer()
        container.font = .meringue(size: 15)
        container.foregroundColor = .label
        
        var buttonConfiguration = UIButton.Configuration.filled()
        buttonConfiguration.baseBackgroundColor = .systemBackground
        buttonConfiguration.attributedTitle = AttributeContainer(title, attributes: container)
        
        configuration = buttonConfiguration
        
        addShadows()
    }
    
    private func addShadows() {
        addShadow(radius: 12, opacity: 0.2)  // ์•„๋ž˜ 'UIView+Extension์œผ๋กœ ๊ทธ๋ฆผ์ž ๊ตฌํ˜„์„ ๋น ๋ฅด๊ฒŒ ํ•˜๊ธฐ' ์ฐธ๊ณ 
    }

 

 

 

 

  UIView+Extension์œผ๋กœ ์žฌ์‚ฌ์šฉ์„ ํ™œ์šฉํ•ด ๊ทธ๋ฆผ์ž ๊ตฌํ˜„์„ ๋น ๋ฅด๊ฒŒ ํ•˜๊ธฐ  

 

๋งค๋ฒˆ 4์ค„์”ฉ ์ ์–ด์•ผ ๊ทธ๋ฆผ์ž๋ฅผ ๊ทธ๋ฆด ์ˆ˜ ์žˆ๋Š” ๋ฒˆ๊ฑฐ๋กœ์›€์„ ์ค„์ด๊ณ ์ž extension์œผ๋กœ ๋ฉ”์„œ๋“œ๋ฅผ ๋งŒ๋“ค์—ˆ๋‹ค.

UIView์˜ extension์— ์•„๋ž˜์™€ ๊ฐ™์€ ๋ฉ”์„œ๋“œ๋ฅผ ์„ ์–ธํ•ด ๋†“์œผ๋ฉด, 
UIImageView, UIButton๊ณผ ๊ฐ™์ด UIView๋ฅผ ์ƒ์†๋ฐ›๋Š” ๊ฐ์ฒด๋“ค์—์„œ ์ด ๋ฉ”์„œ๋“œ๋กœ ๊ทธ๋ฆผ์ž๋ฅผ ๊ทธ๋ฆด ์ˆ˜ ์žˆ๋‹ค!

extension UIView {
    func addShadow(radius: CGFloat, opacity: Float) {
        layer.shadowColor = UIColor.tintColor.cgColor
        layer.shadowOffset = .zero
        layer.shadowRadius = radius
        layer.shadowOpacity = opacity
    }
}

 

 

์ด๋ ‡๊ฒŒ UIImageView์—์„œ๋„ ๊ฐ€๋Šฅํ•˜๊ณ 

let cloudImageView = UIImageView().then {
        $0.contentMode = .scaleAspectFit
        $0.image = UIImage(systemName: SFSymbol.cloudFill)
        $0.tintColor = .white
//        $0.layer.shadowColor = UIColor.tintColor.cgColor
//        $0.layer.shadowOffset = .zero
//        $0.layer.shadowRadius = 60
//        $0.layer.shadowOpacity = 0.4
//	    ↓ !!!
        $0.addShadow(radius: 60, opacity: 0.4)
    }

 

 

UITableView์—์„œ๋„ ๊ฐ€๋Šฅํ•˜๋‹ค.

let tableView = UITableView(frame: .zero, style: .insetGrouped).then {
        $0.register(BackupFileTableViewCell.self, forCellReuseIdentifier: BackupFileTableViewCell.reuseIdentifier)
        $0.backgroundColor = .clear
        $0.addShadow(radius: 12, opacity: 0.2)
    }

 

 

 

extension์œผ๋กœ ๊ตฌํ˜„๋œ ๋ฉ”์„œ๋“œ๋Š” ์„œ๋ธŒํด๋ž˜์Šค์—์„œ๋„ ์‚ฌ์šฉํ•  ์ˆ˜ ์žˆ๋‹ค๋Š” ๊ฒƒ ๋˜ํ•œ ์•Œ ์ˆ˜ ์žˆ๋‹ค..!