How to use a AnimationPlaybackController at the Entity level - swift

I am using realityKit and I want to stop and start a models animation depending on differing events like collisions and user interactions. I started by using a wrapper class to handle this logic, but this seemed to be cumbersome, and my app started crashing when I attempted to make more than one GameEntity.
Example:
class GameEntity: ObservableObject {
let model: ModelEntity
var currentMovementController: AnimationPlaybackController? = nil
// lots of other methods and properties ...
}
So now I am attempting to make a subclass of Entity where I will have an attribute for AnimationPlaybackController:
class ARXEntity: Entity {
var animationHandler: AnimationPlaybackController? = nil
// more methods ...
}
My question is: is it possible to use the AnimationPlaybackController on the entity level? If so, what is the right way to do it?

Related

Custom Class Sprite Kit, don't work init by name for iOS 10 (Xcode 11.3.1)

I have a parent class that is inherited from the standard SKScene, named as - SKSParent. It is created to perform the parent function of creating custom scenes by identifier. The problem is that when I launch the project on iOS 11 + everything works correctly, but when I launch on ios 10.3.1. My objects that I create by the scene ID do not accept the desired child class based on identifier. All objects are created as objects of the SKSParent class, regardless of their identifier and created .swift files.
Perhaps someone has encountered this behavior 😞
import SpriteKit
class Parent: SKScene {
}
class StoryScene: Parent {
}
class Story1: StoryScene {
}
class Story2: StoryScene {
}
class Story3: StoryScene {
}
Some condition for chose story(for example save current user progress to user default like story name)
Created some story with using for init by Name from super class like below:
let storyName = UserDefaults.standard.string(forKey: "current_user_story") ?? "Story1"
let currentStory = Parent(fileNamed: storyName)
/* some configurations with using object like Parent object */
/* presenting to user. */
In this case on iOS 10 current story is object of class 'Parant'...
In this case on iOS 11 and higher it's object of a specific type of Story(*)
The fact is that on ios 10 in such cases, objects load components from the .sks file but do not execute the life cycle methods of a particular class from the .swift file.

Core Data Background Thread Returning Inserted NSManagedObject

In my app I am using a NSPersistantContainer with two NSManagedObjectContexts (viewContext & background context). All my read operations are performed on view context, while all my write operations are performed on the background context (shown below).
Creating a new Animal class
class func new(_ eid: String) {
//Create Animal Entity
let container = CoreDataService.persistentContainer
container.performBackgroundTask { (context) in
let mo = Animal(context: context)
mo.eid = eid
mo.lastModified = Date()
mo.purchaseDate = Date()
mo.uuid = UUID()
do {
try context.save()
}
catch let error {
print(error)
}
}
}
The problem I am having is I need to return the newly created NSManagedObject (Animal) back to the manager class, where the Animal.new(eid) was called, to be used to show the object properties.
I have experimented with using a completion handler, but had issues returning the value, as was using a background NSManagedObject in the main thread.
Using possible new function
Animal.new(eid) { (animal) in
if let animal = animal {
}
What is the best approach for returning a newly created NSManagedObject, created in a background context?
What I do is to keep my CoreData managed objects within my CoreDataManager class, not exposing them out to the rest of my framework. So methods that are to create one or more managed objects would accept the data as an unmanaged object, and then create the managed object but not return it (as callers already have the unmanaged object). When fetching from the CoreDataManager, I'd create and populate a unmanaged object(s) and return that.
Now part of why I do this is because I'm using CoreData in a framework, such that I'd never want to hand a managed object to a client app of my framework. But it also solves other problems like the one you described.
(When I write apps, I use Realm, and those objects can go straight to app's UI classes because Realm is so much easier to, erm, manage. :)

Private attributes/properties and Core Data

I am attempting to transform one of my model objects into a Core Data managed Entity, the object has a private list of sub-objects.
I don't want users of the object to be able to access the list, but instead create, update and calculate values using the business logic in the object, something akin to:
struct MyObject {
private let listOStuff: [String]
func updateBusinessLogic(value: String): MyObject {
// business logic here
return ... // new version of MyObject
}
}
I understand I can use an extension to add the required business logic to the managed object; but is Core Data able to handle the property/attribute being private?
Thanks
PS this is the closest answer I can see to my problem, but I don't think it is the same.

Need help understand interfaces and/or abstract classes in angular2

I am new to the angular2 world. I am trying to create interfaces for certain components and then implement these interfaces in my models so I can make sure they will be able to work properly.
One thing I have noticed is that if I create new instances of these objects they work fine but when I pull data from a restful call, I use the type casting to turn the data into the type of object I expect. The following code is a pseudo example.
I come from a Java/C++ background so I am hoping someone can see what I'm trying to do and explain to me how to get this working correctly.
Thanks In Advance!
Doesn't work ---
private vehicles: Vehicle[];
this._vehicleService.loadVehicles().subscribe(
vehicles => this.vehicles = <Vehicle[]>vehicles);
Does Work ---
vehicles : Vehicle[];
vehicles.push(new Vehicle(1, 'Old Junker'));
vehicles.push(new Vehicle(2, 'Old Junker2'));
Example class/interface setup.
#Component
export class SelectableComponent {
options : Selectable[]
// Access options.label and options.value
}
export interface Selectable {
label(): string;
value(): any;
}
export class Vehicle implements Selectable {
constructor (
public id: number,
public description: string,
){}
get label() : any {
return this.description;
}
get value() : any {
return this.id;
}
}
What happens here is that the object retrieved from the backend is just a plain Javascript object that gets cast to a Vehicle:
this._vehicleService.loadVehicles().subscribe(
vehicles => this.vehicles = <Vehicle[]>vehicles);
Objects in this array will have all the data of a Vehicle, but none of the behavior of an instance of the Vehicle class, which can be quite confusing as you mention.
The simplest is instead of casting them, calling new and creating an instance of Vehicle immediately while retrieving them from the backend.
But using a long constructor call can be cumbersome, especially if Vehicle has a lot of properties and you need to pass them all to the constructor one by one.
A way to fix this is to create an auxiliary method in the Vehicle class:
class Vehicle {
constructor(private name, private year) {
}
static fromJson({name,year}) {
return new Vehicle(name, year);
}
}
And then use it in return from the backend to create an array of Vehicles, instead of casting them:
this._vehicleService.loadVehicles().subscribe(
vehicles => this.vehicles = vehicles.map(Vehicle.fromJson));
This way the vehicles in the result will have not only all the data of a vehicle, but also the behavior of the Vehicle class, because they are instances on Vehicle.
The main difference between classes and interfaces in TypeScript is that interfaces don't exist at runtime. They are "only" there for compilation and type checking.
Casting an element to an interface / class "only" tells TypeScript that the object follows the structure of it but it's not actually an instance of the type. It's a bit disturbing at a first sight. The main consequence (in the case of a class) is that casting doesn't allow you to use methods of the class.
I already casted this way:
private vehicles: Vehicle[];
this._vehicleService.loadVehicles().subscribe(
vehicles => this.vehicles = <Vehicle[]>vehicles);
What is the exact compilation error you have?

Mocking singleton/sharedInstance in Swift

I have a class that I want to test using XCTest, and this class looks something like this:
public class MyClass: NSObject {
func method() {
// Do something...
// ...
SingletonClass.sharedInstance.callMethod()
}
}
The class uses a singleton that is implemented as this:
public class SingletonClass: NSObject {
// Only accessible using singleton
static let sharedInstance = SingletonClass()
private override init() {
super.init()
}
func callMethod() {
// Do something crazy that shouldn't run under tests
}
}
Now for the test. I want to test that method() actually does what it is supposed to do, but I don't want to invoke the code in callMethod() (because it does some horrible async/network/thread stuff that shouldn't run under tests of MyClass, and will make the tests crash).
So what I basically would like to do is this:
SingletonClass = MockSingletonClass: SingletonClass {
override func callMethod() {
// Do nothing
}
let myObject = MyClass()
myObject.method()
// Check if tests passed
This obviously isn't valid Swift, but you get the idea. How can I override callMethod() just for this particular test, to make it harmless?
EDIT: I tried solving this using a form of dependency injection, but ran into big problems. I created a custom init-method just to be used for tests such that I could create my objects like this:
let myObject = MyClass(singleton: MockSingletonClass)
and let MyClass look like this
public class MyClass: NSObject {
let singleton: SingletonClass
init(mockSingleton: SingletonClass){
self.singleton = mockSingleton
}
init() {
singleton = SingletonClass.sharedInstance
}
func method() {
// Do something...
// ...
singleton.callMethod()
}
}
Mixing in test code with the rest of the code is something I find a bit unpleasing, but okay. The BIG problem was that I had two singletons constructed like this in my project, both referencing each other:
public class FirstSingletonClass: NSObject {
// Only accessible using singleton
static let sharedInstance = FirstSingletonClass()
let secondSingleton: SecondSingletonClass
init(mockSingleton: SecondSingletonClass){
self.secondSingleton = mockSingleton
}
private override init() {
secondSingleton = SecondSingletonClass.sharedInstance
super.init()
}
func someMethod(){
// Use secondSingleton
}
}
public class SecondSingletonClass: NSObject {
// Only accessible using singleton
static let sharedInstance = SecondSingletonClass()
let firstSingleton: FirstSingletonClass
init(mockSingleton: FirstSingletonClass){
self.firstSingleton = mockSingleton
}
private override init() {
firstSingleton = FirstSingletonClass.sharedInstance
super.init()
}
func someOtherMethod(){
// Use firstSingleton
}
}
This created a deadlock when one of the singletons where first used, as the init method would wait for the init method of the other, and so on...
Your singletons are following a very common pattern in Swift/Objective-C code bases. It is also, as you have seen, very difficult to test and an easy way to write untestable code. There are times when a singleton is a useful pattern but my experience has been that most uses of the pattern are actually a poor fit for the needs of the app.
The +shared_ style singleton from Objective-C and Swift class constant singletons usually provide two behaviors:
It might enforce that only a single instance of a class can be instantiated. (In practice this is often not enforced and you can continue to alloc/init additional instances and the app instead depends on developers following a convention of exclusively accessing a shared instance via the class method.)
It acts as a global, allowing access to a shared instance of a class.
Behavior #1 is occasionally useful while behavior #2 is just a global with a design pattern diploma.
I would resolve your conflict by removing the globals entirely. Inject your dependencies all of the time instead of just for testing and consider what responsibility that exposes in your app when you need something to coordinate whatever set of shared resources you're injecting.
A first pass at injecting dependencies throughout an app is often painful; "but I need this instance everywhere!". Use it as a prompt to reconsider the design, why are so many components accessing the same global state and how might it be modeled instead to provide better isolation?
There are cases where you want a single copy of some mutable shared state and a singleton instance is perhaps the best implementation. However I find that in most examples that still doesn't hold true. Developers are usually looking for shared state but with some conditions: there's only one screen until an external display is connected, there's only one user until they sign out and into a second account, there's only one network request queue until you find a need for authenticated vs anonymous requests. Similarly you often want a shared instance until the execution of the next test case.
Given how few "singleton"s seem to use failable initializers (or obj-c init methods which return an existing shared instance) it seems that developers are happy to share this state by convention so I see no reason not to inject the shared object and write readily testable classes instead of using globals.
I eventually solved this using the code
class SingletonClass: NSObject {
#if TEST
// Only used for tests
static var sharedInstance: SingletonClass!
// Public init
override init() {
super.init()
}
#else
// Only accessible using singleton
static let sharedInstance = SingletonClass()
private override init() {
super.init()
}
#endif
func callMethod() {
// Do something crazy that shouldn't run under tests
}
}
This way I can easily mock my class during tests:
private class MockSingleton : SingletonClass {
override callMethod() {}
}
In tests:
SingletonClass.sharedInstance = MockSingleton()
The test-only code is activated by adding -D TEST to "Other Swift Flags" in Build Settings for the app test target.
I had a similar issue in my app, and in my case it made sense to use Singletons for these particular services as they were proxies for external services that were also singletons.
I ended up implementing a Dependency Injection model using https://github.com/Swinject/Swinject. It took about a day to implement for about 6 classes which seems like a lot of time to enable this level of unit testability. It did make me think hard about the dependencies between my service classes, and it made me more explicitly indicate these in the class definitions. I used the ObjectScope in Swinject to indicate to the DI framework that they're singletons: https://github.com/Swinject/Swinject/blob/master/Documentation/ObjectScopes.md
I was able to have my singletons, and pass in mock versions of them to my unit tests.
Thoughts on this approach: it seems more error prone as I could forget to initialize my dependencies correctly (and would never receive a runtime error). Finally, it doesn't prevent someone from just instantiating a instance of my Service class directly (which was sort of the whole point of the singleton), since my init methods had to be made public for the DI Framework to instantiate the objects into the registry.
I would suggest to make init not private (quite not convenient), but don't see better solution for now that object can be tested, if you need to simulate multi calls of initializing of the data type.