【问题标题】:Swift: How to change views' background from other viewsSwift:如何从其他视图更改视图的背景
【发布时间】:2019-08-19 10:15:02
【问题描述】:

我的任务是创建一个可以更改和保存背景的应用程序。我想做一些更精细的事情,所以我决定创建一个颜色菜单,让我可以更改所有视图的背景。现在,我有了菜单,并且知道如何在背景中设置和保存图片/颜色。但我不知道如何从一个视图控制器到另一个。现在我的代码改变了它自己视图的背景。这是我的代码(我知道它很多......):

首先,我有 2 个扩展允许我 1) 使用用户默认值保存 UIColor; 2) 使用 rgb 颜色:

//MARK: - Extension for rgb
extension UIColor {
    convenience init(red: Int, green: Int, blue: Int) {
        assert(red >= 0 && red <= 255, "Invalid red component")
        assert(green >= 0 && green <= 255, "Invalid green component")
        assert(blue >= 0 && blue <= 255, "Invalid blue component")

        self.init(red: CGFloat(red) / 255.0, green: CGFloat(green) / 255.0, blue: CGFloat(blue) / 255.0, alpha: 1.0)
    }

    convenience init(rgb: Int) {
        self.init(
            red: (rgb >> 16) & 0xFF,
            green: (rgb >> 8) & 0xFF,
            blue: rgb & 0xFF
        )
    }
}


//MARK: - Extension to save colors
extension UserDefaults {
    func setColor(color: UIColor?, forKey key: String) {
        var colorData: NSData?
        if let color = color {
            do {
                colorData = try NSKeyedArchiver.archivedData(withRootObject: color, requiringSecureCoding: false) as NSData?
                set(colorData, forKey: key)
            } catch let error {
                print("error archiving color data", error)
            }
        }
    }

    func colorForKey(key: String) -> UIColor? {
        var color: UIColor?
        if let colorData = data(forKey: "Background") {
            do{
                color = try NSKeyedUnarchiver.unarchivedObject(ofClass: UIColor.self, from: colorData)
            } catch let error {
                print("error unarchivig color data", error)
            }
        }
        return color
    }

}

我的 viewDidLoad:

var defaults = UserDefaults.standard
private let backgroundKey = "backg"
 override func viewDidLoad() {
        super.viewDidLoad()


        //MARK: - Background Settings


        let color = defaults.colorForKey(key: backgroundKey)
        view.backgroundColor = color

        if let backgroundImage = self.getSavedBackgroundImage() {
            self.backgroundImageView.image = backgroundImage
        }
}

允许我将图片设置为背景的代码

@IBOutlet weak var backgroundImageView: UIImageView!
//I KNOW THIS HAS TO BE PUT IN THE VC WHERE I WANT THE BACKGROUND TO BE CHANGED
 @IBAction func pictureButton(_ sender: Any) {
        let imagePicker = UIImagePickerController()
        imagePicker.delegate = self
        imagePicker.sourceType = .photoLibrary
        imagePicker.allowsEditing = false
        present(imagePicker, animated: true, completion: nil)
    }
    func imagePickerController(_ picker: UIImagePickerController, didFinishPickingMediaWithInfo info: [UIImagePickerController.InfoKey : Any]) {
        if let image = info[UIImagePickerController.InfoKey.originalImage] as? UIImage {
            backgroundImageView.image = image
            let _ = self.saveBackgroundImage(image: image)

        }

        self.dismiss(animated: true, completion: nil)

    }
    func saveBackgroundImage(image: UIImage) -> Bool {
        guard let data = image.pngData() ?? backgroundImageView.image?.pngData() else {
            return false
        }
        guard let directory = FileManager.default.urls(for: .documentDirectory,
                                                       in: .userDomainMask).first else {
                                                        return false
        }
        do {
            try data.write(to: directory.appendingPathComponent("MainBackgroound.png"))
            return true
        } catch {
            print(error.localizedDescription)
            return false
        }
    }

    func getSavedBackgroundImage() -> UIImage? {
        if let dir = FileManager.default.urls(for: .documentDirectory,
                                              in: .userDomainMask).first {
            return UIImage(contentsOfFile: URL(fileURLWithPath: dir.absoluteString).appendingPathComponent("MainBackgroound.png").path)
        }
        return nil
    }

    func deleteImage() {
        let fileManager = FileManager.default
        let yourProjectImagesPath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("MainBackgroound.png")
        if fileManager.fileExists(atPath: yourProjectImagesPath) {
            try! fileManager.removeItem(atPath: yourProjectImagesPath)
        }
        let yourProjectDirectoryPath = (NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0] as NSString).appendingPathComponent("MainBackgroound.png")
        if fileManager.fileExists(atPath: yourProjectDirectoryPath) {
            try! fileManager.removeItem(atPath: yourProjectDirectoryPath)
        }
    }

允许我更改背景颜色的代码

@IBAction func lightPinkButton(_ sender: Any) {
        self.deleteImage()
        let lightPink = UIColor(red: 255, green: 215, blue: 214).withAlphaComponent(1)
        defaults.setColor(color: lightPink, forKey: backgroundKey)
        view.backgroundColor = lightPink
    }

【问题讨论】:

    标签: ios swift uiview background uibutton


    【解决方案1】:

    您应该为背景颜色更改和背景图像更改时创建Notification。任何应该是主题的 ViewController 都需要监听这些通知并相应地更新自身:

    //Make your custom notification
    extension Notification.Name {
        static let backgroundColorUpdated = Notification.Name("backgroundColorUpdated")
    }
    
    //Post the notification when you update backgroundColor
    NotificationCenter.default.post(Notification(name: .backgroundColorUpdated, object: nil, userInfo: ["backgroundColor": UIColor.red]))
    
    //Subscribe everywhere that needs to be interested in backgroundColor changes
    var token: NSObjectProtocol? // retain token for life of subscription, ie as long as you vc exists
    ...
    token = NotificationCenter.default.addObserver(forName: .backgroundColorUpdated, object: nil, queue: .main) { notification in
        guard let backgroundColor = notification.userInfo?["backgroundColor"] as? UIColor else {
            return
        }
        //Do stuff with backgroundColors here
    }
    
    

    【讨论】:

    • 我真的不知道如何使用这些信息:我必须在我的按钮中输入NotificationCenter.default.post(Notification(name: .backgroundColorUpdated, object: nil, userInfo: ["backgroundColor": UIColor.red])) 而不是 userDefaults 吗?我必须将令牌放在我的 viewDidLoad 中吗?你对 backgroundColors 的东西是什么意思?这也适用于图片吗?
    【解决方案2】:

    您如何创建一个基本视图控制器,例如ColorViewController,在其中您有一个对背景颜色的引用,然后从那里继承并在您需要的地方更新它。

    这样

    ColorViewController

    class ColorViewController: UIViewController {
    
        var myBackgroundColor: UIColor = .white
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
    }
    

    ViewControllerOne

    class ViewControllerOne: ColorViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
    
            view.backgroundColor = myBackgroundColor
        }
    
        @IBAction func blueButtonTapped(_ sender: Any) {
            myBackgroundColor = .blue
            view.backgroundColor = myBackgroundColor
        }
    
    }
    

    ViewControllerTwo

    class ViewControllerTwo: ColorViewController {
    
        override func viewDidLoad() {
            super.viewDidLoad()
        }
    
        override func viewWillAppear(_ animated: Bool) {
            super.viewWillAppear(animated)
    
            view.backgroundColor = myBackgroundColor
        }
    
        @IBAction func purpleButton(_ sender: Any) {
            myBackgroundColor = .purple
            view.backgroundColor = myBackgroundColor
        }
    
    }
    

    【讨论】:

    • 等等,这可能不是我的意思。在我的背景设置中,我有不同的按钮,每个按钮都与一种颜色相关联,我希望这些按钮可以更改所有视图的颜色/图像,并只需在背景设置中按一个按钮即可保存它们。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多