【问题标题】:UserDefaults for NSMutableAttributedStringNSMutableAttributedString 的 UserDefaults
【发布时间】:2020-12-10 08:50:25
【问题描述】:

我有一个 textView,它是应用程序的整个屏幕。用户输入新文本,更改属性等。我希望应用程序下次保存 textview 内容及其属性。我想出了userDefaults。我尝试了很多,但没有任何反应。我找不到解决方案。我从 stackoverflow https://stackoverflow.com/a/36940864/12698480 尝试了这个解决方案,但没有改变。 textview 上再次出现空白屏幕。我作为 Userdefaults 扩展的代码如下:

//Save text
func setNSMutableText(string: NSMutableAttributedString?, forKey key: String){
        var stringData: NSData?
        if let string = string {
            do {
                stringData = try NSKeyedArchiver.archivedData(withRootObject: string, requiringSecureCoding: false) as NSData?
                set(stringData, forKey: key)
                print("archived NSMutableData")
            } catch let err {
                print("error archiving string data", err)
            }
        }
    }

//LOAD text
    func getNSMutableForKey(key: String) -> NSMutableAttributedString? {
        var string: NSMutableAttributedString?
        if let stringData = data(forKey: "screentextKey") {
            do {
                string = try NSKeyedUnarchiver.unarchivedObject(ofClass: NSMutableAttributedString.self, from: stringData)
                print("UNARchived string data!!!")
            } catch let err {
                print("error extracting string data", err)
            }
        }
        return string
    }

用法:

//For saving
UserDefaults.standard.setNSMutableText(string: NSMutableAttributedString(attributedString: myTextView.attributedText), forKey: "screentextKey")

//For loading
override func viewDidLoad() {
   super.viewDidLoad()

   let oldstring = (UserDefaults.standard.getNSMutableForKey(key: "screentextKey"))!
   myTextView.attributedText = oldstring
}

有什么问题?我看到有人建议在 NSMutableAttributedString 的地方使用 NSAttributedString。我也尝试过这种方式,但没有改变。

【问题讨论】:

  • 控制台打印什么?什么时候调用 setNSMutableText?
  • 不是问题,而是:您将密钥传递给“getNSMutableForKey”,但您没有使用它。
  • @Jordan 这是一个计算器应用程序。我在计算“=”符号处调用 setNSMutableText。我在控制台中看不到任何内容,因为在销毁应用程序后连接丢失。
  • @Jordan 我在 viewDidLoad 部分使用了带有 getNSMutableForKey 的密钥,可以在帖子中看到
  • 当您执行let oldstring = ... 时,您可以打印它的值吗?之后是否会覆盖 myTextView 文本/attributedText?

标签: swift xcode userdefaults


【解决方案1】:

为了让它按照你想要的方式工作,你不必使用 NSKeyedArchiver.archivedData。相反,最好使用 CoreData 将数据保存在设备内存中(因为如果我知道它不是大量数据),使用 XCDataModel 对其进行结构化,然后使用 NSFetchController 获取它。

在 XCDataModel 中,您必须创建实体并为其设置属性(字符串、布尔值、双精度等)

之后,您必须设置 NSFetchedResultsController 才能管理该过程。

这是我的设置方式:

  1. 导入核心数据

  2. 设置持久化容器(数据容器):

    静态让 persistentContainer: NSPersistentContainer = { 让容器 = NSPersistentContainer(名称:“RebelFitness”) container.loadPersistentStores { (_, error) in 如果让错误=错误作为NSError? { fatalError("未解决的错误 (error), (error.userInfo)") } } 返回容器 }()

  3. 设置 NSFetchedResultsController:

    lazy var fetchedResultsController: NSFetchedResultsController = {

         let fetchRequest: NSFetchRequest< YourEntityName > = YourEntityName.fetchRequest()
         fetchRequest.sortDescriptors = [NSSortDescriptor(key: "distance", ascending: true), NSSortDescriptor(key: "duration", ascending: true)] //Here you use descriptor to sort the data in my example distance comes in array first and then any other elements
         let fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: CoreDataStack.persistentContainer.viewContext, sectionNameKeyPath: nil, cacheName: nil)
         fetchedResultsController.delegate = self as? NSFetchedResultsControllerDelegate
    
         return fetchedResultsController
    
     }()
    
  4. 用于获取保存数据的函数:

静态变量上下文:NSManagedObjectContext { return persistentContainer.viewContext }

在此函数中,我们将数据获取到新数组,然后将其传递给为 UIKit 元素提供数据的数组

func loadIsCurrent() -> [YourEntityName] {
        
        var _data : [YourEntityName] = []
        let context = persistentContainer.viewContext
        let fetchRequest: NSFetchRequest< YourEntityName > = YourEntityName.fetchRequest()
        fetchRequest.sortDescriptors = [NSSortDescriptor(key: "distance", ascending: false), NSSortDescriptor(key: "duration", ascending: true)]
        
        do {
            let data = try context.fetch(fetchRequest)
            if(sessions.count > 0) {
                _data = data
            }
        } catch {
            print("Something happened while trying to retrieve tasks...")
        }
        return _data
    }
  1. 将数据保存到 coreData:

func saveContext () { 让上下文 = persistentContainer.viewContext

guard context.hasChanges else {
  return
}
    
do {
  try context.save()
    try fetchedResultsController.performFetch()
} catch {
  let nserror = error as NSError
  fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
    }

}

【讨论】:

  • 我认为 Userdefaults 更便宜且易于使用。但是如果没有 NSMutableAttributedStrings 的方法,那么似乎我应该学习 coreData。我之前没用过coredata,所以没有经验。我现在将尝试实现这一点,如果成功,我将接受答案。
  • 一开始我也尝试归档文件,但不幸的是没有找到任何方法来完成它。我的研究表明,coreData 是唯一的方法,当然如果您不想使用任何其他在线数据库,例如 FireBase:)
  • 我成功了。问题是我忘记了在 viewDidLoad 部分中清除屏幕(文本视图)代码行的存在。当我删除那条线时,一切正常。无论如何,非常感谢您的贡献。目前不需要 CoreData :)
  • 很高兴你成功了:) 顺便说一句,当你从设备上的任务管理器关闭应用程序后,别忘了检查数据是否保留在播放中(过去我遇到过很多麻烦:( )
  • 感谢我兄弟的建议。我也试过了,一切正常:)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-08-18
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多