iOS 内容阻止扩展正在加载多个 JSON 文件
iOS Content Blocking Extension Loading Multiple JSON Files
是否可以从 Content Blocker Extension return 多个 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)
}
我试过做多个项目和一个带有多个附件的项目。如果不可能有单独的文件,有什么方法可以合并多个文件(或以编程方式生成)?
可以有多个 JSON 文件并将其用于内容拦截器扩展。
1) 当您将多个扩展项传递给 completeRequestReturningItems
方法时抛出 SFContentBlockerErrorDomain
。
2) 无法将多个附件附加到 NSExtension
。对源代码的评论说,附件并不是要成为一组备用数据 formats/types,而是要包含在社交媒体 post 中的集合。这些项目总是键入 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
根据您的喜好。
对于那些好奇的人,我最终添加了代码以动态生成 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)
}
}
您可以将两个 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")
}
}
}
}
}
是否可以从 Content Blocker Extension return 多个 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)
}
我试过做多个项目和一个带有多个附件的项目。如果不可能有单独的文件,有什么方法可以合并多个文件(或以编程方式生成)?
可以有多个 JSON 文件并将其用于内容拦截器扩展。
1) 当您将多个扩展项传递给 completeRequestReturningItems
方法时抛出 SFContentBlockerErrorDomain
。
2) 无法将多个附件附加到 NSExtension
。对源代码的评论说,附件并不是要成为一组备用数据 formats/types,而是要包含在社交媒体 post 中的集合。这些项目总是键入 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
根据您的喜好。
对于那些好奇的人,我最终添加了代码以动态生成 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)
}
}
您可以将两个 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")
}
}
}
}
}