swift empty dictionary bug? playground vs project - dictionary

this code work in playground
var detaildata:Dictionary=[:]
detaildata = ["apple":"hello"]
detaildata["orange"]="byebye"
this code don't work in project
class ViewController: UIViewController{
var detaildata:Dictionary=[:]
override func viewDidLoad() {
super.viewDidLoad()
detaildata = ["apple":"hello"]
detaildata["orange"]="byebye" // Error -> 'Dictionary' is not identical to 'Dictionary<key,Value>'
}
}
do you know why?
I think same code.

That code doesn't work in my playground, and shouldn't work in yours. When you declare a Dictionary, you need to give it both key and value types either explicitly or through type inference. All of these will work:
var dict1 = ["apple": "hello"] // inferred
var dict2: [String: String] = [:] // explicit
var dict3: Dictionary<String, String> = ["apple": "hello"] // longest version
Neither of these will work:
var dict3: Dictionary = [:] // type inference impossible
var dict4 = [:] // same

Related

How to convert/transform a collection to another collection by element's property?

If I have a collection of an object in Kotlin, is there a quick way to get a collection of a certain property of those objects? I looked at a list of collection operations for Kotlin, but nothing stood out for me (but I may have overlooked something)
In python it would be akin to:
[person.name for person in persons]
And I'd prefer to use a collections function instead of doing:
var nameMap = mutableListOf<String>()
persons.forEach{person -> nameMap.add(person.name)}
I'm pretty lacking in knowledge of filtering/lambda functions and anything other than list comprehension, so apologies if this is a simple question
it's easy to do in Kotlin:
// v--- the variable type can be removed
var nameMap: MutableList<String> = persons.map { it.name }.toMutableList();
IF you want an immutable List, it can simplify as below:
// v--- the variable type can be removed
var nameMap: List<String> = persons.map { it.name };
OR using function reference expression instead:
var nameMap = persons.map(Person::name);
If you want to map model then do this.
var nameMap: List<Model> = persons.map { Model(it.name,it.number) };
Option 1:
inline fun <reified T, Y> MutableList<T>.listOfField(property: KMutableProperty1<T, Y?>): MutableList<Y> {
val yy = ArrayList<Y>()
this.forEach { t: T ->
yy.add(property.get(t) as Y)
}
return yy
}
Usage:
val serviceIds = services.listOfField(ServiceModel::id)
Option 2:
var serviceIds: MutableList<String> = services.map { it.id }.toMutableList()
Option 3:
Function Reference
var serviceIds = services.map(Person::id)

Swift - Store Closures in Dictionary

Is it possible to store closures in dictionaries (how we could store ObjC blocks in dictionaries)? Example:
data = [String:AnyObject]()
data!["so:c0.onSelection"] = {() in
Debug.log(.Debug, message: "Hello, World!")
}
You can, but with some restrictions. First of all, function types don't inherit from AnyObject and don't share a common base class. You can have a dictionary [String: () -> Void] and [String: (String) -> Int], but they can't be stored in the same dictionary.
I also had to use a typealias to define the dictionary so that swift would parse correctly. Here's an example based off of your snippet.
typealias myClosure = () -> Void
var data: [String: myClosure]? = [String: myClosure]()
data!["so:c0.onSelection"] = {() -> Void in
Debug.log(.Debug, message: "Hello, World!")
}
I have a different approach
I create a "holder" class to hold your closures something like this:
typealias SocialDownloadImageClosure = (image : UIImage?, error: NSError?) -> ()
typealias SocialDownloadInformationClosure = (userInfo : NSDictionary?, error: NSError?) -> ()
private class ClosureHolder
{
let imageClosure:SocialDownloadImageClosure?
let infoClosure:SocialDownloadInformationClosure?
init(infoClosure:SocialDownloadInformationClosure)
{
self.infoClosure = infoClosure
}
init(imageClosure:SocialDownloadImageClosure)
{
self.imageClosure = imageClosure
}
}
then i make the dictionary like this:
var requests = Dictionary<String,ClosureHolder>()
Now to add a closure to the dictionary just do this:
self.requests["so:c0.onSelection"] = ClosureHolder(completionHandler)
Connor is correct, I did try many ways to store variables and closures in the same dictionary, but I failed and couldn't parse it out, the swift decompiler will throw the error:
"Command failed due to signal: Segmentation fault: 11" (the hell is it?!)
For example:
//This won't work
var params:[String: Any] = ["x":100, "onFoundX": {println("I found X!")}]
if var onFoundX: (()->Void) = params["onFoundX"] as? (()->Void) {
onFoundX()
}
//This should work by separate into 2 dictionaries and declare the "typealias" obviously
var params:[String: Any] = ["x":"100"}]
var events:[String: (()->Void)] = ["onFoundX": {println("I found X!")]
if var onFoundX: (()->Void) = events["onFoundX"] as? (()->Void) {
onFoundX() // "I found X!"
}
if var x = events["x"] as? String {
println(x) // 100
}
I hope Swift will allow this to happen in the future..
Cheers!
This simple example helped me understand a bit more:
//Init dictionary with types (i.e. String type for key, Closure type for value):
var myDictionary: [String: ()->(String)] = [:]
//Make a closure that matches the closure signature above and assign to variable (i.e. no parameter and returns a String):
let sayHello: () -> (String) = {
return "Hello!"
}
//Add closure to dictionary with key:
myDictionary["myFunc"] = sayHello
//Access closure by known key and call it:
myDictionary["myFunc"]!() //"Hello!"

Adding entries to Dictionary (not NSDictionary) from Info.plist

In the following OS X application, how can I create a Dictionary in a similar way to how I create an NSDictionary?
I suppose I need to find a method on Dictionary that performs the same task as NSDictionary(contentsOfFile:infoPlist) but I am not sure what this Dictionary method is.
import Cocoa
class AppDelegate: NSObject, NSApplicationDelegate {
#IBOutlet weak var window: NSWindow!
func applicationDidFinishLaunching(aNotification: NSNotification?) {
var infoPlist = "/Applications/Calendar.app/Contents/Info.plist"
var nsDictionary = NSDictionary(contentsOfFile:infoPlist)
println("nsDictionary = \(nsDictionary)")
var dictionary = Dictionary<String, String>()
// TODO: How do I add entries from "infoPlist" to "dictionary"
// like I do above with the old "nsDictionary"?
println("dictionary = \(dictionary)")
}
func applicationWillTerminate(aNotification: NSNotification?) {
}
}
Many thanks in advance.
Sadly there is no way to do this in native swift dictionaries at the moment. However using NSDictionary is still quite fine.
For more info you can look at this similar question

How to access a Dictionary passed via NSNotification, using Swift

I have code that sends a notification (where serialNumber is a String):
var dataDict = Dictionary<String, String>()
dataDict["Identity"] = serialNumber
dataDict["Direction"] = "Add"
NSNotificationCenter.defaultCenter().postNotificationName("deviceActivity", object:self, userInfo:dataDict)
And code that receives this notification:
func deviceActivity(notification: NSNotification) {
// This method is invoked when the notification is sent
// The problem is in how to access the Dictionary and pull out the entries
}
I've tried a variety of code to accomplish this, with no success:
let dict = notification.userInfo
let dict: Dictionary<String, String> = notification.userInfo
let dict: Dictionary = notification.userInfo as Dictionary
And while some of my attempts satisfy the compiler, none have yielded actual Strings when trying to access what has been extracted as a Dictionary:
let sn : String = dict["Identity"]!
let sn : String = dict.valueForKey("Identity") as String
let sn : String = dict.valueForKey("Identity")
So the question is this: How do I write Swift code to extract an object, in this case a Dictionary, that was passed via a notification, and access the component parts of that object (in this case the keys and values)?
As notification.userInfo type is AnyObject ayou must downcast it to appropriate dictionary type.
After exact type of dictionary is known you don't need to downcast values you get from it. But you may want to check if values are actually present in dictionary before using them:
// First try to cast user info to expected type
if let info = notification.userInfo as? Dictionary<String,String> {
// Check if value present before using it
if let s = info["Direction"] {
print(s)
}
else {
print("no value for key\n")
}
}
else {
print("wrong userInfo type")
}
You should use structure like [NSObject : AnyObject] and retrieve value as from NSDictionary yourLet[key]
func keyboardWillShown(notification : NSNotification){
let tmp : [NSObject : AnyObject] = notification.userInfo!
let duration : NSNumber = tmp[UIKeyboardAnimationDurationUserInfoKey] as NSNumber
let scalarDuration : Double = duration.doubleValue
}

I cannot undetstand how works "isSubtypeOf" in Dart mirrors

According to this test, I can not invoke the method "method" with an argument "list" because argument type is not compatible with the type of the method parameter.
Where I am wrong in my test?
import "dart:mirrors";
void main() {
var list = new List<String>();
var listMirror = reflectClass(list.runtimeType);
// Is "List<String>" subtype of "List<String>"?
print(listMirror.isSubtypeOf(listMirror));
// Method with parameter "List<String>"
var method = (List<String> list) {};
var closure = reflect(method) as ClosureMirror;
var function = closure.function;
var parameter = function.parameters.first;
// Is "List<String>" subtype of "List<String>"?
print(parameter.type.isSubtypeOf(listMirror));
print(listMirror.isSubtypeOf(parameter.type));
// Invoke method with arg: "List<String>" on param "List<String>"
method(list);
}
Output:
true
false
false
P.S.
Maybe I not understand something but it still not works.
import "dart:mirrors";
void main() {
var stringMirror = reflectClass(String);
// Query "List<int> get codeUnits"
MethodMirror method = stringMirror.declarations.values
.where((e) => e.simpleName == #codeUnits).first;
// List<int>
var returnType = method.returnType;
print(returnType);
// List
var baseType = reflectClass(List);
print(baseType);
// List<int> is List
print(returnType.isSubtypeOf(baseType));
}
Output:
ClassMirror on 'List'
ClassMirror on 'List'
false
This line is the culprit:
var listMirror = reflectClass(list.runtimeType);
it returns
ClassMirror on '_GrowableList'
if you use
var listMirror = reflectType(List);
it should work.
What you can when you need to get the type from a value at runtime
var listMirror = reflect(list).type.superinterfaces;
...
listMirror.forEach((e) => print(parameter.type.isSubtypeOf(e)));
depending on the situation you may need to make additional checks with
reflect(list).type.mixin;
If one of these checks is true it is a subtype.

Resources