NSArray.init(array: [Any])
NSArray has an initial function whose parameter is [Any]. But not [Any?], so, how to add a nil value to this array?
NSArray/NSMutableArray don't allow you to store nil values in the array. This is why none of the Swift APIs allow optional values.
If you really need to something for nil, use NSNull() though I'm not 100% sure how that will work with Core Data.
And Swift actually does this for you. If you pass a Swift array of optionals, any nil values get converted to NSNull. Example:
var array = [Int?]()
array.append(4)
array.append(nil)
let nsa = array as NSArray
print(nsa) // (4, "<null>")
print(type(of: nsa[1])) // NSNull
Note that using let nsa = NSArray(array: array) instead of let nsa = array as NSArray worked without warning under Swift 4.0 but gives a warning as of Swift 4.1.
Related
group.issues = temp.sortedArray(using: [sortDescriptor]) as! NSMutableArray
The system version is iOS 11.0, Xcode 9.0.
How can we solve this?
Depending on what you're actually doing, you're probably better off using a mutable Swift array, declared as a var. However, if you really do need reference semantics for some reason, you can make an NSMutableArray like this:
group.issues = NSMutableArray(array: temp.sortedArray(using: [sortDescriptor]))
The reason you cannot just cast it is because the Objective-C bridge bridges a Swift array to an immutable NSArray, which would throw an exception if you tried to call the mutating methods on it.
Again, though, the best thing to do is just use a Swift array, by declaring the issues property as a var:
struct Group {
...
var issues: [String] // or whatever type goes inside the array
...
}
Then just assign it like:
group.issues = temp.sortedArray(using: [sortDescriptor])
Swift 5 Easy and simple way
let arrPicOne = temparrpicFind as! [Any]
let arrPicTwo = temparrpic as! [Any]
let picResult = arrPicOne + arrPicTwo
arrGpic = NSMutableArray(array:picResult)
I have below code in my project.
for (key, value) in photoDic {
if let url = URL.init(string: value as! String){
let photo : PhotoRecord = PhotoRecord.init(name:key as! String, url:url)
self.photoRecords.append(photo)
}
}
My question is how can I make key and value in for loop optional, or check if either of them are nil?
I am not able to check if they are nil, getting warning saying any cannot be nil because it is nonoptional.
I was thinking of using something like
for(key:String?, value:String?){}
But it is not working.
The key in a dictionary can't be an optional. (The key must conform to the Hashable protocol, and optionals don't.) So you CAN'T make the keys in your dictionary optional
If you want the values of your dictionary to be Optionals then you need to declare them as Optionals.
So, for example, change
let photoDic: [String: String] = ["key1": "http://www.someDomain.com/image.jpg"]
to
let photoDic: [String: String?] = ["key1": "http://www.someDomain.com/image.jpg"]
(Note that the type of photoDic is changed to [String: String?].)
As mentioned already all keys in a dictionary are non-optional by definition.
Further in NSDictionary all values are non-optional by definition, too.
Be happy about that because
There is no need to check for nil.
The code will never crash.
A Swift dictionary can theoretically contain optional values but practically you are discouraged from using it. For compatibility reasons to NSDictionary a nil value indicates key is missing.
This code which ran perfectly in Xcode 7.0 now complains with a error : Ambiguous use of a subscript in Xcode 7.3.1 on the second line.
let ar = sender.draggingPasteboard().propertyListForType("ABLinkedPeopleUIDsPboardType") as! NSArray?
let uniqueID = ar![0][0] as! String
I understand that the NSArray on its own is now considered bad practice, but what do I need to do to get this to compile and run?
NSArray is a single-dimensioned array, but you're trying to use it as a two-dimensional array. I can't see how this would ever compile.
You need to translate into Swift types immediately so you can continue programming in Swift, not go adrift in a sea of force-unwrapped Optionals.
How about:
if let ar = sender.draggingPasteboard().propertyListForType("ABLinkedPeopleUIDsPboardType") as? [[String]] {
// I'm assuming you're expecting to get back a two-dimensional array of Strings, or in the Obj-C realm, an NSArray of NSArrays of NSStrings
let uniqueID = ar[0][0]
}
else {
print("Property List for ABLinkedetc. is not a 2D String Array!")
}
Hayden's link is the correct general discussion but if you're new to bridging Obj C to Swift it may be difficult to apply in your particular case.
I'm trying to save a dictionary to NSUserDefaults using the setObject() function but when I use the objectForKey() function to retrieve the dictionary it returns nil. Why is this happening?
var data = NSUserDefaults.standardUserDefaults();
var scoreboard = [Int : String]()
let scores = "scoresKey"
scoreboard[3] = "spencer"
scoreboard[6] = "brooke"
scoreboard[11] = "jason"
data.setObject(scoreboard, forKey: scores)
data.objectForKey(scores) // Returns nil
The first problem was that it's not possible to use NSUserDefaults in a Playground.
See: https://stackoverflow.com/a/31210205/3498950
A second problem is found when the code above runs in a normal iOS project. It throws an NSInvalidArgumentException since the dictionary was a non-property list object because the keys needed to be of type String.
Although NSDictionary and CFDictionary objects allow their keys to be
objects of any type, if the keys are not string objects, the
collections are not property-list objects.
See: "What is a Property List?" in the Apple Docs
I have been porting some objective-c code over into swift and I am trying to get the result set as a dictionary and then pack each dictionary (equivalent to a row from the db) into an array. But I am getting this error message "Dictionary cannot be bridged from Objective-C". I have read this from apple but still I am no further along towards a solution. Any ideas? Thanks.
This is the line where the error is:
resultsArray.append(resultSet!.resultDictionary() as Dictionary<String,String>)
From the awesome robertmryan reposted here for convenience:
This will happen if your database has an null values (which return [NSNull null] objects) or numeric values (which return NSNumber objects). You can fix this by defining resultsArray as:
var resultsArray = Array<Dictionary<String,AnyObject>>()
Or, I personally prefer:
var resultsArray = [[String: AnyObject]]()
And then when adding objects, I'd
resultsArray.append(resultSet!.resultDictionary() as Dictionary<String, AnyObject>)
or
resultsArray.append(resultSet!.resultDictionary() as [String: AnyObject])