Ios 如何观察已更改的共享应用程序组文件
我有一个在我的应用程序和扩展名之间共享的文件: 从扩展名写入文件:Ios 如何观察已更改的共享应用程序组文件,ios,swift,nsfilemanager,Ios,Swift,Nsfilemanager,我有一个在我的应用程序和扩展名之间共享的文件: 从扩展名写入文件: func writeToFile() { let file = "file.txt" let text = "data" //just a text let dir = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.ml.test.apps")! let fileUR
func writeToFile()
{
let file = "file.txt"
let text = "data" //just a text
let dir = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.ml.test.apps")!
let fileURL = dir.appendingPathComponent(file)
do {
try text.write(to: fileURL, atomically: false, encoding: .utf8)
}
catch {/* error handling here */}
}
从应用程序中读取:
func readFromFile()
{
let file = "file.txt"
let dir = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.ml.test.apps")!
let fileURL = dir.appendingPathComponent(file)
do {
let text2 = try String(contentsOf: fileURL, encoding: .utf8)
NSLog("Dan: \(text2)")
}
catch {/* error handling here */}
}
我的问题是如何观察此文件的更改。如果扩展写入并更改数据,应用程序将收到更改通知并读取文件。下面是一个基于用法的简单演示
NSFileCoordinator/NSFilePresenter
模式
使用Xcode 11.4/iOS 13.4进行测试
1) 应用部分。以下是一个ViewController
扮演文件演示者角色,为简单起见(如果一个控制器可以管理多个文件,那么最好为每个文件创建显式演示者)
因此,基本上,您希望在writeToFile()函数成功执行时触发readFromFile()函数?如果是这种情况,您可以查看协议和委托或NotificationCenter。我可以在应用程序和扩展之间使用NotificationCenter吗?重复问题的潜在副本来自近6年前,这方面没有什么新的内容?不,没有什么新的内容。如果你看一下苹果的应用程序扩展编程指南,
NSFileProvider/Coordinator
是自iOS 9以来推荐的方法(如果不使用用户默认值)。请参阅此链接中的“共享数据”:
class ViewController: UIViewController, NSFilePresenter {
var presentedItemURL: URL?
var presentedItemOperationQueue: OperationQueue = OperationQueue.main
@IBOutlet weak var userNameField: UILabel!
func presentedItemDidChange() { // posted on changed existed file only
readFromFile()
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// register for presentedItemDidChange work
NSFileCoordinator.addFilePresenter(self)
}
override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
// unregister - required !!
NSFileCoordinator.removeFilePresenter(self)
}
override func viewDidLoad() {
super.viewDidLoad()
let file = "file.txt"
let dir = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.test.apps")!
presentedItemURL = dir.appendingPathComponent(file)
readFromFile() // read previously stored data
}
private func readFromFile()
{
let coordinator = NSFileCoordinator(filePresenter: self)
coordinator.coordinate(readingItemAt: presentedItemURL!, options: [], error: nil) { url in
if let text2 = try? String(contentsOf: url, encoding: .utf8) {
userNameField.text = text2 // demo label in view for test
} else {
userNameField.text = "<no text>"
//just initial creation of file needed to observe following changes
coordinator.coordinate(writingItemAt: presentedItemURL!, options: .forReplacing, error: nil) { url in
do {
try "".write(to: url, atomically: false, encoding: .utf8)
}
catch { print("writing failed") }
}
}
}
}
}
class TodayViewController: UIViewController, NCWidgetProviding, NSFilePresenter {
var presentedItemURL: URL?
var presentedItemOperationQueue: OperationQueue = OperationQueue.main
override func viewDidLoad() {
super.viewDidLoad()
let file = "file.txt"
let dir = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.test.apps")!
presentedItemURL = dir.appendingPathComponent(file)
}
@IBAction func post(_ sender: Any) { // action on button in extension
writeToFile()
}
func writeToFile()
{
let text = "new data" //just a text
let coordinator = NSFileCoordinator(filePresenter: self)
coordinator.coordinate(writingItemAt: presentedItemURL!, options: .forReplacing, error: nil) { url in
do {
try text.write(to: url, atomically: false, encoding: .utf8)
}
catch { print("writing failed") }
}
}
func widgetPerformUpdate(completionHandler: (@escaping (NCUpdateResult) -> Void)) {
completionHandler(NCUpdateResult.newData)
}
}