NSUserDefaults.standardUserDefaults().dictionaryRepresentation().keys returns [NSObject] but I need (and would expect) [String]. Is it just some coffee I'm missing?
dictionaryRepresentation() returns NSDictionary that does not support generic types. You can convert to Swift dictionary:
let dictionary = NSUserDefaults.standardUserDefaults().dictionaryRepresentation() as [String : AnyObject]
let keys = dictionary.keys
That actually returns a LazyBidirectionalCollection<MapCollectionView<Dictionary<Key, Value>, Key>>. You can add .array to get an array instance back, then use map to cast the values to String:
let keys = NSUserDefaults.standardUserDefaults().dictionaryRepresentation().keys.array.map { $0 as String }
println(keys)
// [NSLanguages, NSInterfaceStyle, AppleLanguages]
Related
Say I have the following for comprehension:
val validatedInput = for {
stringID <- parseToInt(optionalInputID)
} yield (stringID)
where optionalInputID is an input parameter of type Option[String]. I want to be able to convert an Option[String] into just a String, if of course there is an option present. As far as I'm aware, you cannot case match inside a for comprehension.
Some details have been omitted, such as other for comprehension items. Therefore I would like to know if it's possible to do this inside the for comprehension. If not, then what's a suitable alternative? Can I do it outside of the for comprehension?
Simply add it to the for comprehension:
val validatedInput = for {
inputID <- optionalInputID
stringID <- parseToInt(inputID)
} yield (stringID)
It will work only if parseToInt has type of Option. If it returns something of Try, you can't do it - because you can't mix Try and Option in the same for-comprehension.
If parseToInt returns Try, you can do the following:
val validatedInput = for {
inputID <- optionalInputID
stringID <- parseToInt(inputID).toOption
} yield (stringID)
I want to be able to convert an Option[String] into just a String.
Therefore I would like to know if it's possible to do this inside the for comprehension
In Scala, for-comprehension desugars into a combinitation of map, flatMap, filter, none of which allows to extract the value out of the Option.
If not, then what's a suitable alternative? Can I do it outside of the for comprehension?
To do so you can use one of get (unsafe), or it safer version getOrElse, or fold:
val validatedInput: Option[String] = Some("myString")
scala>validatedInput.get
// res1: String = "myString"
scala>validatedInput.getOrElse("empty")
// res2: String = "myString"
scala>validatedInput.fold("empty")(identity)
// res3: String = "myString"
I have some string codes but when my strings values null gives my app fatal error my codes here which changes i need to do ?
let pCodeTextFieldStr:NSString = pCodeTextField.text!
let pNameTextFieldStr:NSString = pNameTextField!.text!
let pQuantityTextFieldStr:NSString = pQuantityTextField.text!
let commingReadyIDs:NSString = prefs.valueForKey("addClientID") as! String!
let commingCurrs:NSString = prefs.valueForKey("addClientCurrency") as! String!
let commingtype:NSString = prefs.valueForKey("addProductType") as! String!
let productnameclean:NSString = prefs.valueForKey("addProductName") as! String!
The exclamation mark ! tells the compiler "if this item is nil then please crash". So the first step would be not to do that. The second step would be to figure out what you want to do if something is nil. You usually handle this using if let ... or using the nil-coalescing operator, ??.
They aren't "opinion"s they're how it is.
let commingCurrs:NSString states that commingCurrs CAN NEVER be nil.
Likewise, the fragment prefs.valueForKey("addClientID") as! String! states that prefs.valueForKey("addClientID") CAN NEVER return nil.
Since your data obviously CAN be nil, you're going to have to resolve the discrepancy.
You've been given 3 options, the only possible other option is to declare your variables as optional instead of required:
let commingReadyIDs:String? = prefs.valueForKey("addClientID") as? String
But that's just kicking the can down the road. Sooner or later you're going to have to deal with the fact that these values WILL BE NIL at some point.
Just a note, ANY time you're posed with the option of putting ! in a swift program you need to think long and carefully about is it really the right thing to do? Can this truly NEVER be nil? ! is the most evil, insidious, character in the swift language.
Since there's a possibility that these string values do not exist, you should not force unwrap them. An optional represents a variable that may have a value or it may have nil. Swift encourages you as a developer to acknowledge this and unwrap cases where a value may return nil. By using !, you are telling the compiler, I know there's a value here, in which in your case, there was not and an exception was thrown.
In the example below, if a string exists for the key, it will enter the scope of the block and you can access the string with the constant variable, commingReadyIDs. If not, the block will not be entered and no exception will occur.
I would encourage you to read more about optionals in Swift documentation since you will frequently encounter them and they encourage developers to avoid these null pointer exceptions.
if let commingReadyIDs = prefs.valueForKey("addClientID") as? String{
//do whatever
}
If you don't know when value exists of a variable or when not then you should use Optional Chaining, you can try below code
// all defined variables (like pCodeTextField) can have value or can be nil so don't use forcefully unwrapped optional value without cheking nil
let pCodeTextFieldStr:NSString? = pCodeTextField?.text
let pNameTextFieldStr:NSString? = pNameTextField?.text
let pQuantityTextFieldStr:NSString? = pQuantityTextField?.text
let commingReadyIDs : NSString? = prefs?.valueForKey("addClientID") as? String
let commingCurrs : NSString? = prefs?.valueForKey("addClientCurrency") as? String
let commingtype : NSString? = prefs?.valueForKey("addProductType") as? String
let productnameclean : NSString? = prefs?.valueForKey("addProductName") as? String
I know curly brackets are not used to initialize array in Groovy but I have noticed one peculiar thing.
Why groovy doesn't give compiler error when I initialize an array like this.
String emailAddress = "test#gmail.com";
String [] var = {emailAddress};
println var[0];
Output: com.test.examples.GroovyTest$_main_closure1#12e4860e
When I try to declare like this I get error:
String [] var = {"a","b"};
Can anybody explain this?
When you do:
String [] var = {emailAddress};
That creates a Closure that returns a String emailAddress, and then crams that closure into a String array (by calling toString() on it), as that's what you told it to do ;-)
So var equals ['ConsoleScript0$_run_closure1#60fd82c1'] (or similar, depending on where you're running things)
When you do:
String [] var = {"a","b"};
The right-hand side is not a valid Closure, so the script fails to parse.
What you want is:
String[] var = ['a', 'b']
Or:
String[] var = [emailAddress]
How do I convert an object of type (NSObject, AnyObject) to the type String?
At the end of the first line of the method below, as String causes the compiler error:
'(NSObject, AnyObject)' is not convertible to 'String'
Casting street to NSString instead of String compiles, but I'm casting street to String because I want to compare it to placemark.name, which has the type String!, not NSString.
I know name and street are optionals, but I'm assuming they're not nil for now because all the places returned from MKLocalSearch seem to have non-nil names and streets.
func formatPlacemark(placemark: CLPlacemark) -> (String, String) {
let street = placemark.addressDictionary["Street"] as String
if placemark.name == street {
// Do something
}
}
A String is not an object, so you do need to cast it to an NSString. I would recommend the following syntax to cast it and unwrap it at the same time. Don't worry about comparing it to a variable of type String! since they are compatible. This will work:
func formatPlacemark(placemark: CLPlacemark) -> (String, String) {
if let street = placemark.addressDictionary["Street"] as? NSString {
if placemark.name == street {
// Do something
}
}
}
This has the added benefits that if "Street" is not a valid key in your dictionary or if the object type is something other than NSString, this will not crash. It just won't enter the block.
If you really want street to be a String you could do this:
if let street:String = placemark.addressDictionary["Street"] as? NSString
but it doesn't buy you anything in this case.
The return type from looking up via subscript for a swift dictionary has to be an optional since there may be no value for the given key.
Therefor you must do:
as String?
I think it may have to do with addressDictionary being an NSDictionary.
If you convert addressDictionary to a Swift dictionary, it should work.
let street = (placemark.addressDictionary as Dictionary<String, String>)["String"]
I've got the following F# code:
//Array iter version
let toSecureString (s:string) =
let sString = new SecureString()
s |> Array.iter (fun cl -> sString.AppendChar cl)
sString
I'm trying to convert a .Net string to a .Net SecureString. When I try to compile I get a Type Mismatch error:
stdin(60,10): error FS0001: Type mismatch. Expecting a
string -> 'a
but given a
'b [] -> unit
The type 'string' does not match the type ''a []'
If I don't specify the type of s, this is the type signature I see:
val toSecureString : char [] -> SecureString
But since I don't want to have to manually create an array of chars for the argument each time, it seems like I am missing something. How can I make this code work with a string parameter being passed in?
If it makes a difference I'm testing on F# 2.0 (Build 4.0.40219.1).
Any hints welcome. If this has already been asked and answered, post a link in the comments and I'll close this question.
Use Seq.iter, not Array.iter, because strings are char seqs but not char[]s.
To manipulate a string as a char seq, one can use String module. This works:
let toSecureString s =
let sString = new SecureString()
String.iter sString.AppendChar s
sString
You can also do this:
SecureString(&&s.ToCharArray().[0], s.Length)