Swift - extra argument 'count' in call? - swift

All I'm trying to do is to inverse key/values in a dictionary, and I get the following error:
extra argument 'count' in cal
var dictionary = SWIFT_DICTIONARY
var inverseDictionary = NSDictionary.dictionaryWithObjects(dictionary?.keys, forKeys: dictionary?.values, count: dictionary?.count)

Use this instead:
var inverseDictionary = NSDictionary(objects: dictionary.keys.array, forKeys: dictionary.values.array)
I notice that you are unwrapping dictionary in your code, but it is declared as non optional. Code mistake or just copy & paste mistake?
Addendum - if you try the static version without the count parameter:
var inverseDictionary = NSDictionary.dictionaryWithObjects(dictionary.keys.array, forKeys: dictionary.values.array)
the compiler complains with this message:
'dictionaryWithObjects(_:forKeys:) is unavailable: use object construction 'NSDictionary(objects:forKeys:)'
I think the same happens for the other method you want to use, but the compiler doesn't report the proper error message.

Related

How to pass a dictionary parameters with '&' to Objective-C method in Swift

I have a Objective-C library (and my project is Swift source).
I'm trying to use the library's methods.
there's a method like below
- (int)recognize:(NSDictionary **)dictionaryResult;
In ObjC, simply call it like
NSDictionary *resultDictionary = [[NSDictionary alloc] init];
nRet = [crControl recognize:&resultDictionary];
However in Swift, when I call the method like below, an error occurs
var dictionary = NSDictionary.init()
nRet = crControl.recognize(&dictionary)
==================
The error message:
Cannot convert value of type 'AutoreleasingUnsafeMutablePointer' to expected argument type 'AutoreleasingUnsafeMutablePointer<NSDictionary?>'
How can I pass a empty dictionary with '&' to ObjC methods in Swift?
The translation to swift seems to have translated the parameter type to:
AutoreleasingUnsafeMutablePointer<NSDictionary?>
Note that it's a pointer to an optional NSDictionary, so you should declare the argument as an optional too:
var dictionary: NSDictionary? = .init()

Swift Dictionary confusion

Say I have
var dict = parseJSON(getJSON(url)) // This results in an NSDictionary
Why is
let a = dict["list"]![1]! as NSDictionary
let b = a["temp"]!["min"]! as Float
allowed, and this:
let b = dict["list"]![1]!["temp"]!["min"]! as Float
results in an error:
Type 'String' does not conform to protocol 'NSCopying'
Please explain why this happens, note that I'm new to Swift and have no experience.
dict["list"]![1]! returns an object that is not known yet (AnyObject) and without the proper cast the compiler cannot know that the returned object is a dictionary
In your first example you properly cast the returned value to a dictionary and only then you can extract the value you expect.
To amend the answer from #giorashc: use explicit casting like
let b = (dict["list"]![1]! as NSDictionary)["temp"]!["min"]! as Float
But splitting it is better readable in those cases.

Access Class In A Dictionary - Swift

I am now writing a program involves class and dictionaries. I wonder how could I access a class's values inside a dictionary. For the code below how do I access the test1 value using the dictionary. I have tried using dict[1].test1but it doesn't work.
class test {
var tes1 = 1
}
var refer = test()
var dict = [1:refer]
There are a few problems with the line dict[1].test1:
Firstly, the subscript on a dictionary returns an optional type because there may not be a value for the key. Therefore you need to check a value exists for that key.
Secondly, in your class Test you've defined a variable tes1, but you're asking for test1 from your Dictionary. This was possibly just a type-o though.
To solve these problems you're code should look something like this:
if let referFromDictionary = dict[1] {
prinln(referFromDictionary.test1)
}
That's because the subscript returns an optional, so you have to unwrap it - and the most straightforward way is by using optional chaining:
dict[1]?.tes1
but you can also use optional binding:
if let test = dict[1] {
let value = test.tes1
}

Swift Compiler Error when accessing array - Exit code 254

I am quite new to swift and got a pretty weird compiler error:
Command
/Applications/Xcode6-Beta5.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/swiftc
failed with exit code 254
The Error occours when I ad the following lines to my code:
var response = HoopsClient.instance().collections["posts"]
response = response["_id"]
when I remove the second line everything compiles fine. I don't get it ^^
edit: The reason is probably that "response" is of type "AnyObject" according to the compiler... but shouldn't that be detected by xcode or give me a runtime error instead of this compiler error?
Try casting response as the type you're expecting. From what you're trying to do, instance().collections I would assume that it should return some type of dictionary.
var response = HoopsClient.instance().collections["posts"] as NSDictionary
That way, response now can handle subscripts so you could now (in theory) do:
response = response["_id"]
However
The error you get is regarding bad access to an array. This makes me think that instance().collections actually returns an array of some sort, containing Post objects.
Arrays in Swift can only handle Integer subscripts. If you want to access the information of a Post in the array, you can do something like this:
for post: Post in response {
println(post._id)
}
I know this is a long shot, but hope it helps.
Swift tends to throw error when it cant infer the type of an object, what you could probably do is add a conditional cast as follows
Im assuming that HoopsClient.instance().collections["posts"] is either a Dictionary or an Array
var response = HoopsClient.instance().collections["posts"]
if response is NSArray {
let item = response.objectAtIndex(0)
let reponseId: Post = item
}
if response is NSDictionary {
let item = response.objectForKet("_id")
let reponseId: Post = item
}
Any way, in my experience you should try to cast your variables when assigning from types that return AnyObject, xcode doesn't handle very well type inferring and when it's unable to infer the type the interface starts to throw error, like text editor uncoloring the code.

Having problems trying to call substringWithRange on a String optional

I'm trying to call substringWithRange on an option String but after multiple experiments am still not able to get it to compile:
var mdn:String?
var subscriber = CTSubscriber()
var carrierToken = subscriber.carrierToken
mdn = NSString(data:carrierToken, encoding:NSUTF8StringEncoding)
let range:NSRange = NSRange(location: 0, length: 10)
if mdn
{
let subString = mdn!.substringWithRange(range)
}
This will result in the compilation error saying the value of the optional NSString is not unwrapped.
I thought it already was unwrapped due to the !.
If I remove ! then I get an error saying String? does not have a member named substringWithRange.
Replace
var mdn:String?
with
var mdn:NSString?
You are using the var to store a NSString so you should give it the correct type. Although String and NSString are mutually assignable, it's not the same type.
String doesn't have the substringWithRange method.
I think this might actually be a compiler bug. I would report it to Apple and see how they come back.
However, the proper approach to unwrapping an optional for use if you need to gain some information from it. (Like obtaining a substring, in your example) is:
if let theMdn = mdn {
let subString = theMdn.substringWithRange(range)
}
That way your codeblock will only be executed if the unwrapping was successful.
Edit: Sulthan's answer might be more accurate. However I still think if you can unwrap the optional in a let block, you should be able to do it manually.