How to convert array of NSCFString to Array of NSCFNumber in swift? - ios

I have fetched array (say contactNameList) from SQLITE which is array of NSCFString. I want to compare objects of contactNameList with array of Id(say bookIdArray) which is of Int type.Can anyone please guide me.
Help will be appreciated.Thank you in advance :)
Code:
let testDetail_Obj = OfflineDB()
ContactDataArray = testDetail_Obj.fetch_BooksFromSQLite()
for i in 0..< ContactDataArray.count
{
let newItem: Any = ContactDataArray[i] as Any
contactNameList.addObjects(from: [(newItem as AnyObject).value(forKey: "book_Id") as Any])
print("contactNameList fetched from db = \(contactNameList)")
}
bookIdArray = contactNameList // tried this
func loadBooks() {
let v = Constant.DBHandler()
v.clearDatabase()
Alamofire.request(Constant.url.getAllBooksUrl, method: .get, parameters: nil, encoding: JSONEncoding.default)
.downloadProgress(queue: DispatchQueue.global(qos: .utility)) { progress in
}
.validate { request, response, data in
// Custom evaluation closure now includes data (allows you to parse data to dig out error messages if necessary)
return .success
}
.responseJSON {
response in switch response.result {
case .success(let JSON):
if let jsonResult = JSON as? Dictionary<String, AnyObject> {
// do whatever with jsonResult
let booksJson = jsonResult ["objects"]
print("jsonResult In loadBook= \(jsonResult)")
let realm = try! Realm()
for bookJson in booksJson as! [NSDictionary] {
let book = Book()
print(bookJson)
book.author = bookJson["author"] as! String
print("\(String(describing: jsonResult ["author"]))")
book.bookImg = bookJson["book_img"] as! String
book.bookName = bookJson["book_name"] as! String
book.desc = bookJson["description"] as! String
book.language = bookJson["language"] as! String
book.noOfChapters = bookJson["no_of_chapters"] as! Int
book.id = bookJson["id"] as! Int
book.timestamp = bookJson["timestamp"] as! String
if bookIdArray.contains(book.id) {
// where, static var bookIdArray = [2,10]
book.isHidden = false
}}}}}}
I want to show i.e -> book.isHidden = false , for all books whose id is present in contactNameList.I have tried
bookIdArray = contactNameList
But not getting output as per requirement.

Related

JSON Parsing Swift using JSONPlaceholder

I'm playing with Swift and JSONPlaceholder. I want to retrieve all the data contained in: https://jsonplaceholder.typicode.com/photos
I created a function that is acceding to the url, downloading the JSON but then I don't know how can I obtain the title and the thumbnailUrl to pass then for populate the tableView. In the past I used this code but now it's not working because on the JSONPlaceholder there are no array.
Any help for re-arrange the code for read and obtain the jsonplaceholder elements?
func loadList(){
let url = URL(string: urlReceived)
var myNews = NewInfo()
let task = URLSession.shared.dataTask(with: url!) {
(data, response, error) in
if error != nil{
print("ERROR")
}
else{
do {
if let content = data{
let myJson = try JSONSerialization.jsonObject(with: content, options: .mutableContainers)
//print(myJson)
if let jsonData = myJson as? [String : Any] {
if let myResults = jsonData["list"] as? [[String : Any]]{
//dump(myResults)
for value in myResults{
//Read time string from root
if let time = value ["dt_txt"] as? String{
myNews.time = time
}
//Read main container
if let main = value["main"]
as? [String : Any]{
if let temperature = main["temp"] as? Double {
myNews.temperature = String(temperature)
}
}
//Read from weather container
if let weather = value["weather"] as? [[String: Any]]{
for value in weather{
if let weatherContent = value["description"] as? String{
myNews.weatherDescription = weatherContent
}
}
}
self.myTableViewDataSource.append(myNews)
}
dump(self.myTableViewDataSource)
DispatchQueue.main.async {
self.tableView.reloadData()
}
}
}
}
}
catch{
}
}
}
task.resume()
}//End func
Okey, so with Alamofire + SwiftyJSON, you can do this:
func loadList(){
let url = "https://jsonplaceholder.typicode.com/photos"
AF.request(url).responseJSON { (response) in
switch response.result {
case .success(let value):
let json = JSON(value)
print(json)
for value in json.arrayValue {
let url = value.dictionaryValue["url"]!.stringValue
let albumId = value.dictionaryValue["albumId"]!.stringValue
let thumbnailUrl = value.dictionaryValue["thumbnailUrl"]!.stringValue
let id = value.dictionaryValue["id"]!.stringValue
let title = value.dictionaryValue["title"]!.stringValue
// Add this album to array.
let album = AlbumModel(id: id, albumId: albumId, title: title, thumbnailUrl: thumbnailUrl)
albums.append(album)
}
case .failure(let error):
print(error)
}
}
}
EDIT:
I made model for values
class AlbumModel {
var id: String?
var albumId: String?
var title: String?
var thumbnailUrl: String?
init(id: String?, albumId: String?, title: String?, thumbnailUrl: String?){
self.id = id
self.albumId = albumId
self.title = title
self.thumbnailUrl = thumbnailUrl
}
}
After that, just create an array like var albums = [AlbumModel]() and you can append all the albums to this. Easy to use after in tableViewcell (example: albums[indexPath.row].id)

parse json in UICollectionViewCell in swift

I want to parse JSON in UICollectionviewCell. I have a collectionViewController with two UICollectionviewCell. In collectionViewController first cell made to background scrolling and in the second I want to parse JSON. There is no error in the code, this is my JSON code.
var oCategoryFilter: CategoryFilter? {
didSet {
if let name = oCategoryFilter?.totalItem {
totalItemLabel.text = name
}
appsCollectionView.reloadData()
}
}
var arrProduct: [Product]?
func getPropductListByCategory(){
let category_id:String;
category_id = "21"
let url = URL(string: UtilityController.BASE_URL+"/products/"+category_id)
URLSession.shared.dataTask(with:url!) { (urlContent, response, error) in
if error != nil {
print(error)
}
else {
do {
let json = try JSONSerialization.jsonObject(with: urlContent!) as! [String:Any]
print(json)
let items = json["categories"] as? [[String: Any]] ?? []
items.forEach { item in
let oProduct = Product()
//oProduct.id = item["id"] as? String
oProduct.image = item["image"] as? String
oProduct.name = item["name"] as? String
oProduct.ar_name = item["ar_name"] as? String
//oProduct.description = item["description"] as? String
oProduct.ar_description = item["ar_description"] as? String
oProduct.price = item["price"] as? String
oProduct.quantity = item["quantity"] as? String
oProduct.is_featured = item["is_featured"] as? String
oProduct.seller_id = item["seller_id"] as? String
oProduct.payment_required = item["payment_required"] as? String
oProduct.is_editors_choice = item["is_editors_choice"] as? String
oProduct.created_at = item["created_at"] as? String
oProduct.updated_at = item["updated_at"] as? String
self.arrProduct?.append(oProduct)
}
print(url)
} catch let error as NSError {
print(error)
}
}
DispatchQueue.main.async(execute: {
self.appsCollectionView.reloadData()
})
}.resume()
}
When are you calling your functions ? You should call the method in the CollectionView, when it is loading every cell, but doing that is really bad, because each time you will scroll or reload your CollectionView it will parse again.
You should parse in a special class, call by the collection view and this last send the parse object to the cell.

swift: Alphabetiz data being parsed from a JSON

I wrote my own function in Swift2 to parse a JSON. Once the JSON is parsed, a list of data that was pulled from the JSON is displayed in a tableView on my app. I am trying to figure out how to display this data in alphabetical order. I think this needs to happen somewhere before the append method I call in the function. I would imagine this needs to be a sort function but I have not been able to figure out the correct sort function in Swift2 that will execute this properly. Any help I can get is appreciated!
Here is my parseJSON function:
func parseJSON(){
do{
let data = NSData(contentsOfURL: NSURL(string: "https://jsonblob.com/api/jsonBlob/580d0ccce4b0bcac9f837fbe")!)
let jsonResult = try NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers)
for anItem in jsonResult as! [Dictionary<String, AnyObject>]{
let mifiName2 = anItem["name"] as! String
let mifiId = anItem["employeeId"] as! Int
let newName = Name(mifiName: mifiName2, mifiId: mifiId)
nameOfMifi.append(newName)
//print("Name: \(newName)")
}
}
catch let error as NSError{
print(error.debugDescription)
}
}
You need to sort your array after all the object is append in Array means after the for loop.
for anItem in jsonResult as! [Dictionary<String, AnyObject>]{
let mifiName2 = anItem["name"] as! String
let mifiId = anItem["employeeId"] as! Int
let newName = Name(mifiName: mifiName2, mifiId: mifiId)
nameOfMifi.append(newName)
//print("Name: \(newName)")
}
//Now you need to sort your array on the basis of name like this
nameOfMifi.sortInPlace { $0.mifiName < $1.mifiName }
Edit: As #vadian suggested do not use NSData(contentsOfURL:) because it will block your UI, so batter to use NSURLSession like this.
let session = NSURLSession.sharedSession()
let url = NSURL(string: "https://jsonblob.com/api/jsonBlob/580d0ccce4b0bcac9f837fbe")!
var task = session.dataTaskWithURL(url, completionHandler: {
(data, response, error) -> Void in
if error != nil {
return
}
if let jsonResult = try? NSJSONSerialization.JSONObjectWithData(data!, options: NSJSONReadingOptions.MutableContainers) as? [Dictionary<String, AnyObject>] {
for anItem in jsonResult {
let mifiName2 = anItem["name"] as! String
let mifiId = anItem["employeeId"] as! Int
let newName = Name(mifiName: mifiName2, mifiId: mifiId)
nameOfMifi.append(newName)
//print("Name: \(newName)")
}
//Now you need to sort your array on the basis of name like this
nameOfMifi.sortInPlace { $0.mifiName < $1.mifiName }
//Now reload tableView on main thread.
dispatch_async(dispatch_get_main_queue()) {
self.tableView.reloadData()
}
}
})
task.resume()

Cannot instantiate function Could not cast value of type '__NSArrayI'

I have made the following function in Swift 3:
func parseJSON() {
var JsonResult: NSMutableArray = NSMutableArray()
do {
JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray
} catch let error as NSError {
print(error)
}
var jsonElement:NSDictionary=NSDictionary()
let locations: NSMutableArray = NSMutableArray()
for i in 0 ..< JsonResult.count
{
jsonElement = JsonResult[i] as! NSDictionary
let location = Parsexml()
if let title = jsonElement["Title"] as? String,
let body = jsonElement["Body"] as? String,
let userId = jsonElement["UserId"] as? Int,
let Id = jsonElement["Id"] as? Int
{
location.title = title
location.body = body
location.userId = userId
location.id = Id
}
locations.add(location)
}
DispatchQueue.main.async { () -> Void in
self.delegate.itemsDownloaded(items: locations)
}
When i call this function from another method, i get the following error:
Could not cast value of type '__NSArrayI' (0x105d4fc08) to 'NSMutableArray' (0x105d4fcd0).
It points me towards the element here:
JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSMutableArray
Where it exits with a SIGBRT..
What have i missed here?
You are trying to convert an NSArray into an NSMutable array which is what the warning is complaining about.
Take the array it provides you, and then convert it into a mutable one.
let jsonArray = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
jsonResult = jsonArray.mutableCopy() as! NSMutableArray
Unrelated, but you may also want to user a lower case value for the JsonResult to fit with normal iOS style guidelines. It should instead be jsonResult.
Another way to improve your code:
You are not mutating your JsonResult, so you have no need to declare it as NSMutableArray:
var JsonResult = NSArray()
do {
JsonResult = try JSONSerialization.jsonObject(with: self.data as Data, options:JSONSerialization.ReadingOptions.allowFragments) as! NSArray
} catch let error as NSError {
print(error)
}
And some steps to improve your code...
enum MyError: Error {
case NotArrayOfDict
}
func parseJSON() {
do {
guard let jsonResult = try JSONSerialization.jsonObject(with: self.data as Data) as? [[String: Any]] else {
throw MyError.NotArrayOfDict
}
let locations: NSMutableArray = NSMutableArray()
for jsonElement in jsonResult {
let location = Parsexml()
if let title = jsonElement["Title"] as? String,
let body = jsonElement["Body"] as? String,
let userId = jsonElement["UserId"] as? Int,
let Id = jsonElement["Id"] as? Int
{
location.title = title
location.body = body
location.userId = userId
location.id = Id
}
locations.add(location)
}
DispatchQueue.main.async { () -> Void in
self.delegate.itemsDownloaded(items: locations)
}
} catch let error {
print(error)
}
}
as! casting sometimes crashes your app, use it only when you are 100%-sure that the result is safely converted to the type. If you are not, using guard-let with as? is safer.
Use Swift types rather than NSSomething as far as you can.
Specifying .allowFragments is not needed, as you expect the result as an Array.
And if you can modify some other parts of your code, you can write your code as:
func parseJSON() {
do {
//If `self.data` was declared as `Data`, you would have no need to use `as Data`.
guard let jsonResult = try JSONSerialization.jsonObject(with: self.data) as? [[String: Any]] else {
throw MyError.NotArrayOfDict
}
var locations: [Parsexml] = [] //<-Use Swift Array
for jsonElement in jsonResult {
let location = Parsexml()
if let title = jsonElement["Title"] as? String,
let body = jsonElement["Body"] as? String,
let userId = jsonElement["UserId"] as? Int,
let Id = jsonElement["Id"] as? Int
{
location.title = title
location.body = body
location.userId = userId
location.id = Id
}
locations.append(location)
}
DispatchQueue.main.async { () -> Void in
self.delegate.itemsDownloaded(items: locations)
}
} catch let error {
print(error)
}
}

How to get all keys and values into separate String arrays from NSDictionary in Swift?

let urlAsString = "https://drive.google.com/uc?export=download&id=0B2bvUUCDODywWTV2Q2IwVjFaLW8"
let url = NSURL(string: urlAsString)!
let urlSession = NSURLSession.sharedSession()
let jsonQuery = urlSession.dataTaskWithURL(url, completionHandler: { data, response, error -> Void in
do {
if let jsonDate = data, let jsonResult = try NSJSONSerialization.JSONObjectWithData(jsonDate, options: []) as? NSDictionary {
print(jsonResult)
}
} catch let error as NSError {
print(error)
}
})
jsonQuery.resume()
Okay so here i am receiving data from online json then storing it as NSDictionary in jsonresult . I need to get all keys and values as into two separate arrays ?
Basically i want this
jsonresult.allkeys --> String array
jsonresult.allvalues --> String array
You can use:
let keys = jsonResult.flatMap(){ $0.0 as? String }
let values = jsonResult.flatMap(){ $0.1 }
It is quite simple because you are using jsonResult as NSDictionary.
let dict: NSDictionary = ["Key1" : "Value1", "Key2" : "Value2"]
let keys = dict.allKeys
let values = dict.allValues
In you're case
let keys:[String] = dict.allKeys as! [String]
var values:[String]
if let valuesSting = dict.allValues as? [String] {
values = valuesSting
}
For anyone trying it with newer version Swift please use compactMap()instead of flatMap()
let keys = jsonResult.compactMap(){ $0.0 as? String }
let values = jsonResult.compactMap(){ $0.1 }

Resources