在多个视图控制器上使用委托和协议快速更改主题

时间:2019-07-17 05:29:43

标签: ios swift delegates protocols

我正在尝试第一次使用委托和协议。

我想在许多视图控制器中更改主题。

然后在任何具有更改主题协议的控制器上

当我现在转到此控制器时,我希望主题是新的但旧的。

我不会从主题控制器转到它们已更改的地方


我的代码

protocol ThemeDelegate: class {
    func changeTheme(theme: UIColor)
}


class FirstController: UICollectionViewController, UICollectionViewDelegateFlowLayout, ThemeDelegate {

    var newTheme: UIColor  = .red

    func changeTheme(theme: UIColor) {
        newTheme = theme
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = newTheme
    }
}

ThemeController {

    weak var themeDelegate: ThemeDelegate?

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {        
        let theme = .blue        
        themeDelegate?.changeTheme(theme: theme)        
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {

        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: themeCellId, for: indexPath) as! ThemeCell
        cell.themeImageView.image = UIImage(named: "theme cell image")
        return cell
    }
}

this is order

image2

2 个答案:

答案 0 :(得分:1)

我将尝试使其简单:-

1)首先,声明一个协议:-

protocol ThemeDelegate{
    func changeTheme(theme: String, fontColor: UIColor, alpha: CGFloat)
}

2)在ThemeController中具有该协议的变量:

open var themeDelegate: ThemeDelegate? = nil

3)通过themeDelegate调用委托函数:-(直到这一步为止,您都已完成此操作)

func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
    themeDelegate?.changeTheme(theme: theme, fontColor: fontColor, alpha: alpha)
}

4)您需要像AnyController一样将yourThemeControllerInstance.delegate = self用作委托人,并且您也已经做到了。

该操作无效,因为您已声明ThemeController的新实例,并已符合AnyController是该新实例的委托,该新实例具有相同的旧主题:< / strong>

override func viewDidLoad() {
    let themeController = ThemeController() // This is a new instance which you have created, so gets initialised with old theme. You have made your class to be the delegate of this instance
    themeController.themeDelegate = self
}

为使您的代表按预期工作,您需要使用ThemeController 的同一实例来更改主题

答案 1 :(得分:1)

您可以设置委托,但需要加载仔细的视图。

您也可以使用通知进行此操作,并发送所有符合主题的viewControllers

1-您的步骤

import UIKit

protocol ThemeDelegate: class {
    func changeTheme(theme: String, fontColor: UIColor, alpha: CGFloat)
}

class ThemeController: UIViewController {

    weak var themeDelegate: ThemeDelegate?

    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        themeDelegate?.changeTheme(theme: theme, fontColor: fontColor, alpha: alpha)
    }

}

class XViewController: UIViewController {


    // Create an instance
    lazy var themeController = ThemeController()


    override func viewDidLoad() {
        super.viewDidLoad()

        // We need call loadView becase collectionView needs to be show
        themeController.loadView()
        themeController.themeDelegate = self

    }

}
extension XViewController: ThemeDelegate {
    // And we conform ThemeDelegate
    func changeTheme(theme: String, fontColor: UIColor, alpha: CGFloat) {
        // TODO UI
    }
}

2-观察者步骤

// Sometimes we need update multiple viewControllers and we should use notification and observers


// We create a model
struct Theme {
    let theme: String
    let fontColor: UIColor
    let alpha: CGFloat
}

// We need a protocol for we don't want all view controller listen theme
protocol Themeable: class {
    func listenTheme()
    func didThemeChange(theme: Theme)
}


// Global notification name
let themeableNotificationName = Notification.Name(rawValue: "ThemeableNotification")

// Our protocol extension and observer notification
extension Themeable where Self: UIViewController {
    func listenTheme() {
        NotificationCenter.default.addObserver(forName: themeableNotificationName, object: nil, queue: nil) { [weak self] notification in
            guard let theme = notification.object as? Theme else { return }
            self?.didThemeChange(theme: theme)
        }
    }

}


// Notification sender themeController
class NotifyThemeController: UIViewController {


    func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
        // Create a model and post
        NotificationCenter.default.post(name: themeableNotificationName, object: Theme(theme: "Lorem", fontColor: .red, alpha: 1.0), userInfo: nil)
    }

}

// YViewController
class YViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        // We need call this method for observer
        listenTheme()
    }


}
// YViewController conforms Themeable
extension YViewController: Themeable {
    func didThemeChange(theme: Theme) {
        // TODO UI
    }

}
// ZViewController
class ZViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()
        // We need call this method for observer
        listenTheme()
    }


}
// ZViewController conforms Themeable
extension ZViewController: Themeable {
    func didThemeChange(theme: Theme) {
        // TODO UI
    }

}

玩得开心!