8

是否可以从Content Blocker Extension返回多个 JSON 文件?在我的 UI 中,用户启用/禁用不同的过滤器,每个过滤器都由一个单独的文件表示。我目前有(尽管迭代了多个,但它只加载一个):

func beginRequestWithExtensionContext(context: NSExtensionContext) {
    var items = Array <NSExtensionItem>()

    let resources = ["a", "b", "c"]
    for resource in resources {
        let url = NSBundle.mainBundle().URLForResource(resource, withExtension: "json")

        if let attachment = NSItemProvider(contentsOfURL: url) {
            let item = NSExtensionItem()
            item.attachments = [attachment]
            items.append(item)
        }
    }
    context.completeRequestReturningItems(items, completionHandler: nil)
}

我试过做多个项目和一个带有多个附件的项目。如果不可能有单独的文件,有什么方法可以组合多个(或以编程方式生成)?

4

3 回答 3

4

可以有多个 JSON 文件并将其用于 Content Blocker 扩展。

SFContentBlockerErrorDomain1)当您将多个扩展项传递给completeRequestReturningItems方法时抛出。

2) 不能将多个附件附加到NSExtension. 对源代码的评论说,附件并不是一组替代数据格式/类型,而是一个集合,例如包含在社交媒体帖子中。始终键入这些项目NSItemProvider。我认为您无法将多个 JSON 数据添加为附件,因为它们不是用于创建消息的一系列附件。

我的解决方案(已验证有效):

NSItemProvider可以用项目(NSData)和初始化typeIdentifier

let aData = NSData(contentsOfURL: NSBundle.mainBundle().URLForResource("a", withExtension: "json")!)
let bData = NSData(contentsOfURL: NSBundle.mainBundle().URLForResource("b", withExtension: "json")!)

aJSON = `convert aData to JSON`
bJSON = `convert bData to JSON`
combinedJSON = `aJSON + bJSON`
combinedData = 'convert combinedJSON to NSData'

let attachment = NSItemProvider(item: combinedData, typeIdentifier: kUTTypeJSON as String)

combinedData现在,您可以根据自己的喜好创建带有附件的扩展。

于 2015-09-21T19:55:34.247 回答
3

对于那些好奇的人,我最终添加了代码来动态生成 JSON 文件(保存到磁盘)。从其他答案看来,似乎可以通过返回NSData文件的表示来避免保存步骤——尽管这种尝试对我来说失败了。这是我的片段:

import UIKit
import MobileCoreServices

class ActionRequestHandler: NSObject, NSExtensionRequestHandling {

    func beginRequestWithExtensionContext(context: NSExtensionContext) {
        let item = NSExtensionItem()
        let items = [item]

        let url = buildJSONFileURL()
        if let attachment = NSItemProvider(contentsOfURL: url) { item.attachments = [attachment] }

        context.completeRequestReturningItems(items, completionHandler: nil)
    }

    func buildJSONFileURL() -> NSURL {
        let directories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)
        let directory = directories[0]

        let path = directory.stringByAppendingFormat("/block.json")

        let selector = [...] // Dynamically Generated
        let dictionary = [[
            "action": [ "type": "css-display-none", "selector": selector ],
            "trigger": [ "url-filter": ".*" ]
            ]]

        let data = try! NSJSONSerialization.dataWithJSONObject(dictionary, options: NSJSONWritingOptions.PrettyPrinted)
        let text = NSString(data: data, encoding: NSASCIIStringEncoding)!

        try! text.writeToFile(path, atomically: true, encoding: NSASCIIStringEncoding)

        return NSURL(fileURLWithPath: path)
    }

}
于 2015-09-24T01:30:59.380 回答
1

您可以将两个 JSON 规则文件合并到一个文件中并使用该文件。

    import UIKit
    import MobileCoreServices
    class ContentBlockerRequestHandler: NSObject, NSExtensionRequestHandling {

        func beginRequest(with context: NSExtensionContext) {

        let sharedContainerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "you app group identifier")

                let sourceURLRules = sharedContainerURL?.appendingPathComponent("Rules1.json")
                let sourceURLRules2 = sharedContainerURL?.appendingPathComponent("Rules2.json")
                do {
                    let jsonDecoder = JSONDecoder()

                    let dataFormRules1 = try Data(contentsOf: sourceURLRules1!, options: .mappedIfSafe)// Rule is Decode able Swift class            
                   let  rulesArray1 = try? jsonDecoder.decode(Array<Rule>.self,from: dataFormRules1)

                    let dataFormRules2 = try Data(contentsOf: sourceURLRules2!, options: .mappedIfSafe)
                    let  rulesArray2 = try? jsonDecoder.decode(Array<Rule>.self,from: dataFormRules2)

                    saveCombinedRuleFile(ruleList: rulesArray1! + rulesArray2!)

                } catch {
                    //handle error condition
                }

                let sourceURLCombinedRule = sharedContainerURL?.appendingPathComponent("CombinedRule.json")
                let combinedRuleAttachment = NSItemProvider(contentsOf: sourceURLCombinedRule)
                let item = NSExtensionItem()
                item.attachments = [combinedRuleAttachment]
                context.completeRequest(returningItems: [item], completionHandler: nil)
            }

            func saveCombinedRuleFile(ruleList:[Rule]) {
                let encoder = JSONEncoder()
                if let encoded = try? encoder.encode(ruleList) {
                    let sharedContainerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "you app group identifier")
                    if let json = String(data: encoded, encoding: .utf8) {
                        print(json)
                    }
                    if let destinationURL = sharedContainerURL?.appendingPathComponent("CombinedRule.json") {
                        do {
                            try  encoded.write(to: destinationURL)
                        } catch {
                            print ("catchtry")
                        }
                    }
                }
            }
        }
于 2020-05-14T04:55:41.227 回答