尝试重新加载视图控制器以更新当前主题

乔治·E

我在寻找什么

我想重新加载在我的视图控制器各方面的意见,主题之间切换(类似于TwitterApple Maps不会)。

推特 苹果地图


我如何设置不同的主题

我有这样的主题视图设置:

@IBDesignable
extension UIView {

    @IBInspectable
    var lightBackgroundColor: UIColor? {
        set {
            switch GEUserSettings.theme {
            case .light:    backgroundColor = newValue
            case .dark:     break
            }
        }
        get {
            return self.lightBackgroundColor
        }
    }

    @IBInspectable
    var darkBackgroundColor: UIColor? {
        set {
            switch GEUserSettings.theme {
            case .light:    break
            case .dark:     backgroundColor = newValue
            }
        }
        get {
            return self.darkBackgroundColor
        }
    }
}

这使我可以根据当前主题Main.storyboard设置lightdark主题背景色。我的背景模糊效果被排除在外,因为我找不到更新stylein代码的方法,因此它在中创建viewDidLoad


摇动设备触发主题

但是,当我想更改主题时,我不确定该怎么做。我想通过摇动设备来触发它,就像这样:

override func motionBegan(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
    print("Shaken!")
    let oppositeTheme: GEUserSettings.Theme = {
        switch GEUserSettings.theme {
        case .light:    return .dark
        case .dark:     return .light
        }
    }()

    GEUserSettings.theme = oppositeTheme

    // My attempt to update the view controller to
    // update the theme, which doesn't do anything.
    dismiss(animated: true) {
        UIApplication.shared.keyWindow?.rootViewController?.present(self, animated: true, completion: nil)
        // Yes, the presenting is working, but the views don't change.
    }
}

有什么可能的解决方案?

如果退出并重新启动该应用程序,设置将生效。我可以强制退出应用程序(不使用exit(0)不算崩溃),或在使用应用程序时重新加载它。

我试图关闭然后重新加载视图控制器,如上面的代码所示。我要重装的一个显示在基本视图控制器的顶部。

当我使用情节提要板时,如何进行这项工作?

编辑-添加了我的亮/暗模式的图像,使我的问题更清晰:

亮/暗模式

乔治·E

我终于弄清楚了,使用NotificationCenter

GEUserSettings

GEUserSettings 现在看起来如下:

enum GEUserSettings {

    enum Theme: String {
        case light
        case dark
    }
    /// The current theme for the user.
    static var theme: Theme = .dark
    #warning("Store theme in UserDefaults")

    /// Toggles the theme.
    static func toggleTheme() {
        switch GEUserSettings.theme {
        case .light:    theme = .dark
        case .dark:     theme = .light
        }

        NotificationCenter.default.post(name: Notification.Name("UpdateThemeNotification"), object: nil)
    }
}

GEView

GEView是我的的自定义子类UIView这是替代品,而不是我对的扩展UIView现在看起来与此类似:

/// UIView subclass to allow creating corners, shadows, and borders in storyboards.
@IBDesignable
final class GEView: UIView {

    // MARK: - Initializers
    override init(frame: CGRect) {
        super.init(frame: frame)
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)

        // Triggers when the theme is changed
        NotificationCenter.default.addObserver(self, selector: #selector(updateBackgroundColorNotification), name: Notification.Name("UpdateThemeNotification"), object: nil)
    }
    @objc
    private func updateBackgroundColorNotification() {
        updateBackgroundColor()
    }


    /* ... */


    // MARK: - Background
    @IBInspectable
    var lightBackgroundColor: UIColor? {
        didSet {
            updateBackgroundColor()
        }
    }
    @IBInspectable
    var darkBackgroundColor: UIColor? {
        didSet {
            updateBackgroundColor()
        }
    }

    /// Updates the background color depending on the theme.
    private func updateBackgroundColor() {
        switch GEUserSettings.theme {
        case .light:    backgroundColor = self.lightBackgroundColor
        case .dark:     backgroundColor = self.darkBackgroundColor
        }
    }
}

通过更新 motionBegan(_:with:)

override func motionBegan(_ motion: UIEvent.EventSubtype, with event: UIEvent?) {
    super.motionBegan(motion, with: event)

    // Toggles the theme and update the views
    GEUserSettings.toggleTheme()
    drawerViewModel.updateBlurEffect(drawerView: drawerView)
}

并且模糊将被删除并重新创建,如下所示:

/// Creates the blur effect behind the collection view.
func updateBlurEffect(drawerView: GEView) {
    if let blurView = drawerView.subviews[0] as? UIVisualEffectView {
        blurView.removeFromSuperview()
    }

    let blurEffect: UIBlurEffect = {
        switch GEUserSettings.theme {
        case .light:    return UIBlurEffect(style: .light)
        case .dark:     return UIBlurEffect(style: .dark)
        }
    }()
    let blurView = UIVisualEffectView(effect: blurEffect)

    drawerView.addSubview(blurView)
    drawerView.sendSubviewToBack(blurView)
    GEConstraints.fillView(with: blurView, for: drawerView)
}

这甚至不需要退出应用程序或重新加载视图控制器,它会立即发生!

额外(动画)

如果需要,还可以通过更改updateBackgroundColor()功能来为颜色变化设置动画

/// Updates the background color depending on the theme.
private func updateBackgroundColor() {
    UIView.animate(withDuration: 0.25) {
        switch GEUserSettings.theme {
        case .light:    self.backgroundColor = self.lightBackgroundColor
        case .dark:     self.backgroundColor = self.darkBackgroundColor
        }
    }
}

您还可以设置模糊动画:

/// Creates the blur effect behind the collection view.
func updateBlurEffect(drawerView: GEView) {
    if let blurView = drawerView.subviews[0] as? UIVisualEffectView {
        UIView.animate(withDuration: 0.25, animations: {
            blurView.alpha = 0
        }, completion: { _ in
            blurView.removeFromSuperview()
        })
    }

    let blurEffect: UIBlurEffect = {
        switch GEUserSettings.theme {
        case .light:    return UIBlurEffect(style: .light)
        case .dark:     return UIBlurEffect(style: .dark)
        }
    }()
    let blurView = UIVisualEffectView(effect: blurEffect)
    blurView.alpha = 0

    drawerView.addSubview(blurView)
    drawerView.sendSubviewToBack(blurView)
    GEConstraints.fillView(with: blurView, for: drawerView)

    UIView.animate(withDuration: 0.25, animations: {
        blurView.alpha = 1
    })
}

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

提出新的视图控制器后关闭当前视图控制器-Swift

尝试在取消分配视图时加载视图控制器的视图... UIAlertController

重新加载AngularJS控制器

在Swift中关闭模式呈现的视图控制器后,如何重新加载ViewController?

Ajax POST到控制器操作以更新视图模型,然后重新加载div

如果从其他视图控制器按回,则重新加载而不重新加载。迅速

UISearchViewController不允许尝试在取消分配时加载视图控制器的视图

从ajax控制器调用更新视图

更新状态参数而无需重新加载控制器

尝试在取消分配<SFAuthenticationViewController>时加载视图控制器的视图

当用户回到视图控制器时,重新加载集合视图数据

控制器未更新AngularJS视图

尝试检查视图控制器是否已加载,然后将其显示在容器中(UISegmentedController)

从明细视图控制器返回后重新加载Tableview单元格-Swift

swift xcode iOS:我可以重新使用已加载的模态全屏视图控制器吗?

从控制器加载局部视图

Codeigniter问题与从控制器加载视图

快速保存当前视图控制器

如何让AngularJS路由器在导航时更新控制器值,而不是重新加载整个控制器?

页面视图控制器更新视图控制器?

如何在“后退”按钮上重新加载以前的视图控制器?

BAD_EXC_ACCESS用于尝试在取消分配时加载视图控制器

获取视图控制器当前比例

尝试使用 .nib 加载视图控制器失败

重新加载相同的视图控制器但具有不同的信息

如何从当前视图控制器弹出上一个视图控制器?

从另一个视图控制器动态更改视图控制器的主题而无需重新加载

重新加载视图控制器后如何仍然显示progressView的进度?

尝试更新前一个视图控制器上的 UI 时崩溃