When should I use an Optional String in my model? - ios

In my model code currently in some places, I am doing
var optionalString : String?
and in some places
var otherString : String = ""
When it is an optional and I am unwrapping it, I am scared it shouldn't be nil and just for being on the safe side I do
let newString = optionalString ?? ""
With optionals, I need to unwrap and perform nil checks. It makes the code a little less readable.
Should a String ever be an optional in the model? Any scenario where it must be one?

Optionals are used when the absence of a value (the string) has differing semantics from an empty value.
Simple example:
A password could be either
set to some string
empty
not yet set at all.
Here, the "not-set" case must be handled differently than the "empty" case.
You should only use optionals when model logic differs for empty vs. missing string. Same is true for collection types (Array, Dictionary).

IMO, String optionals and empty strings are interchangable sometimes.
Let's say we have a person class, it has a name property. In this case, a person must have a name, so optional and empty strings are interchangable (You can use either). You can use nil or "" to indicate that a person has no name. They mean the same. You can declare a constant too:
let NoName = ""
And you can just check it with this very abstract constant, rather than nil, which is a little bit less abstract.
On the other hand, sometimes you must use an optional. And that is when nil and "" have different meanings in the context. Let's use our person class to illustrate this as well. The person class has a property called dogName. If he/she does not have a dog, it is nil. If he/she has a dog but has not given it a name, it is an empty string. And if he/she has a dog and has given it a name, it would be "fido" or some other names. In this case, nil means he/she has no dog, and "" means his/her dog has no name. They have different meanings!
Conclusion: When nil and empty string have the same meaning, use optional optionally. When nil and empty string have different meanings, use optional.

Related

NNBD: Least upper bound of String and Null

Working on a patch for some issues in the Dart Analyzer, I need to understand whether Null itself is considered a nullable type.
Currently, the least upper bound computed by Dart’s type algebra for String and Null is String.
However, in my opinion, the type union of String and Null is a nullable String.
Ticket with patch: https://github.com/dart-lang/sdk/issues/38585 Note that the patch still has a bug in widening T to T? if a closure returns both T and null.
Bonus question (ticket https://github.com/dart-lang/sdk/issues/38623): Is Null itself a nullable type and should be suffixed with ‘?’?
My opinion as proof by contradiction (LUB is least upper bound function):
Assume that Null is not nullable.
That means Null and Null? are different types.
LUB(T, Null) = T?, i.e. combining T with Null widens T to T?
Hence, LUB(Null, Null) = Null?
That violates LUB being reflexive which would mean that LUN(Null, Null) = Null
Hence the assumption is wrong.
Dart does not, yet, have non-nullable types. So, the type written as String is a nullable string. The Null type is considered a subtype of any type, and therefore the least upper bound of Null and (nullable) String is (nullable) String.
When Dart gets non-nullable types, that will change. Then the type written String will be non-nullable, and String? will be nullable, and the least upper bound of Null and String should then (hopefully!) be String?. Non-nullable types are not yet available, but they are being designed and are expected to be released ... well, when they are ready.
If you are trying to patch the Dart Analyzer, then you need to be aware of both type systems at the same tiem, because the analyzer has already been modified to recognize some non-nullable types if you pass the proper flags and proper source code.

What is the difference between "var" and "List" in Dart?

Is there a noticeable difference between the two?
var example = ["some","content",11,45,true];
List example = ["some","content",11,45,true];
With var example the type (static and runtime) for example will be inferred from the assigned value ["some","content",11,45,true] which will be List (or actually List<dynamic>)
With List example the type will not be inferred but the explicitely provided type List (or actually List<dynamic> if no generic type is provided) will be used instead.
For var example = ["some","content","11","45","true"]; the inferred type would be List<String>.
As far as I know and as simple as I can be;
List is a data type just like some other built-in types in Dart such as String, int and bool. When you initialize a variable using List, the assigned value must be of List type. i.e. You cannot do this
List example = "sometext";
because you're trying to assign a String value to a List variable or object here.
Whereas, var is a way to declare a variable without specifying its type. For var will accept all kind of data types.
Is there a noticeable difference between the two?
var example = ["some","content",11,45,true];
List example = ["some","content",11,45,true];
Both the methods of declaration have same effect unless you expect to assign a value to example with type(s) other than List during it's lifetime. i.e If you're looking to assign an int or double or string or whatever value to example in future use the first method else you can use any one of them.

Realm not query string field with whitespace

I have such function in my data source:
func getAllFood(by type: String) -> [UserFoodInformation] {
var findedFood = [UserFoodInformation]()
findedFood.append(contentsOf: baseUserFoodDataSource.getAllFood(by: type))
let predicate = NSPredicate(format: "foodType == %#", type)
let resultOfSearching = dataBase.objects(AddedUserFood.self).filter(predicate).sorted(byKeyPath: "name")
for searchedFood in resultOfSearching {
findedFood.append(searchedFood)
}
return findedFood
}
When I try to query with string that consist whitespace, I have no result, but if I query with simple one-word parameter, everything goes fine. Why is that? Can I have a string field in Realm that consists multiple words?
The predicate you're using is looking for objects whose foodType property is equal to the type string that is passed in. Only those objects whose property is exactly equal to that string will match. If you want to perform some other form of matching you'll need to use something other than the equality operator. BEGINSWITH, CONTAINS, ENDSWITH and LIKE are the comparison operators that Realm supports on string fields.
Can I have a string field in Realm that consists multiple words?
String fields can contain any string values. The supported comparison operators don't have the concept of a "word", though, so if you want to do filtering using that concept you'll likely need to do further work on your part. Depending on your use case, I can see a couple of ways to go about it:
Use CONTAINS to find any objects whose foodType properties contains the given type string.
Parse the string into structured data that you store in your model. For instance, it may make sense to store a List<FoodType> rather than a String for the foodType property.
There are likely other options, but they depend on details of what it is you're trying to achieve that you've not shared.

How to check if a string has many instances of a sub string?

I need to check if the user is typing a word correctly in a UITextView but the word is repeated multiple times. The rangeOfString() and containsString() methods for strings either check for the specified strings at their first or last occurrence, but I want to check for ALL occurrences of the string.
For example:
var string = "Hi Bloog hi Bloog hi Bloog"
I want to check if "Bloog" is present in the string, and if it is, it should be exactly "Bloog" and not "Bloogg" or "Bloo g" whenever it is repeated
How do I do that? Thanks

Comparing strings with objects in c#/XNA

I have an XML file which is split up using pipes "|". I have some code in a question class that splits up the XML files "Items" as so..
List<string> questionComponents = newquestionString.Split('|').ToList<string>();
questionString = questionComponents[0];
apple = questionComponents[1];
pear = questionComponents[2];
orange = questionComponents[3];
correctAnswer = Int32.Parse(questionComponents[4]);
I want to compare these components with objects which are instantiated in my Game1 class (three fruit - apple, pear, orange). So how do I do this?
A friend helped me get this far. I have no idea how to do this, and after searching google with no luck I've resulted in asking here to you lovely people.
Thanks in advance :D
EDIT: To clear things up...
I have three objects called apple, pear and orange and I want to associate these objects with the strings which are shown in the XML file for each component of the strings. The question string displays a question, [1] answer 1, [2] answer 2, [3] answer [3].
And then I need a way to compare the answer to the object that is eaten in the game..
Assuming you have some kind of Orange object, some kind of Pear object, and some kind of Apple object, in each class override the ToString method.
If you have some generic Fruit or Answer object, consider passing a string in the constructor and returning that string in the ToString method.
EDIT: Since you've now clarified, I would go with Jonathan's idea of having a Name or Answer property; then you can do:
if(object.Answer == questionComponent)
//do stuff
And ToString does not turn the object into a string. It simply returns a user-defined (if you choose to override) string for the object - for the Ints it is "42", and for bools it is "true" or "false". No conversion occurs.
Based on your edit, it sounds like all you're trying to do is be able to look up some concrete object based on a string that you get from a data file? Couldn't you use a Dictionary for this, as in:
Fruit apple = new Apple();
Fruit orange = new Orange();
Dictionary<string,Fruit> map = new Dictionary<string,Fruit>();
map["apple"] = apple;
map["orange"] = orange;
and then later you can get the user's answer/input:
string input = ...
Fruit result;
if(map.TryGetValue(input, out result)) {
// `fruit` now holds the fruit object the user selected.
} else {
// User input did not correspond to a known fruit.
}
But I'm still not convinced I'm understanding your question properly.
It looks like the range of possible strings is limited, so why not just use identifiers in the form of Enums, which you can parse from the string, and set that identifier into the answers and the fruits?
public enum AnswerType
{
Apple,
Pear,
Banana
}
Store the answers in a dictionary mapping ids to answers (casting enum to int for the key), plus the correct answer's id, and now you can know which answer was picked each time, checking the eaten fruit's id, and if the answer was right.

Resources