Changing required property left field blank - swift

I have object Company that previously used an optional property name. Now I needed to change it to not be null, so I changed it from
#objc dynamic var name: String?
to
#objc dynamic var name = ""
The problem is that now all company names are reporting as empty strings. The realm itself does have valid values in it. If I change the code back to the optional method it does have their values. Other places that have always been required strings are not returning empty strings. What is causing this?

Related

How do put multiple values into a single key in Swift?

Is there a way to put multiple values in one key in Swift's dictionary, such as 'multimap' in Java?
var multiDic = [String:UserData]()
This is the dictionary I declared. it has this structure.
struct UserData{
var name: String
var id: String
var nickname: String
}
And when I put the value in one key in the dictionary, the value is updated without being stacked.
for key in 1...10 {
multiDic.updateValue(UserData(name:"name+\(key)", id:"id+\(key)", nickname:"nick+\(key)"), forKey: "A")
}
print(multiDic.count)
reults
1
How can I accumulate multiple values on a single key? I looked up a library called 'Buckets'
(https://github.com/mauriciosantos/Buckets-Swift#buckets), but there has been no update since swift 3.0.
Swift dictionary doesn't support this. One work around is to declare the dictionary to hold an array of values, like this:
var multiDic = [String:[UserData]]()
You would have to modify your code for adding values to work with the array instead of updating the value in place.
I haven't tried the "Buckets" project you mention, but for what it's worth, it probably still works either as-is or with minor changes.

Get codable's property names as strings in swift

Edit
let disucssionMessageTimestampKey = DiscussionMessage.CodingKeys.messageTimestamp.stringValue gives an error:
'CodingKeys' is inaccessible due to 'private' protection level
I have a message structure defined like this:
struct DiscussionMessage: Codable {
let message, userCountryCode, userCountryEmoji, userName, userEmailAddress: String
let messageTimestamp: Double
let fcmToken, question, recordingUrl, profilePictureUrl: String?
}
I want to define a variable disucssionMessageTimestampKey whose value will be messageTimestamp. I want to use disucssionMessageTimestampKey variable in the following query:
messagesReference.queryOrdered(byChild: "messageTimestamp").queryStarting(atValue: NSDate().timeIntervalSince1970).observe(.childAdded)
So that I don't have to hardcode the string value ("messageTimestamp") of the variable name.
Now I know I could just do let disucssionMessageTimestampKey: String = "messageTimestamp". But this is again prone to errors. So I was wondering if there was a way that I could get the string value messageTimestamp without having to define it anywhere.
By something like this (I know this won't work but just to give an idea of what I am looking for)
let disucssionMessageTimestampKey: String = String(describing: DiscussionMessage.messageTimestamp) // Will store disucssionMessageTimestampKey = "messageTimestamp"
Also, would it be possible to completely define the key values first as strings and then use those as variable names in the actual codable object? I.e. first define let disucssionMessageTimestampKey: String = "messageTimestamp", and then use the variable disucssionMessageTimestampKey to define what the property (messageTimestamp) of the codable object should be called. (This is low priority but curious and seems related to the question at hand)

SwiftRealm optional value with default

I am very new to Realm but I was wondering if there was a way to set the default of an optional value to another variable. I know this sounds very confusing but I hope my code will explain it. My goal is to create Directories with multiple categories. If the user does not enter a custom for the category, it will default to the last path component (folder name). Does anyone have any ideas about how to do this? I was thinking about doing #objc dynamic var name: String = (path as NSString).lastPathComponent but it wouldn't work. Any help is appreciated. Thanks!
class Category: Object {
let name = (LinkingObjects(fromType: Category.self, property: "path") as NSString).lastPathComponent
#objc dynamic var path = ""
#objc dynamic var directory: Directory?
}
class Directory: Object {
#objc dynamic var name = ""
#objc dynamic var path = ""
let categories = List<Category>()
}
This is not a Realm issue, but a Swift issue in general. You cannot declare an instance property and assign it a value in which you are referring to the value of another instance property, since instance properties are only guaranteed to have a value at the end of the initializer, but when you declare an instance property with a default value, that gets called before the initializer, so there's no guarantee that the other properties already have values.
If you need name to be a persisted Realm property, you won't be able to use your other instance property to get a default value, however, if you don't need to persist name in Realm, you can simply make name a lazy variable and hence you'll be able to access other instance properties.
lazy var name = (path as NSString).lastPathComponent

Conditional Defining a property in model object

I have a model object and there are some properties in that object. Based on some conditions, I want a property to be defined there or not to be defined. For example, this property is my app version.
class Person {
var name: String
var address: String
var age: String
// I want some condition here like if myAppVersion > 1.0 then add isChild
// property to my model object other wise don't add that
var isChild: Bool
// Normal property again
var gender: String
}
I want this behaviour because the properties are coming from the backend and all these properties are required, so if, for some reason, the BE doesn't send the a required property which the client is expecting, then I will crash. These properties have to be mandatory and not optional.
Don't do this.
Declare your parameter as an optional and set it to nil if you don't want it to have a value. You should create two separate classes if you want to have different implementations, but that would be pretty superfluous for just one little change.
If your application crashes just because a property has a nil value, you should really take a look at optional handling in Swift and nullability in Objective-C.

stored property "text" without initial value prevents synthesized initializers

I'm learning swift and have came up with the simple code below.
class ARandom{
var number: Int = 0
var text: String
}
However, Xcode displays the following Error:
stored property "text" without initial value prevents synthesized initializers
Why is this happening? what is an synthesized initialiser? why "text" without initial value prevents systhesised initialiser? Could someone please kindly explain it to me? THanks in advance for any help!
You have a few options here.
Make text optional.
var text: String?
Give text a default value
var text: String = ""
Give text a value in ARandom's initializer
init() { text = "" }
The reason this happens is your are defining text as a String. It is not optional. Essentially you are saying that it always is a String and never nil.
With your current code if you created a new instance of ARandom, text would have no value - and that is not possible if text is not optional
Apple's docs probably explain it a bit better
Classes and structures must set all of their stored properties to an
appropriate initial value by the time an instance of that class or
structure is created. Stored properties cannot be left in an
indeterminate state.
You can set an initial value for a stored property within an
initializer, or by assigning a default property value as part of the
property’s definition.