Swift assign value from dictionary to string object - swift2

I am using swift dictionary of AnyObject type and reading values for specific key and assigning it to a string object like this,
contactObject.lastName = requestDict.objectForKey("lastName") as! String
My question is when the key "lastName" is not present into the dictionary at that time my app crashes, so I added the check to avoid the crash, but I want to know how can I get the optional value from the dictionary for key "lastName" as I know swift's feature of getting optional value.
So how can I get rid of adding the check if that key exist into the dictionary then read the value and assign it to string object.
Any help would be much appreciable.
Thanks

Im not quite sure what you are asking. If you are trying to get the lastName from a dictionary of [String: AnyObject] and convert it to a string, I recommend you do it like this. It will only assign it if it exists.
if let lastName = requestDict["lastName"] as? String {
contactObject.lastName = lastName
}
force unwrapping is always dangerous. Use if let and guard let statements to prevent errors from propagating when unwrapping optionals.

You should use SwiftyJSON library(external framework), it is very clean and you would not need type checks like in ios built-in system.
For SwiftyJSON, all you have to do is
contactObject.lastName = requestDict["lastName"].stringValue
It will convert the value of key to string itself.
If the dictionary lastname contains nothing, SwiftyJSON will use "", it is very good.
For creating an array, you can use something like :
array = dictionary["contactObjects"].arrayValue
To learn more, just google Swifty JSON and open github page.
And all you have to do to use it is to create a podfile and add pod if you can use CocoaPods.

Related

macOS command line app - User Defaults dictionaryRepresentation shows too many values

I a developing a macOS commandline application in Xcode, which uses User Defaults. I have the following code for my User Defaults
if let configDefaults = UserDefaults.init(suiteName: "com.tests.configuration") {
configDefaults.set("myStringValue", forKey: "stringKey")
configDefaults.synchronize()
print(configDefaults.dictionaryRepresentation())
}
This will create my own .plist file in the ~/Library/Preferences folder. If I look into the file, I can see only my single value which I added, which is perfectly fine. But when I call dictionaryRepresentation() on my UserDefaults object, the there are a lot of other attributes (I guess from the shared UserDefaults object), like
com.apple.trackpad.twoFingerFromRightEdgeSwipeGesture or AKLastEmailListRequestDateKey
Looking into the documentation of UserDefaults, it seems that this has to do with the search list of UserDefaults and that the standard object is in the search list:
func dictionaryRepresentation() -> [String : Any]
Returns a dictionary that contains a union of all key-value pairs in the domains in the search list.
There are also the methods addSuite and removeSuite for a UserDefaults object, so I am guessing I need to remove the .standard suite from my configDefaults object, but I don't know the name, which should be used for that in the method.
Is it possible to remove the .standard defaults from the dictionary representation? I basically just want all of my own data in a dictionary, nothing more.
The reason I am trying to get only my values from the UserDefaults, is that a have a number of object of a custom type Connection (which store the configuration to connect to a server), which are saved in the UserDefaults. On program start I want to be able to load all objects into my app. Therefore I thought I could use dictionaryRepresentation(), as it would return all elements in the UserDefaults. But then there should be only my Connection objects in the dictionary, so that I can cast it to [String: Connection].
Given your purpose (in your latest edit of your question), what you should do is store a collection of Connection objects under a single key. Then, look up that key to get the collection.
It's not clear if the collection should be an array of Connection objects or a dictionary mapping strings to Connections. That's a choice you can make.
But, in any case, you shouldn't rely on the defaults being empty of everything else.
In other words, you would do:
UserDefaults.standard.set(yourStringToConnectionDictionary, forKey:"yourSingleKey")
and later:
let connectionMap = UserDefaults.dictionary(forKey:"yourSingleKey")
then look up Connections in the connectionMap by their name/ID/whatever.
Though the other solution proposed by Ken Thomases may be better from a design standpoint, I've found a solution that does exactly what I initially wanted. Calling
UserDefaults.standard.persistentDomain(forName: "com.company.TestApp.configuration")
Returns a dictionary containing only the values I've added to the domain com.company.TestApp.configuration, using
let configs = UserDefaults.init(suiteName: "com.company.TestApp.configuration")!
configs.set(someData, forKey: someKey)
Strangely in the Apple documentation says this about persistentDomain(forName:):
Calling this method is equivalent to initializing a user defaults object with init(suiteName:) passing domainName and calling the dictionaryRepresentation() method on it.
But this is not the case (see my question). Clarification on that subject is more than welcome.

CoreData 'Name must begin with lower case letter' - can I get around this?

When I first started my iOS project I could use capital letters in core data to start my property names (FirstName, LastName, ect...). This is extremely beneficial to me since I feed data into CoreData using a web service and plists and the creation of objects inserted into my local CoraData DB is greatly simplified and super fast if all property names match exactly. Which up until now has not been a problem. Currently in xCode 4.3.1 I cannot get around the nameing convention restrictions and it is causing me a huge headache since my remote DB uses capital letters for it's column names which in turn then do not match my local CoreData properties.
Is there anyway to get around this in xCode?
Function to convert the first character to lowercase:
-(NSString *)refactorAttributeName:(NSString*)name {
NSString *first = [[name substringToIndex:1] lowercaseString];
return [name stringByReplacingCharactersInRange:NSMakeRange(0, 1)
withString:first];
}
Simple answer is No. If you have any control over the way the data is coming out of your remote DB, you could just do something like:
Select FirstName as firstName, LastName as lastName ...
If that is too much trouble, then you will need to either need to map these in your project or not use Xcode 4.3 and up.
you can always go into the model package and edit the contents file manually. does not mean that this new standard won't bite you later.
I suppose you can try opening the same project in 4.2 use big letter, and then reopening in 4.3, which will honor the old convention
I had similar problem - I wanted to use entity names starting with lower case letter and xcode demanded to use names starting with upper case letter. I resolved this issue in the following way:
Created NSManagedObject subclass for an entity - option available in
Editor menu
Used xcode refactoring to change the name of the created subclass
Refactoring changed also the name of the entity in the Data Model. I believe same method can be used for changning the name of attributes. I used xcode 4.6.1.
I encountered the same problem when mapping my web service JSON response to my Core Data models. Instead of changing the Core Data models I solved it by changing my mapping code to the following:
for (NSString *key in json) {
NSString *keyWithFirstCharLowered = [key stringByReplacingCharactersInRange:NSMakeRange(0, 1) withString:[[key substringToIndex:1] lowercaseString]];
if ([modelClass respondsToSelector:NSSelectorFromString(keyWithFirstCharLowered)]) {
[modelClass setValue:[json valueForKey:key] forKey:keyWithFirstCharLowered];
}
}

Core Data KVC example

Sorry to impose, but I would really appreciate it if someone would take a look at this and show me how to get this done:
Core Data works as expected with data associations between the Source list entry(s) and the upper right textField.
So does textField2 (lower right) if you manually type in a string.
I want to append a string in the lower textField, in this case a generic "Hello!" (implemented in the setText method) and have it also maintain it's association with the source list entry.
To summarize: textField2 - manually type in a string, it works as expected. Append the coded string, and it does not maintain it's association with the source list entry.
Here's the sample project.
Thanks again for the help.
Here's how I updated setText: method in MyDocument class:
-(IBAction)setText:(id)sender
{
NSString *newValue = [[output stringValue] stringByAppendingString:#"Hello!"];
[[setText selection] setValue:newValue forKey:#"textField2"];
}
I think your assumptions on value setting direction was wrong. Object does not take a value from the text field. It's the text field that takes value from the object. Hence I create newValue by taking current value of output text field and appending something to it. Then I take [setText selection] object (the one currently selected) and set it's textField2 property to new value. This setValue:forKey method automatically updates the output test field with new value of textField2 property.

MS CRM QueryExpression ConditionExpression w/ CRMBoolean type

I'm using Microsoft's CRM software (4.0) and I'm trying to build a query expression. It works fine with querying only String values, but now I need to include a field that is of type CRMBoolean. I should also mention I'm querying custom entities.
So previously, in my query I would only search by a few fields, but they were all of type String. Now I need to add another ConditionExpression for a CRMBoolean. The type of custom entity I'm searching for has a field called "Condition" - which will either have a value of "true" or "false". In CRM the attribute is defined as a bit, but I didn't think that would make a difference.
Here is my code I'm trying to use to find records that have a condition of "true":
oCondition = New ConditionExpression()
oCondition.AttributeName = "myEntity_condition"
oCondition.Operator = ConditionOperator.Like
Dim bool As New CrmBoolean
bool.Value = True
oCondition.Values = New Object() {bool}
listConditions.Add(oCondition)
I don't get an error, but nothing really happens. The number of records that is returned never changes one way or another. Has anyone done this before?
Thanks in advance!
Instead of putting a CrmBoolean object in the oCondition.Values array, just put a regular true/false boolean. I would also concur with benjynito on changing it to ConditionOperator.Equals instead of Like.
I don't know how the like operator is suppose to behave on a boolean. I wonder if its being ignored. Try ConditionOperator.Equal.

Optional URL parameters with url routing in webforms

Playing with the new(ish) url rewriting functionality for web forms, but I'm running into trouble trying to declare parameters as optional.
Here's the scenario. I've got a search function which accepts two parameters, sku and name. Ideally I'd like the URL for this search function to be /products/search/skuSearchString/nameSearchString. I also have various management pages that need to map to things like /products/management/ or /products/summary/. In other words, the last two parameters in the URL need to be optional - there might be one search string, or two, or none.
This is how I've declared my virtual URL:
Friend Const _VIRTUALURL As String = "products/{action}/{sku}/{*product}"
And added the following defaults:
Me.Defaults = New Web.Routing.RouteValueDictionary(New With {.sku = "/"})
Me.Defaults = New Web.Routing.RouteValueDictionary(New With {.product = "/"})
I have two problems with this setup. The most pressing is that the url seems to expect an sku parameter. So, /products/summary/ cannot be found but /products/summary/anyTextAtAll/ maps to the correct page. You get the same result whether the defaults are set to "/" or "". How do I ensure both sku and product parameters are optional?
The second is more a matter of interest. Ideally, I'd like the url to be able to tell whether or not it's got a product search string or a url search string. The obvious way to do this is to make one or the other default to a value I can just pick up and ignore, but is there a neater way of handling it?
I'm not sure I entirely understood the question, but I have some comments about what you've shown so far:
The manner in which you're setting defaults seems incorrect. You're first setting a default value dictionary with a value for "sku". You're then replacing the default value dictionary with a value for "product".
A default value of "/" is unlikely to be what you want. In this case it sounds like you want a default value of just "" (empty string).
Try something like:
Me.Defaults = New Web.Routing.RouteValueDictionary(New With {
.sku = "",
.product = "" })
My VB skills are rather weak, so the syntax I showed might not be exactly right.
I think that if you change both of these then you should be good to go.

Resources