Error: Deployment Update target 8.3 NSMutableArray and addObjectsFromArray - swift - ios

After updating the xcode and my device some functions are not running anymore.
see It:
var jsonUnico: NSMutableArray! = jsonResult["lista"] as? NSMutableArray
self.tableList.addObjectsFromArray(jsonUnico)
Error: Cannot invoke 'addObjectsFromArray' with an argument list of type '(NSMutableArray!)'
It was working yesterday before upgrading
note: the tablelist is an NSMutableArray

Swift 1.2 no longer implicitly converts between NSArray and Swift’s native array type – you need to explicitly cast from one to the other. Since addObjectsFromArray takes a Swift array, that means you need to convert it to [AnyObject].
Normally you’d get a more helpful error message: error: 'NSMutableArray' is not implicitly convertible to '[AnyObject]'; did you mean to use 'as' to explicitly convert?, with a offer to “fix-it”. But it looks like this isn’t happening because of your use of implicitly-unwrapped optional NSMutableArray!.
But… this isn’t such a bad thing, since using implicitly-unwrapped optionals like that when fetching values out of dictionaries is dangerous (if the entry is ever not there, your app will crash). An alternative is:
if let jsonUnico = jsonResult["lista"] as? NSMutableArray {
let tableList = NSMutableArray()
// Xcode will recommend adding the "as [AnyObject]"
tableList.addObjectsFromArray(jsonUnico as [AnyObject])
}
But since you’re already doing an as above it, you may as well combine them:
if let jsonUnico = jsonResult["lista"] as? [AnyObject] {
tableList.addObjectsFromArray(jsonUnico)
}

Related

Adding Swift closure object to NSMutableArray and then removing it doesn't work - LEAK

I have some Swift code that interoperates with Objective C, and I noticed I'm leaking, I narrowed it down to NSMutableArray not removing my closure, here's a pure Swift snippet that reproduces the problem:
let myClosure : ((String?) -> ())! = { (fileName: String?) in
}
let arr = NSMutableArray()
arr.add(myClosure)
arr.remove(myClosure)
Did anyone encounter this -- why does this happen? and how can I get it to work?
The closure doesn't have the reference so the array is unable to compare for removing your closure object that's why this will not remove from the array.
Your code
let arr1 = NSMutableArray()
arr1.add(myClosure)
print(arr1) //("(Function)")
arr1.remove(myClosure)
print(arr1) //("(Function)")
Solution
var arr = Array<Any>()
arr.append(myClosure)
print(arr) //[(Function)]
arr.remove(at: 0)
print(arr) //[]
This will remove by index so you have to use the index for removing the element instead of closure instance also I recommend you to use pure swift classes in Swift.
To re-emphasize, our codebase uses Swift that interops with ObjC, therefore, in my case its not possible to go pure Swift trivially.
I changed our API to use an NSDictionary that maps from NSUInteger handle to the closure and that integer is then used for removal of the closure from the dictionary.
The purpose of that API is to register listener callbacks and have a facility to unregister them. So that NSUInteger handle satisfies the removal bit.

Intricate access to dictionary key

From a server I receive a JSON string, then I try to convert it to an NSDictionary this way:
let JSON = try NSJSONSerialization.JSONObjectWithData(rToData!, options:[])
guard let JSONDictionary:NSDictionary = (JSON as! NSDictionary) else {
print("My grandma is way more NSDictionary than this")
return
}
Once converted, I try to get some data contained in the dictionary: in particular I need an array I can access this way:
let myArray = JSONDictionary["data1"][0]["data2"];
XCode really doesn't like this idea, it puts an arrow under the first bracket and says Value of optional type "AnyObject?" not unwrapped, did you mean to use "!" or "?" ?. I follow its suggestion and I insert a "!", converting my preceding code to this:
let myArray = JSONDictionary["data1"]![0]["data2"];
At this point, the following line (where I count the number of elements in data2) shows an error, stating AnyObject has no member count.
The only thing that seems to work fine is this solution but, apart from being ugly and unreadable, I really don't understand it:
let myArray = (JSONDictionary["data1"]?[0]["data2"])!;
Can you help me understand why this basic access to a key in a dictionary must be so intricate?
I must say I like Swift but I spend a lot of time dealing with optionals and bizarre XCode alerts.
There is no guarantee that your JSON dictionary will contain a value for the key data1 (OK, you know it will, but Swift doesn't) so JSONDictionary["data1"] returns an optional. You need to unwrap the optional with ? or !
Also, since you have an NSDictionary, not a Swift dictionary, Swift doesn't know the type of the values, so they are AnyObject. Now again, you know it is an array, but Swift doesn't so you get an error stating that AnyObject doesn't have a count method.
While it is more verbose, it is cleaer for both the compiler and anyone else looking at your code if you split the line into multiple lines. It also lets you downcast the various objects so that Swift knows what is going on and handle any malformed JSON;
if let array1 = JSONDictionary["data1"] as? NSArray {
if let dictionary1 = array1[0] as? NSDictionary {
if let data2Array = dictionary1["data2"] as? NSArray {
let count=data2Array.count
}
}
}
You could implement appropriate else statements to handle errors
Optionals are one of Swift's most powerful features. They help avoid a whole family of bugs associated with uninitialised variables and special sentinnel values for boundary conditions. It is important that you learn how they can help you and not just throw ? or ! at your code until it compiles.

Swift 2.2 breaks optionals/unwrapping optionals

Swift 2.2 has broken almost all my code. Even this simple string assigning to label doesn't work anymore:
cell.categoryName.text = peopleArray![indexPath.row]["Name"] as? String
The error says "Downcast from 'String?!' to 'String' only unwraps optionals, did you mean to use '!!'?"
What changes do I have to do now.
EDIT:
More Problems:
if (dict["data"]!["DataDetails"] as! NSArray).count == 0 {
}
Due to this I am getting a segmentation fault and the error shows this: warning: cast from 'String?!' to unrelated type 'NSArray' always fails
UPDATE:
I was using NSDictionaries, NSArrays in my classes that seems to cause the problem. Changing all the literals from Obj-C to swift made the code work properly.
So, I will also recommend other developers to prefer swift literals.
it seems there are some slight differences when using the swift types and the objective-c NS... types
eg
let dic:NSDictionary? = ["a":"a"]
let str:NSString? = dic!["a"] as? NSString
let dic2:Dictionary? = ["b":"b"]
let str2:String? = dic2!["b"] //dont need to do any casting, already optional
print(str)
print(str2)
prints
Optional(a)
Optional("b")
so depending on how your array / dictionary is defined, you might need different casting/unwrapping

Cast from 'MDLMaterialProperty?!'?

I'm working with the parse framework for an App that I'm converting to Xcode 7. One of the interesting errors which has occurred as part of migrating the project is the following:
Cast from 'MDLMaterialProperty?!' to unrelated type 'PFUser' always fails
The offending line seems to be the "if let" clause below. I've commented the old line which worked fine in the previous version of Swift for comparison.
With respect to what this is actually doing - I've passed an array of Parse objects into "likesForThankful" where a pointer "userID" refers to a related PFUser. As part of this method I'm writing individual PFUsers to an array.
Any help is appreciated - thanks in advance.
//Add PFUsers who Like Post to our FeedItem
private func callbackFromLikesProcessing(likesForThankful:[AnyObject], againstFeedItem:FeedItem){
//Instantiate our Objective C compatible array for processing later
againstFeedItem.parseUsersObjectsWhoLikePost = NSMutableArray()
//Loop through likes and add PFUsers to array of users who like post
for usersWhoLikePost in likesForThankful{
// if let parseUserWhoLikesPost = usersWhoLikePost["userID"] as PFUser{
if let parseUserWhoLikesPost = usersWhoLikePost["userID"] as? PFUser {
againstFeedItem.parseUsersObjectsWhoLikePost.addObject(parseUserWhoLikesPost)
}
}
Andrew
Figured this out if it can help anyone - it's basic Swift Syntax (though I'm not sure why the compiler let me get away with this in the first version of Swift!).
Because usersWhoLikePost is a PFObject which happens to contain a pointer to a PFUser object I needed to conditionally unwrap this first like so:
for usersWhoLikePost in likesForThankful{
if let parseLikeObject = usersWhoLikePost as? PFObject{
if let parseUserWhoLikesPost = parseLikeObject["userID"] as? PFUser {
againstFeedItem.parseUsersObjectsWhoLikePost.addObject(parseUserWhoLikesPost)
}
}
}
After this I could continue as I had previously done and access the "userID" property with a conditional unwrap of the PFUser object.

Swift: Cast from 'Ride' to unrelated type 'NSDictionary' always fails

I'm building my first iOS app using Swift 2.0 and I'm running in to the following error:
Cast from 'Ride' to unrelated type 'NSDictionary' always fails
at this line:
if let rowData: NSDictionary = ride as? NSDictionary,
Just below my class declaration I'm declaring rides like this:
var rides = [Ride]()
And above the error line I have added this:
let ride = self.rides[indexPath.row]
Screenshot:
And my Ride class:
Can someone tell me what I'm doing wrong and how to fix this?
struct Ride is not a subtype of NSDictionary. They are completely different concept.
Therefore, the casting if let rowData: NSDictionary = ride as? NSDictionary always fails.
Since rides's type is [Ride], let ride = rides[indexPath.row]'s type is Ride.
No optional unwrapping is required. Use the properties(name, state, ...) directly.
So, I think the code should be something like this.
let ride = rides[indexPath.row]
dataFull = ride.name
dataState = ride.state
dataUrlString = ride.image
...
just cast to the proper type : Ride
if let rowData = ride as? Ride,
but as the datasource is defined as Ride anyway this check is not needed at all
Edit:
The properties of Ride are all declared as non optional types, so you never have to check for nil. That's a huge benefit of the Swift language

Resources