保存UIFont?到UserDefault Swift 3

时间:2017-01-23 19:19:39

标签: ios swift

我已经创建了一个步进器来增加我的应用程序中的字体大小,现在,我想保存最后的字体大小,这样当用户重新打开应用程序时,最后一个字体大小将是持久的。我试图将它保存到UserDefaults,但它不会让我保存我的标签,因为我使用UIFont来建立我想要的字体类型,并且CGFloat能够使用我的步进器切换字体大小。

当我运行应用程序并尝试选择字体大小时,应用程序崩溃,我找不到问题。我知道问题是试图将数据从UIFont保存到UserDefaults,因为当我注释掉那行代码时,应用程序没有运行问题。

此外,在我尝试在ViewDidAppear函数中调用存储的UserDefault设置后,我收到错误消息,说我无法分配Any?输入UIFont?

任何帮助将不胜感激。同样,我的意图是,当用户使用步进器更改字体大小时,即使退出并重新打开应用程序,字体大小仍将保持持久。

import UIKit
import Foundation

class ViewController: UIViewController {
@IBOutlet weak var quotesLabel: UITextView!
@IBOutlet weak var welcomeLabel: UILabel!
@IBOutlet weak var topLabel: UILabel!
@IBOutlet weak var generateLabel: UILabel!
@IBOutlet weak var fontStepper: UIStepper!
@IBOutlet weak var minFontSizeLabel: UILabel!
@IBOutlet weak var adjustFontSizeLabel: UILabel!
@IBOutlet weak var maxFontSizeLabel: UILabel!


    let quotesBook = QuotesBook()
    let defaults = UserDefaults.standard



    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically   from a nib



        fontStepper.wraps = true
        fontStepper.autorepeat = true
        generateLabel.font = UIFont(name: "HoeflerText-Italic", size: 15)
        generateLabel.textColor = UIColor(red: 25/255, green: 23/255, blue: 170/255, alpha: 230/255)
        generateLabel.textAlignment = NSTextAlignment.center
        topLabel.font = UIFont(name: "HoeflerText-Italic", size: 20)
        topLabel.textColor = UIColor(red: 25/255, green: 23/255, blue: 170/255, alpha: 230/255)



}

override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }

@IBAction func stepperPressed(_ sender: UIStepper) {
    quotesLabel.isEditable = true
    quotesLabel.font = UIFont (name: "Futura-MediumItalic", size: CGFloat(Float(sender.value)))
    defaults.set(quotesLabel.font, forKey: "textSize")




}
@IBAction func showQuoteBttn(_ sender: Any) {
    quotesLabel.textAlignment = NSTextAlignment.center
    maxFontSizeLabel.isHidden = false
    adjustFontSizeLabel.isHidden = false
    minFontSizeLabel.isHidden = false
    fontStepper.isHidden = false
    generateLabel.isHidden = false
    welcomeLabel.isHidden = true
    topLabel.isHidden = true
    quotesLabel.isHidden = false
    quotesLabel.text = quotesBook.randomQuote()

}

override func viewDidAppear(_ animated: Bool) {
    if let b = defaults.object(forKey: "textSize")
    {
    quotesLabel.font = b
    }

}

3 个答案:

答案 0 :(得分:6)

您无法将(UI)Font 直接保存到用户默认值中,因为它不符合属性列表。

合适的解决方案是分别保存字体的String名称和Float大小。这可以通过UserDefaults

的扩展名来完成
extension UserDefaults {

    func set(font : UIFont, forKey key : String)
    {
        let fontName = font.fontName
        let fontSize = font.pointSize
        self.set(fontName, forKey: key + "_name")
        self.set(Float(fontSize), forKey: key + "_size")
    }

    func font(forKey key : String) -> UIFont?
    {
        guard let fontName = string(forKey: key + "_name") else { return nil }
        let fontSize = float(forKey: key + "_size")
        if fontSize == 0.0 { return nil }
        return UIFont(name: fontName, size: CGFloat(fontSize))
    }
}

或者 - 也可以使用扩展程序 - 归档并从NSData取消归档字体:

extension UserDefaults {

    func set(font: UIFont, forKey key: String)
    {
        let data = NSKeyedArchiver.archivedData(withRootObject: font)
        self.set(data, forKey: key)
    }

    func font(forKey key: String) -> UIFont?
    {
        guard let data = data(forKey: key) else { return nil }
        return NSKeyedUnarchiver.unarchiveObject(with: data) as? UIFont
    }
}

答案 1 :(得分:1)

UIFont无法保存到UserDefaults。您可以根据需要保存字体大小和字体名称。

将字体保存到UserDefaults

let font = UIFont.systemFont(ofSize: 15)
let defaults = UserDefaults()
defaults.set(font.pointSize, forKey: "font")
defaults.set(font.fontName, forKey: "fontName")

稍后恢复:

let fontSize = defaults.float(forKey: "font")
let fontName = defaults.string(forKey: "fontName")
if let name = fontName {
    let savedFont = UIFont(name: name, size: CGFloat(fontSize))
    print("Saved font: \(savedFont)")
}
else {
    // Use default font
}

答案 2 :(得分:0)

(这是我搜索此问题的解决方案时出现的第一项,因此我不妨分享一个可持续的解决方案。在这里使用macOS,但NSFontDescriptor也存在于iOS上,只是替代UIFont。) >

推荐的保存字体的方法是不要这样做(有点浮躁,对不起)-但是在2013年的WWDC 223会议上(将字体与TextKit一起使用),建议专门用于 a)不选择属性(换句话说,不只保存字体名称和大小),并且 b)不保存NSFont,而是保存NSFontDescriptor。

NSFontDescriptor是一个容易被忽略的类,但是documentation很清楚

  

符号特征取代了NSFontManager使用的现有NSFontTraitMask类型。

所以我们应该使用它。尤其是在iOS上,您可以用它做很多奇怪的事情,包括要使用的字体的级联首选项,特定于语言的设置等。

保存,假设您使用的字体名为“字体”:

  let fontDescriptor = font.fontDescriptor
           let descriptorData = NSKeyedArchiver.archivedData(withRootObject: fontDescriptor)
            userDefaults.set(descriptorData, forKey: "descriptorData")

阅读:

if let descriptorData = userDefaults.data(forKey: "descriptorData"){
        if let fontDescriptor = NSKeyedUnarchiver.unarchiveObject(with: descriptorData) as? NSFontDescriptor {
            let myFont = NSFont(descriptor: fontDescriptor, size: 0)
        }
    }

将大小设置为'0'意味着它将从描述符中获取大小,否则将覆盖它。

这不会保存字体颜色;如果要保存默认的文字颜色,则仍需要单独进行。