RealmSwift: saving related objects during add() - swift

In the header for add(_ object:, update:) it says, "When added, all child relationships referenced by this object will also be added to the Realm if they are not already in it." This is the behavior I was hoping for, but I'm not 100% clear on what "child relationships" includes/excludes. Which types of Realm relationships are not covered by this behavior?
For example, if I'm adding a ClassA object to the realm and I have another unsaved ClassB object, will the ClassB object be saved:
If the ClassB object points to the ClassA object and ClassA has a LinkingObjects property for ClassB?
If the ClassB object is added to a List property of ClassA?
If ClassA has a to-one relationship variable pointing to the ClassB object?
I know that I could set up some sample classes and play around with this to figure out the behavior, but I'd like to have some official clarification if possible.

I figured out this behavior with realm also in the last months. From my experience the child relationships will be saved in your realm database as well. Below you can find the code examples based on your bullet points:
If this is your data model:
import Foundation
import RealmSwift
class ClassA: Object {
dynamic var uniqueID:String?
dynamic var someVaraible?
dynamic var classB:ClassB?
var list = List<ClassB>()
}
If the ClassB object points to the ClassA object and ClassA has a
LinkingObjects property for ClassB?
If you have a classA variable aVar you can add your object with aVar.classB = <your classB variable> in this case nothing will stored in the realm database for now. If you then add a object to realm with
try! realm.write({
realm.add(aVar)
})
Realm is going to save both objects (aVar and also your classB variable).
If the ClassB object is added to a List property of ClassA?
It is exactly the same behavior like in your first question -> the list of classB's (also every single entry of the list will be created in your classB database column) will be added to realm, if you add classA to realm.
If ClassA has a to-one relationship variable pointing to the ClassB
object?
In this case classB variable is already present and you just created a classA variable, which is starting to point to an existing classB stored entry in realm. (Please correct me, if I misunderstood you).

Related

Will referencing an array of instances of a class in a class create a strong reference cycle?

I have the following class:
class Circle: CustomStringConvertible, Hashable, Equatable
{
...
var bonus5Circles = [Circle]()
...
}
Now, in most cases the bonus5Circles array will be empty, but in some cases it will contain some subset of Circles. This seems to function properly in code, but my question is whether this is creating a strong reference cycle. I have noticed leaks that I cannot track down in functions when a bonus is created, and was wondering if it could be tracked to this property.
After asking this question I wrote a playground with analogous code. I found that there is no issue deinitializing instances of the class UNLESS the class instance with the non-empty array contains itself, in which case you do have a strong reference cycle.

Casting a class to subclass fails

Edit - Sorry guys, I don't think I gave enough detail:
In Parse's iOS framework, they is a class called PFObject (ClassA). The framework also allows you to subclass (ClassB) PFObject. AND, if a scenario such as the one I gave should occur, they would be no issue.
My question is how is this possible? I understand that a subclass could contain variables/methods that would not be present in the main class, thus making the process of casting a class to a subclass unreasonable/unsafe.
They have a protocol defined as PFSubclassing, but I don't see exactly how this allows this behaviour to occur.
I've got the following in Playground:
class ClassA: NSObject { }
class ClassB: ClassA { }
let objectA = ClassA()
let objectB = objectA as! ClassB // <- Crashes
Questions:
Why is a crash occurring?
Is there any way around this?
You do know how inheritance works right? Class B inherits from Class A. When you make an instance of ClassA and then try to cast it to class B, many different things might happen because this is undefined behavior. The problem here is what's called slicing. The compiler refuses to cast down from a parent class to a child class because it knows the child class may have different info (variables, func. etc) and it doesn't necessarily know how to translate those into an instance of a super classes child class. However, going the other way around is almost always fine, i.e
let objectB = ClassB()
let objectA = objectB as? ClassA
A subclass inherits all functionality from its super class and can add own functionality.
Logically you can cast types only from more to less functionality (sub -> super) but not vice versa.

Realm class name different from Stored Name in DB

So I am having naming conflicts in my code.
I have
struct LocationMessage {}
and
class LocationMessageRLM : Object {}
Is there an annotation or configuraiton option that will allow my LocationMessageRLM object to be stored in a table called LocationMessage
No, sorry. Realm generates the object schema for each table at runtime based off the class names of every Object subclass. There are no configuration options to change this behaviour.
If you're not happy about the name of the Realm object table, it might be worth considering renaming the struct instead (Sorry if that was really obvious!).

CoreData Handling Sets

I'm introducing CoreData to an existing class with objects that include to-Many-Relations.
Before I would have for example something like this:
"Player" is just a normal class with a result array...
for (y,result) in player.result!.enumerate() {
Now i would have to do it like this....
for (y,result) in (player.relResults!.allObjects as! [CDResult]).enumerate()
Is there a better way to do this?
Is there a way to avoid this ugly casting stuff?
An optional to-many relationship is represented in the NSManagedObject
subclass as an optional NSSet:
#NSManaged var results: NSSet?
So the type of the target entity of the relationship is lost here,
and some casting is needed. But you don't have to convert
the set to an array. You can cast it to a Set of the appropriate
type and iterate over the set:
for result in player.results! as! Set<CDResult> { ... }
Note that player.results can be nil, so this should be checked
before, or wrapped into an optional binding with if let or
guard let.
You could also change the property definition to
#NSManaged var results: Set<CDResult>?
and then simply iterate with
for result in player.results! { ... }
The disadvantage is that the change is lost if you re-generate the
managed object subclass in Xcode. Perhaps a future version of
Xcode will create Set<T> typed properties for to-many relationships.
(You may also have a look at "mogenerator" which is an alternative tool
to create the managed object subclasses with some nice additional features. It could be that mogenerator handles this better.)

MEF Export derived classes ans new instances

I have a base class and a derived class and I want to export for types derived from either.
So like this
public class ClassA { }
public class ClassB : ClassA { }
I need to load types derived from ClassA but also types derived from ClassB.
var registration = new RegistrationBuilder();
registration.ForTypesDerivedFrom<ClassA>()
.Export<ClassA>();
registration.ForTypesDerivedFrom<ClassB>()
.Export<ClassB>();
var catalog = new AggregateCatalog();
catalog.Catalogs.Add(new DirectoryCatalog(".", registration));
catalog.Catalogs.Add(new AssemblyCatalog(Assembly.GetExecutingAssembly(), registration));
container = new CompositionContainer(catalog);
container.SatisfyImportsOnce(this, registration);
I think the problem is that when exporting ClassA derived types it also exports ClassB types which is obvious and is the functionality that I am looking for. But it means that the ClassB imports aren't exported as independent objects, rather being the same ones as those imported as ClassA types. If I don't specifically export the ClassB then any imports using them fail.
I may be trying to do something stupid to try and solve my problem here that MEF isn't liking? I have looked at making the MEF imports non-singleton but that might break things in my imports.
In your given example only ClassB (with the export definition of classA) is exported as a MEF part. As Panos already mentioned, ForTypesDerivedFrom does not export the base class.
You can do something like this:
var registration = new RegistrationBuilder();
registration.ForTypesDerivedFrom<ClassA>().Export();
registration.ForType<ClassA>().Export();
This will export all derived classes of ClassA (also ClassB with ClassB contract and not with ClassA) and separately ClassA.
Additionally if you want to hide the base part but still want to use imports in this class you can add the [PartNotDiscoverable] attribute to your base class.