Why accessing this json sub elements by index raises this error? - arrays

this is the part of the json
"feature_id" = (
3047,
3084,
3095,
3100,
3121,
3124,
3182,
3272,
3273,
3274
);
this is how I access json, I use Alamofire.
var features_id = self.jsonD["results"]!["place_basic_info"]!!["feature_id"]!!
now the problem is in here
features_id[0] as? String
the error raised is :
ambiguous use of 'subscript'
the weird thing is this shows up when I try to build for the device, but not when running, how to solve this problem ? and why it shows up?

ambiguous use of 'subscript'
The issue is that the compiler doesn't know that features_id is an array, so it is unable to subscript it by index.
You have to give the object's type to the compiler, for example with optional binding and casting:
if let featID = features_id as? [Int] {
// here featID is features_id unwrapped as an array of Ints
}

Related

Cannot convert value of type '[UITableViewCell.Type]' to '[_.Type]' in Swift 4.2

Well, today after I update Xcode to version 10.0, I faced following error in my code.
// error: Cannot convert value of type '[UITableViewCell.Type]' to expected argument type
// '[_.Type]'
table.registerCells(cells: [MainMenuTableViewCell.self,
RescueServicesTableViewCell.self])
Here is the registerCells function:
func registerCells<T> (cells : [T.Type]) where T: UITableViewCell {
for cell in cells {
let nib = UINib(nibName: String(describing: cell), bundle: nil)
register(nib, forCellReuseIdentifier: String(describing: cell))
}
}
At the beginning I thought it might be swift re-versioning issue so I convert from swift 3 to swift 4 and after 2 hours spending time to fix syntaxes the error was still there, until I did the magic trick.
let cellItems = [MainMenuTableViewCell.self,
RescueServicesTableViewCell.self]
table.registerCells(cells:cellItems)
This solution works and error gone. Now my question is why I'm getting this error is this Xcode problem or I did something wrong?
This is an interesting bug (SR-8825) where the compiler appears to be unable to perform type joining (the process of inferring a common supertype for a collection of types) within a member access on an implicitly unwrapped optional (IUO) declaration (presumably in your case table is an IUO #IBOutlet).
A minimal example would be:
class C {}
class D : C {}
class E : C {}
struct X {
func foo<T>(_: [T.Type]) where T : C {}
}
var x: X!
// error: Cannot convert value of type '[C.Type]' to expected argument type '[_.Type]'
x.foo([D.self, E.self])
Making x either non-optional, or a strong optional (i.e X?) while performing either optional chaining (i.e x?.foo) or force unwrapping (i.e x!.foo) to perform the member access allows the code to compile.
There are a few workarounds you can use, first of which is to explicitly specify the array type, saving the compiler from having to infer the type join:
x.foo([D.self, E.self] as [C.Type])
In your case, this translates to:
table.registerCells(cells:
[MainMenuTableViewCell.self, RescueServicesTableViewCell.self] as [UITableViewCell.Type]
)
Second workaround is to use a non-optional base. In your case, you can force unwrap the IUO into a local variable before performing the member access:
// this is just explicitly doing what the compiler would have otherwise done implicitly.
let table = self.table!
table.registerCells(cells: [MainMenuTableViewCell.self, RescueServicesTableViewCell.self])
Third workaround is, as you've already discovered, to separate out the array into its own expression – which allows the compiler to do the type joining on its own:
let cellItems = [MainMenuTableViewCell.self, RescueServicesTableViewCell.self]
table.registerCells(cells: cellItems)
Though the solution I would go with in your case is to make registerCells(cells:) non-generic, as it doesn't appear that you're using the generic placeholder T for anything useful:
extension UITableView {
func registerCells(_ cells: [UITableViewCell.Type]) {
for cell in cells {
let nib = UINib(nibName: String(describing: cell), bundle: nil)
register(nib, forCellReuseIdentifier: String(describing: cell))
}
}
}
Which you can now just call like so:
table.registerCells([MainMenuTableViewCell.self, RescueServicesTableViewCell.self])
tableView.dequeueReusableCell(withIdentifier: String(describing: YoursCell.self), for: indexPath)

Swift 3: Dictionary from large arrays

I am working with two large arrays containing following data:
print(dataID[1]) // ["DataID123"]
print(dataAR[1]) // ["73.075584"]
I'd like to form a dictionary from the two arrays by:
var arrayofDict = [String: AnyObject?]()
for i in 0...csvDataID.count {
if i < csvDataID.count {
let key = csvDataID[i]
let value = csvDataAG[i]
arrayofDict[key] = value
}
}
But get following error:
Cannot subscript a value to '[String: AnyObject?]' with an index of
type '[String]'
I also tried a few other approaches aswell resulting in the same error.
Could anyone help me and is there even a more efficient way to handle the arrays?
Thanks!
let key = csvDataID[i][0]
let value = csvDataAG[i][0]
Explaination:
The log says that csvDataID[1] is an array: ["DataID123"]
The same is for the second one.:["73.075584"]
So,
let key = csvDataID[i] // you set the key is array.
That's why you can see this error.

Convert [String]? to String in Swift

For my project, I extracted tweets from a CSV file in Swift. Problem is now all tweets are parsed as one element in an array, separated by ",".
let tweetsOfColumns = columns["tweet"]
let seperatedColumns = tweetsOfColumns.componentsSeparatedByString(",")
Error message: '[String]?' does not have a member named
'componentsSeparatedByString'.
I checked if tweetsOfColumns contains multiple elements, but it doesn't allow me to subscript with tweetsOfColumns[index].
Looking at the link you reference, columns["tweets"] is going to give you back an array of the values from the "tweets" column, so it's what you need already, there's no additional comma's to split things on, you just need:
let seperatedColumns = columns["tweet"]
to have an array containing the tweet column for each row.
When you try to get an element from a dictionary, like
columns["tweet"]
it will give you back an optional, because if there is nothing associated with the key, it gives you back nil (None), otherwise the value wrapped in an optional (Some(data)).
So you have to unwrap the optional for example:
columns["tweet"]!
You have to either use the optional ? to access the string:
let seperatedColumns = tweetsOfColumns?.componentsSeparatedByString(",")
But you should unwrap it:
if let unwrappedTweets = tweetsOfColumns?.componentsSeparatedByString(","){
let seperatedColumns = unwrappedTweets
}
The problem is probably that you'll get an optional back, which you have to unwrap. And the easiest and most elegant is to use the if-let unwrapper.
if let tweetsOfColumns = columns["tweet"] {
let seperatedColumns = tweetsOfColumns.componentsSeparatedByString(",")
// do something with the seperatedColumns
}
Based on David's question and the OP's response in the OP comments, you can use map on the Array returned by columns["tweet"]. Please post actual data/code in the future.
let columns = [
"tweet":["handleX,tag1,tag2,textA,textB",
"handleY,tag1,tag2,textC,textD"]]
var chunk = [[String]]()
if columns["tweet"] != nil {
chunk = columns["tweet"]!.map {
return $0.componentsSeparatedByString(",")
}
}

Convert Parse.com json array into Array with swift

Can someone please help me with this. I saved my data into Parse.com into column with type array (example: ["11:30","12:45,"13:02"], just some list of some times as string). I have tried to get this data with swift:
var take: NSMutableArray!
var query = PFQuery(className: "test")
query.getObjectInBackgroundWithId("QZ6Y8Oljc5"){
(testData: PFObject!, error: NSError!) -> Void in
if (error == nil){
take = testData["workday"]
println(take)
}
else{
println(error)
}
}
the problem is that i get only json array type:
(
"11:30",
"12:45,
"13:02"
)
How can I convert it into NSArray so it could be like:
var myArray = ["11:30","12:45,"13:02"]
Thank you for any suggestions because I tried every method I found here, but without any results.
The problem with JSON data is that it is it's own array that has to be sifted and groomed. normally people would end up using huge nested IF statements which ends up looking messy. Luckily, someone created a code that sifts through JSON data and gives you back usable types (Int, Arrays, Strings) by use of a massive switch table.
https://github.com/SwiftyJSON/SwiftyJSON
Look it up, it should help. Once you have it implemented you can call it by typing..
let json = JSON(Data : JSONData)
then to sift through, you use substrings.. (depending on the data, you match it with a string or int)
let firstIndex = json["workday"]
//Int
let firstIndexOfWorkDay = json["workday"][0]
//String
let firstIndexOfWorkDay = json["workday"]["time"]
and so on... however, you will need to cast it once you singled out the data
let firstIndexOfWorkDay = json["workday"][0].valueOfFloat
//printing it would give 11:30
although personally I use ".description" .. since sometimes when I sift through all the array, its a mix of types.
let firstIndexOfWorkDay = json["workday"][0].description
println(firstIndexOfWorkDay)
//would literally give "11:30" including the quotation marks
then I use string methods to trim the quotations then cast it to whatever type I need. But it's up to your creativity once you figure out how it works

swift setting string from array element error

So im grabbing a property from core data, using a dictionary. And it grabs it just fine. However, when I try to take that single returned attribute and assign it to the navigationitem.title it throws some nasty error. Am I missing something here..
Its not actually outputting an error message in the console but instead is giving me this:
Thread 1: EXC_BREAKPOINT(code+exc_I386_BPT.....
on this line.
0x10707a5f3: nopw %cs:(%rax,%rax)
Also its saying
0 swift_dynamicCastObjCClassUnconditional
code:
override func viewDidLoad() {
super.viewDidLoad()
let appDel:AppDelegate = UIApplication.sharedApplication().delegate as AppDelegate
let context:NSManagedObjectContext = appDel.managedObjectContext
let frequest = NSFetchRequest(entityName: "Round")
frequest.propertiesToFetch = NSArray(object: "course")
frequest.returnsObjectsAsFaults = false
frequest.returnsDistinctResults = true
frequest.resultType = NSFetchRequestResultType.DictionaryResultType
var fetchedArray = context.executeFetchRequest(frequest, error: nil)
//this is the line that throw the error...why won't it let me set the title to the array of the single returned result?
self.navigationItem.title = fetchedArray[0]
println(fetchedArray)
}
Without a specific error message you are receiving, this is just a guess...
NSArray un untyped contents (that is to say that elements are of type AnyObject), so the compiler probably doesn't think you can set AyObject as a string. So likely need something like:
self.navigationItem.title = fetchedArray[0] as String
Or:
self.navigationItem.title = String(fetchedArray[0])
To start, I would check couple of things to see if the problem is in the fetched array or in the navigation item:
what exactly is returned in fetchedArray[0]? Is is a string? A nil? Something else? Does it actually have anything at index 0? After checking if fetchedArray is not nil and has any elements, you could use "\(fetchedArray[0])"
What is the state of navigationItem? Is it actually instantiated at the time you are trying to set it's title property? I would suggest checking it for nil. You can also try assigning it a string like this: self.navigationItem.title = "Hello" and see if it fails.

Resources