Thank you for your response @eskimo, but it seems that I misjudged my previous implementation with just JSON file. I am trying to understand why it's not working properly before moving to CoreData usage.
I have a class that I use for managing filtering rules
final class FilterUtilities: NSObject {
// MARK: - Properties
/// Filter rules
@Published
var filterRules: [FilterRule] = [FilterRule.default]
/// Singleton property
static let shared = FilterUtilities()
// MARK: - Init
override init() {
super.init()
loadRules()
}
func getRule(_ socketFlow: NEFilterSocketFlow) -> FilterRule?
func addRule(rule: FilterRule)
func removeRule(domain: String)
func loadRules() {
if let sharedContainerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: Const.appGroupIdentifier) {
let fileURL = sharedContainerURL.appendingPathComponent("\(Const.filterStorageKey).json")
do {
let data = try Data(contentsOf: fileURL)
let decoder = JSONDecoder()
filterRules = try decoder.decode([FilterRule].self, from: data)
} catch {
Logger.statistics.error("Error loading filter rules: \(error.localizedDescription, privacy: .public)")
}
}
}
/// Method to save rules
func saveRules() {
if let sharedContainerURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: Const.appGroupIdentifier) {
let fileURL = sharedContainerURL.appendingPathComponent("\(Const.filterStorageKey).json")
if let encodedRules = try? JSONEncoder().encode(filterRules) {
do {
try encodedRules.write(to: fileURL)
} catch {
Logger.statistics.error("[FilterUtilities] - Error saving filter rules: \(error.localizedDescription, privacy: .public)")
}
}
} else {
Logger.statistics.error("[FilterUtilities] - container access denied")
}
}
}
I noticed that when I call getRule from my Filter Data Provider it doesn't contain newly added rules even though logs in FilterUtilities show that rule is added to filterRules (func getRule basically returns the rule for matched domain), however, if I reload the app, the rules, that Filter Data Provider couldn't access before are now accessible. Then I tried to use Filter Control Provider in order to notify Filter Data provider that rules changed by first using notifyRulesChanged() function and when it didn't work, adding subscription on rules array like this, but that didn't work either. In my implementation rules are added from DNSProxy and then Filter Provider uses them to handle ip-connections. I understand that I am probably missing a very important part but I don't see what's causing this problem yet.
override init() {
super.init()
filterUtilities.$filterRules
.debounce(for: .seconds(0.5), scheduler: DispatchQueue.main)
.sink { [weak self] _ in
self?.filterUtilities.loadRules()
}
.store(in: &subs)
}
I thought the problem could be related to synchronisation of the rules adding/retrieving, but all the logs are showing that DNSProxy is adding rules properly, before the Filter Provider intercepts the flow.
I would be very grateful for any suggestions
Thank you!