I am new to SwiftUI, ARKit And RealityKit so sorry for my very basic question
I have been told to use these methods to load models
Entity.load(named: "abc.usdz")
and
ModelEntity.load(named: "abc.usdz")
so what's the difference between a ModelEntity and Entity ?
First of all, ModelEntity is a child class of main parent nodes' class called Entity.
According to documentation:
An entity represents ‘something’ in a scene. Offsprings like PerspectiveCamera, SpotLight or ModelEntity inherit from Entity class.
class Entity : HasHierarchy, HasSynchronization, HasTransform
ModelEntity (like any other entities) is more specific. It represents a model which is rendered and optionally simulated. It inherits from Entity class and conforms to HasModel and HasPhysics protocols.
class ModelEntity : Entity, HasModel, HasPhysics
Very often two entity classes are interchangeable (when setting components). For example you can use Entity instead of SpotLight class.
Entity().components[SpotLightComponent] = SpotLightComponent(color: .red,
intensity: 2000,
innerAngleInDegrees: 45,
outerAngleInDegrees: 90,
attenuationRadius: 5.0)
vs
SpotLight().components[SpotLightComponent] = SpotLightComponent(color: .red,
intensity: 2000,
innerAngleInDegrees: 45,
outerAngleInDegrees: 90,
attenuationRadius: 5.0)
However, the following example can be given as an exception. You need to exactly use Entity class when downcasting.
arView.installGestures([.all], for: entity as! Entity & HasCollision)
Related
Let's say I have a model like below
class Employee: Codable {
var id: String?
var personalDetails: Person?
}
class Person: Codable {
var firstName:String?
var lastName: String?
}
Now I have to maintain an Entity(say DBEmployee) inside CoreData which will have the exact same properties
Now, is there a way to NOT create a separate NSManaged subclass(DBEmployee) for that entity which will have the same properties(as Employee) and have that entity extract it's properties as per the properties of Employee
My main problem is when I create my CoreData operations for fetch, it returns me DBEmployee which I then have to convert to Employee which has exactly the same properties (because the method that uses this fetch accepts Employee as the parameter and not DBEmployee)
You can get values back as either a NSManaged object / subclass or a dictionary of [String:Any] depending on the fetch result type. However, neither of those is a POSO (plain old Swift object.)
Since they both have the exact same properties, can you can change the method / API to take a protocol instead?
It really comes down to if the API really needs a Codable model (because it’s going to serialize it, for example) or if you can change the method (or possibly add to it)
I have an NSManagedObject called "Routine," that has already been saved to my data model. It has a to-many relationship to another NSManagedObject called "Workout". I want to edit the Routine in order to add more workout relationships to it to it.
let routine = fetchedResultsController.objectAtIndexPath(indexPath) as! Routine
The ViewController where I edit the Routine in my data model contains an array of Workout objects:
var myWorkouts = [Workout]()
Some of the workouts in the "myWorkouts" array may have been already associated with Routine, whereas others may not have (a new workout). I create a relationship between each workout and the routine like this:
for workout in myWorkouts {
routine!.setValue(NSSet(objects: workout), forKey: "workout")
}
My Question: If a relationship between a Routine and a Workout has already been created, will the above for-loop create a duplicate of that workout to associate with my routine, or will it only create new relationships for previously unassociated workouts?
I hope my questions makes sense. Thanks in advance for the help!
Routine CoreDataProperties File
import Foundation
import CoreData
extension Routine {
#NSManaged var name: String?
#NSManaged var workout: Set<Workout>?
}
So, you're working with Sets, which means that they only always contain each value once. Therefore, regardless of the enclosing objects (in this case NSManagedObjects), there will only be one in there. You're good - re-stating the relationship won't change anything.
I might suggest, however, that you can do a couple of things to make your life easier:
If you haven't already, create the concrete subclasses using Xcode's built in tools, so you can directly access relationships and properties.
In the concrete subclasses +NSManagedObjectProperties file, redefine those to-many relationships from NSSets? to Set<MyClass>?. This allows you to call Swift-native functions, and works correctly, as Set is bridged from NSSet.
In the future, just call routine.workout = workout, which is much clearer than the way your code defines setting the relationship.
Let's say I have an NSManagedObject subclass Instrument and I want to subclass that subclass to create something like Guitar. Is there a common practice for this? It doesn't seem to be as straightforward as subclassing NSObject.
For managed object subclasses, the subclass/parent class relationship
corresponds to the subentity/parent entity relationship of the
Core Data entities.
If you set the "Parent Entity" of "Guitar" to "Instrument" in the
Core Data model inspector and then create the managed object subclasses
in Xcode, you'll get
// Instrument.swift:
class Instrument: NSManagedObject {
// Insert code here to add functionality to your managed object subclass
}
// Guitar.swift:
class Guitar: Instrument {
// Insert code here to add functionality to your managed object subclass
}
For more information, see the section "Entity Inheritance"
in the Core Data Programming Guide:
Entity inheritance works in a similar way to class inheritance, and is useful for the same reasons. If you have a number of entities that are similar, you can factor the common properties into a superentity, also known as a parent entity.
Also pay attention to the
NOTE
Be careful with entity inheritance when working with SQLite persistent stores. All entities that inherit from another entity will exist within the same table in SQLite. This factor in the design of the SQLite persistent store can create a performance issue.
There is nothing wrong in doing this:
class Instrument: NSManagedObject {
#NSManaged var name: String
}
class Guitar: Instrument {
#NSManaged var numberOfString: NSNumber
}
I binded the content of an IKImageBrowserView to an array controller of objects Person implementing the IKImageBrowserItem protocol:
– imageUID
– imageRepresentationType
– imageRepresentation
In the class Person, I want the attribute "photo" to be the same as the attribute "imageRepresentation" (that was added merely to conform to the protocol).
My solution so far is to bind the 2 attributes in the Person init method. However, I don't like to have duplicated attributes, since Person is a model class.
What should I do ? (keeping in mind that I want to preserve the name photo, and not imageRepresentation)
Since imageRepresentation is mandatory for the protocol, but you want to use the photo property, you could implement the method in this way:
- (id)imageRepresentation {
return self.photo
}
In this way you fulfill the protocol, but you are using only photo.
I have a rather deep hierarchy of objects that I'm trying to persist with Entity Framework 4, POCO, PI (Persistence Ignorance) and Code First. Suddenly things started working pretty well when it dawned on me to not use the new() operator. As originally written, the objects frequently use new() to create child objects.
Instead I'm using my take on the Repository Pattern to create all child objects as needed. For example, given:
class Adam
{
List<Child> children;
void AddChildGivenInput(string input) { children.Add(new Child(...)); }
}
class Child
{
List<GrandChild> grandchildren;
void AddGrandChildGivenInput(string input) { grandchildren.Add(new GrandChild(...)); }
}
class GrandChild
{
}
("GivenInput" implies some processing not shown here)
I define an AdamRepository like:
class AdamRepository
{
Adam Add()
{
return objectContext.Create<Adam>();
}
Child AddChildGivenInput(Adam adam, string input)
{
return adam.children.Add(new Child(...));
}
GrandChild AddGrandchildGivenInput(Child child, string input)
{
return child.grandchildren.Add(new GrandChild(...));
}
}
Now, this works well enough. However, I'm no longer "ignorant" of my persistence mechanism as I have abandoned the new() operator.
Additionally, I'm at risk of an anemic domain model since so much logic ends up in the repository rather than in the domain objects.
After much adieu, a question:
Or rather several questions...
Is this pattern required to work with EF 4 Code First?
Is there a way to retain use of new() and still work with EF 4 / POCO / Code First?
Is there another pattern that would leave logic in the domain object and still work with EF 4 / POCO / Code First?
Will this restriction be lifted in later versions of Code First support?
Sometimes trying to go the POCO /
Persistence Ignorance route feels like
swimming upstream, other times it feels
like swimming up Niagra Falls. Still, I want to believe...
Here are a couple of points that might help answer your question:
In your classes you have a field for the children collection and a method to add to the children. EF in general (not just Code First) currently requires that collections are surface as properties, so this pattern is not currently supported. More flexibility in how we interact with classes is a common ask for EF and our team is looking at how we can support this at the moment
You mentioned that you need to explicitly register entities with the context, this isn’t necessarily the case. In the following example if GetAdam() returned a Adam object that is attached to the underlying context then the new child Cain would be automatically discovered by EF when you save and inserted into the database.
var adam = myAdamRepository.GetAdam();
var cain = new Child();
adam.Children.Add(cain);
~Rowan