Add site with content blocker extension - ios

Hi I am writing a content blocker app.
In this app I want to allow the user add a website that he wants to block.
How can i do that? I used SFContentBlockerManager.reloadContentBlocker(withIdentifier: blockerIdentifier) but it's just activate filter of block list
Thats my protocol on which i write domain(website) how can implement it here to my blocklist in content blocker extension
extension WhiteBlackViewController: AddDomainViewControllerDelegate {
func addDomain(text: String?) {
if listSwitch.isOn {
viewModel.items.append(text ?? "")
viewModel.filtered.append(text ?? "")
tableView.reloadData()
}
}
}
Thats my content blocker:
class ContentBlockerRequestHandler: NSObject, NSExtensionRequestHandling {
func beginRequest(with context: NSExtensionContext) {
let documentFolder = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.cyberGuard")
guard let jsonURL = documentFolder?.appendingPathComponent("whiteList.json") else { return }
let attachment = NSItemProvider(contentsOf: jsonURL)
let item = NSExtensionItem()
item.attachments = [attachment!]
context.completeRequest(returningItems: [item], completionHandler: nil)
}
}

So i already has a solution for this.
You just need create appGroup between your extension and your app
And after that write in another file json and activate it
func activateFilterBlock(fileName: String, website: String, realPath: String) {
viewModel.dictionary.append(["action": ["type": "block"], "trigger": ["url-filter": "\(website)"]])
let jsonData = try! JSONSerialization.data(withJSONObject: viewModel.dictionary, options: .prettyPrinted)
if let json = String(data: jsonData, encoding: String.Encoding.utf8) {
let file = "\(fileName).json"
if let dir = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.cyberGuard") {
let path = dir.appendingPathComponent(file)
do {
try json.write(to: path, atomically: false, encoding: String.Encoding.utf8)
let id = "\(realPath).json"
SFContentBlockerManager.reloadContentBlocker(withIdentifier: id) {error in
guard error == nil else {
print(error ?? "Error")
return
}
print("Reloaded")
}
} catch {
print(error.localizedDescription)
}
}
}
}
If you want receive this json you just can get it from new created json file
func getJSON(fileName: String, success: #escaping(Success), onError: #escaping(OnError)) {
let groupUrl: URL = FileManager().containerURL(forSecurityApplicationGroupIdentifier: "group.cyberGuard")!
if let path = URL(string: "\(fileName).json", relativeTo: groupUrl) {
do {
let data = try Data(contentsOf: path)
let value = try JSONDecoder().decode(WhiteBlackList.self, from: data)
items = value.map({ $0.trigger.urlFilter })
filtered = value.map({ $0.trigger.urlFilter })
if let json = try? JSONSerialization.jsonObject(with: data, options: .allowFragments) as? [[String: [String: Any]]] {
dictionary = json
}
success()
} catch {
onError(error.localizedDescription)
}
}
}
If it helps, let me know :)

Related

Converting Data from http request from JSON Dictionary of Dictionaries into one Array of Dictionaries in Swift

When Running my http request I get returned the data in the following way.
I am requesting as follows
do {
if let file = URL(string: "https://myhttprequest....") {
let data = try Data(contentsOf: file)
let json = try JSONSerialization.jsonObject(with: data, options: [])
if let object = json as? [String: Any] {
// json is a dictionary
print(object)
} else {
print("JSON is invalid")
}
} else {
print("no file")
}
} catch {
print(error.localizedDescription)
}
The http request shows like this for example
{"created":[{"id":"-LVEAdIk2KwDmxBj25pK","caption":"Cool watch bro ","creationDate":1546442937.5934439,"imageHeight":1000,"imageUrl":"https://firebasestorage.googleapis.com/..."}],"reshared":[{"id":"-LVEAdIk2KwDmxBj25pK","caption":"Cool watch bro ","creationDate":1546442937.5934439,"imageHeight":1000,"imageUrl":"https://firebasestorage.googleapis.com/..."}]}
I want to be able to put the value of object["created"] and object["reshared"] together to have one array of two dictionaries [[caption:"", creationDate:""...],[caption:"", creationDate:""...]]
I have tried by accessing them individually like object["created"] but its not of type dictionary and I cant seem to figure out how to get it to be one.
UPDATE: So I am now doing the following
guard let uid = Auth.auth().currentUser?.uid else { return }
let url = URL(string: "https://us-central1-flashtrend-bdcd3.cloudfunctions.net/getFeed/\(uid)")!
let task = URLSession.shared.dataTask(with: url) {(data, response, error) in
guard let firstData = data else { return }
let jsonStr = String(data: firstData, encoding: .utf8)!
guard let data = jsonStr.data(using: .utf8) else {
return
}
do {
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
return
}
guard let created = json["created"], let reshared = json["reshared"] else {
return
}
let result = [created, reshared]
print(result)
} catch {
print(error.localizedDescription)
}
}
task.resume()
But when i print it looks weird
[<__NSSingleObjectArrayI 0x600002de2290>(
{
caption = "Cool watch bro ";
creationDate = "1546442937.593444";
id = "-LVEAdIk2KwDmxBj25pK";
imageHeight = 1000;
imageUrl = "https://firebasestorage.googleapis.com/v0/b/flashtrend-bdcd3.appspot.com/o/posts%2FE346E4B7-31D8-4E9E-89F2-DA7C426C0537?alt=media&token=4936ce58-64bb-4d5a-b913-c3b87705614f";
imageWidth = 750;
swipes = 0;
userid = U9097gARoXOus96vT1uBHAcNPs03;
views = 1;
}
)
, <__NSArray0 0x600002df40c0>(
)
]
I have changed the http request result to json string, sample code for you as follow, works fine on my xcode:
let jsonStr = "{\"created\":{\"caption\":\"Cool watch bro \",\"creationDate\":\"1546442937.593444\",\"id\":\"-LVEAdIk2KwDmxBj25pK\",\"imageHeight\":1000,\"imageUrl\":\"https://firebasestorage.googleapis.com/v0/b/flashtrend-bdcd3.appspot.com/o/posts/E346E4B7-31D8-4E9E-89F2-DA7C426C0537?alt:media&token:4936ce58-64bb-4d5a-b913-c3b87705614f\",\"imageWidth\":750,\"swipes\":0,\"userid\":\"U9097gARoXOus96vT1uBHAcNPs03\",\"views\":1},\"reshared\":{\"caption \":\"Cool watch bro\",\"creationDate \":\"1546442937.593444\",\"id \":\"-LVEAdIk2KwDmxBj25pK \",\"imageHeight\":1000,\"imageUrl\":\"https://firebasestorage.googleapis.com/v0/b/flashtrend-bdcd3.appspot.com/o/posts/E346E4B7-31D8-4E9E-89F2-DA7C426C0537?alt:media&token:4936ce58-64bb-4d5a-b913-c3b87705614f\",\"imageWidth\":750,\"swipes\":0,\"userid\":\"U9097gARoXOus96vT1uBHAcNPs03\",\"views\":1}}"
guard let data = jsonStr.data(using: .utf8) else {
return
}
do {
guard let json = try JSONSerialization.jsonObject(with: data, options: []) as? [String: Any] else {
return
}
guard let created = json["created"], let reshared = json["reshared"] else {
return
}
let result = [created, reshared]
print(result)
} catch {
print(error.localizedDescription)
}

Reading countries names from JSON file problem

I am trying to load and parse countries names from json file using swift but I can't
This is file's format which I try to read: Countries JSON File
My code to do this task:
func getJsonFromUrl(){
let url = NSURL(string: COUNTRIES_URL)
URLSession.shared.dataTask(with: (url as URL?)!, completionHandler: {(data, response, error) -> Void in
if let jsonObj = try? JSONSerialization.jsonObject(with: data!, options: .allowFragments) as? NSDictionary {
if let countries_array = jsonObj!.value(forKey: "name") as? NSArray {
for country in countries_array {
if let countryDict = country as? NSDictionary {
if let name = countryDict.value(forKey: "name") {
self.countries_names.append((name as? String)!)
}
}
}
}
OperationQueue.main.addOperation ({
self.showNames()
})
}
}).resume()
}
But when I run it, it gives me an error in this line: if let countries_array = jsonObj!.value(forKey: "name") as? NSArray {
because of an unexpected nil.
The JSON starts with a bracket ([) therefore the root object is an array
Don't use NSURL, NSArray and NSDictionary and value(forKey in Swift.
And handle possible errors.
func getJsonFromUrl() {
let url = URL(string: COUNTRIES_URL)!
URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) -> Void in
if let error = error { print(error); return }
do {
if let countriesArray = try JSONSerialization.jsonObject(with: data!) as? [[String:String]] {
for country in countriesArray {
self.countries_names.append(country["name"]!)
}
}
} catch { print(error) }
OperationQueue.main.addOperation ({
self.showNames()
})
}).resume()
}
Or much more convenient with Decodable
struct Country : Decodable {
let name : String
}
func getJsonFromUrl() {
let url = URL(string: COUNTRIES_URL)!
URLSession.shared.dataTask(with: url!, completionHandler: {(data, response, error) -> Void in
if let error = error { print(error); return }
do {
let countries = try JSONDecoder().decode([Country].self, from: data!)
self.countries_names = countries.map{$0.name}
} catch { print(error) }
OperationQueue.main.addOperation ({
self.showNames()
})
}).resume()
}
It's an array not dictionary you need
if let dat = data {
if let jsonObj = try? JSONSerialization.jsonObject(with: dat, options:[]) as? [[String:String]]{
jsonObj.forEach { print($0["name"]) }
}
or use Codable
let res = try? JSONDecoder().decode([[String:String]].self,from:data)
or with model
struct Root: Codable {
let name : String
}
let res = try? JSONDecoder().decode([Root].self,from:data)

ios - How to wait api response using Alamofire

I want to ask about Semaphore in Alamofire.
I want the app wait for data from the server return success and continue to execute the code after (synchronous type). I use semaphore, but when the api function is called, the app is suspended...
This code is call data from server:
func getAllModels() -> [String] {
var _modelList:[String] = []
let url = BASE_URL + "getAllProductAndModelv2"
let semaphore = DispatchSemaphore(value: 0)
Alamofire.request(url, method:.get, parameters: [:], encoding: JSONEncoding.default).responseJSON { response in
let data = NSData(contentsOf: URL(string: url)!)
do {
if let data = data, let json = try JSONSerialization.jsonObject(with: data as Data) as? [String: Any], let models = json["models"] as? [[String:Any]] {
for model in models {
if let name = model["name"] as? String {
_modelList.append(name)
}
}
}
}catch {
print("error")
}
semaphore.signal()
}
semaphore.wait()
return _modelList
}
And this code is going to get the result:
let api = RestApiManager()
var result:[String] = api.getAllModels()
print(result)
How to relsove this issuse?
Thank you
Use completion
func getAllModels( completion: #escaping ([String] ,Bool) -> Void) {
var modelList:[String] = []
let url = BASE_URL + "getAllProductAndModelv2"
Alamofire.request(url, method:.get, parameters: [:], encoding: JSONEncoding.default).responseJSON { response in
let data = NSData(contentsOf: URL(string: url)!)
do {
if let data = data, let json = try JSONSerialization.jsonObject(with: data as Data) as? [String: Any], let models = json["models"] as? [[String:Any]] {
for model in models {
if let name = model["name"] as? String {
modelList.append(name)
}
}
completion(modelList,true)
}
}catch {
print("error")
completion([],false)
}
}
}
Then call it
self.getAllModels { (data, success) in
if(success)
{
// use data
}
}

Getting an AppDelegate Error while json parsing using Alamofire

From the below code it doesn't show any error but it gets run time appDelegate error and its reason is Terminating app due to uncaught exception 'NSInvalidArgumentException'. Please, tell what I want to do to get rid of this...
var urlstring: String!
urlstring = "\(signInAPIUrl)rooms/room_type"
urlstring = urlstring.replacingOccurrences(of: "Optional(", with: "")
urlstring = urlstring.replacingOccurrences(of: ")", with: "")
urlstring = urlstring.addingPercentEncoding( withAllowedCharacters: .urlQueryAllowed)!
print(urlstring)
self.callSiginGBAPI(url: "\(urlstring!)")
}
func callSiginGBAPI(url : String){
print("url: \(url)")
Alamofire.request(url).responseJSON { (response) in
self.parseDataGB(JSONData: response.data!)
print("Response:\(response)")
}
}
func parseDataGB(JSONData : Data){
do{
let readableJSon = try JSONSerialization.jsonObject(with: JSONData, options: .mutableContainers) as! jsonSTD
print(" !!! \(readableJSon[0])")
let value = readableJSon[0] as AnyObject
if let final = value.object(forKey: "id")
{
print(final)
let first_name:String = value.object(forKey: "id") as! String
let last_name:String = value.object(forKey: "type") as! String
let list_type:String = value.object(forKey: "list_type") as! String
print(first_name)
print(last_name)
print(list_type)
} else{
}
}
catch{
print(error)
}
}
Use the following extension to convert data to JSON object:
extension Data {
func JSONObject() -> AnyObject? {
do {
let content = try JSONSerialization.jsonObject(with: self as Data, options: JSONSerialization.ReadingOptions.allowFragments)
return content as AnyObject?
} catch _ as NSError {
return nil
}
}
var string: String {
return String(data: self as Data, encoding: String.Encoding.utf8) ?? "Error: Not able to get string from the data."
}
}
in response
let info = response.data?.JSONObject()

how to access array inside json object in swift

Can't access json object which is array inside json object
i want to access data from json object which have array inside array
and that json file is also uploaded
so pls can anyone check and help me how to get "weather.description"
data
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: "http://api.openweathermap.org/data/2.5/weather?q=London,uk&appid=13ae70c6aefa867c44962edc13f94404")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
print("some error occured")
} else {
if let urlContent = data {
do{
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers)
let newValue = jsonResult as! NSDictionary
print(jsonResult)
let name = newValue["name"]
//Here i am getting name as variable value
//this is not working
let description = newValue["weather"]??[0]["description"]
//this is not working
let description = newValue["weather"]!![0]["description"]
print()
}catch {
print("JSON Preocessing failed")
}
}
}
}
task.resume()
}
I have edited your code a bit, and added a few comments. Basiclly, lets check for the types of your response structure, and get the desired value.
let url = URL(string: "http://api.openweathermap.org/data/2.5/weather?q=London,uk&appid=13ae70c6aefa867c44962edc13f94404")!
let task = URLSession.shared.dataTask(with: url) { (data, response, error) in
if error != nil {
print("some error occured")
} else {
if let urlContent = data {
do{
let jsonResult = try JSONSerialization.jsonObject(with: urlContent, options: JSONSerialization.ReadingOptions.mutableContainers)
// I would not recommend to use NSDictionary, try using Swift types instead
guard let newValue = jsonResult as? [String: Any] else {
print("invalid format")
return
}
// Check for the weather parameter as an array of dictionaries and than excess the first array's description
if let weather = newValue["weather"] as? [[String: Any]], let description = weather.first?["description"] as? String {
print(description)
}
}catch {
print("JSON Preocessing failed")
}
}
}
}
task.resume()

Resources