I want to find a way to make my UnityContainer create instances that inherit from DispatcherObject on the UI thread. Basically this is what I want:
if (objectType is DispatcherObject)
{
Application.Current.Dispatcher.Invoke(
// DO BUILDUP HERE
);
}
else
{
// DO BUILDUP HERE
}
Looking at the Unity source code I can't find a good way to do this. My best option so far is to register a static factory for every instance I want to push to the UI thread but I would like all DispatcherObject derived classes to be created on the UI thread.
Related
I am trying to get my head round how i can achive the following using the MVVM design pattern with SwiftUI.
I want to have only 1 instance of a networking operation queue (using OperationQueue) where any view model that needs to send any networking requests but i have heard that creating a Singleton is not preferred and i should be passing the networking queue object around where it is needed.
So if i create the instance of the network operation queue in the Scene Delegate and pass them into the ContentView initialiser and store it in an object there to then pass into the views then created.
This doesnt seem like good MVVM design practice as from what i understand the View should Own the ViewModel only?
What is the best way of achieving this?
Edit: thought a bit more about this and I can pass it into the view via its constructor and then within the constructor I can create the view model and pass it straight through so the view doesn’t own anything.
But I still will require a singleton so how can I pass the singleton as a dependency injection rather than using it globally?
Thanks
We shouldn’t create singletons for the single reason of being an easy way to get global variables, but it doesn’t mean we should never use them.
In your case, if I understood correctly, you are basically creating a service that can be used by the entire application. You could either A) create a reusable class with the networking functions you need (and instantiate anywhere you need it) or B) create a class with a singleton instance in it, that can be easily accessed anywhere.
A singleton would be a better choice if you need to keep some state common to all callers, or if you need to maintain a waiting queue, for example.
Option A
class NetworkService {
init() {
// init
}
// Your properties and methods
func someFunction() {}
}
Usage in a ViewModel:
let networkService = NetworkService()
networkService.someFunction()
Option B
class NetworkService {
static let shared = NetworkService()
private let queue : Any?
// Your properties and methods
func someFunction() {}
}
Usage:
NetworkService.shared.someFunction()
Either way, this is still MVVM. The data is not related to any specific view, nor to a specific model; it's simply a service you would call in any ViewModel that needs it.
I use NSPersistentContainer as a dependency in my classes. I find this approach quite useful, but there is a dilemma: I don't know in which thread my methods will be called. I found a very simple solution for this
extension NSPersistentContainer {
func getContext() -> NSManagedObjectContext {
if Thread.isMainThread {
return viewContext
} else {
return newBackgroundContext()
}
}
}
Looks wonderful but I still have a doubt is there any pitfalls? If it properly works, why on earth Core Data confuses us with its contexts?
It's OK as long as you can live with its inherent limitations, i.e.
When you're on the main queue, you always want the viewContext, never any other one.
When you're not on the main queue, you always want to create a new, independent context.
Some drawbacks that come to mind:
If you call a method that has an async completion handler, that handler might be called on a different queue. If you use this method, you might get a different context than when you made the call. Is that OK? It depends what you're doing in the handler.
Changes on one background context are not automatically available in other background contexts, so you run the risk of having multiple contexts with conflicting changes.
The method suggests a potential carelessness about which context you're using. It's important to be aware of which context you're using, because managed objects fetched on one can't be used with another. If your code just says, hey give me some context, but doesn't track the contexts properly, you increase the chance of crashes from accidentally crossing contexts.
If your non-main-queue requirements match the above, you're probably better off using the performBackgroundTask(_:) method on NSPersistentContainer. You're not adding anything to that method here.
[W]hy on earth Core Data confuses us with its contexts?
Managed object contexts are a fundamental part of how Core Data works. Keeping track of them is therefore a fundamental part of having an app that doesn't corrupt its data or crash.
In my iOS app, I have user data that gets loaded from the network and saved as a plain Objective-C object which persists its data into NSUserDefaults. I need to be able to log out the current user and remove it, then log in a new user and start using that one instead throughout the app. Right now it is just a singleton I'm calling UserManager, with a method -(User)currentUser.
I'm transitioning to using Typhoon framework in my (http://typhoonframework.org) for dependency injection. What is the right way to store the user data? I know I could keep my UserManager class, inject it everywhere I need it via Typhoon, and set it as Typhoon type definition.scope = TyphoonScopeSingleton;.
But if I do this, isn't it still just a singleton? I know it's a little better because it's injected into classes rather than hidden in their implementation. But, it seems like there should be a better way to just keep a User object somewhere and inject whichever the current one is, without wrapping it in an [injected] singleton with a getter.
Thanks.
Thanks for using Typhoon!
If I understand you correctly, you need doing injecting of currentUser to your classes like as:
#implementation Assembly
- (User *)currentUser
{
return [TyphoonDefinition withFactory:[self userManager] selector:#selector(currentUser)];
}
- (UserManager *)userManager
{
return [TyphoonDefinition withClass:[UserManager class] configuration:^(TyphoonDefinition *definition) {
definition.scope = TyphoonScopeSingleton;
}];
}
I'm using GCD to add thread-safety to a class.
Some public methods of my class are called by other public methods in the class. However, this leads to the re-entrant locking problem: if I protect the appropriate publicly visible methods with synchronous GCD blocks (in some cases), the re-use means sometimes I'll be trying to run anther synchronous block on the current queue, which leads to deadlock.
What's the most elegant solution? An obvious approach is to have internal versions of the appropriate methods, without any GCD blocks, and external public versions of the method that have the GCD blocks wrapping calls to the interal methods. This doesn't quite feel right to me.
Here are a few thoughts:
See if you can't use immutable objects. This means that whenever a method would modify the object it actually returns a new object with the modified state. The blocks would then go on and use this new object. This is simple, requires no special care but is not always possible.
See if your public methods can't use private methods that carry around state. Since each block would carry around its own internal state then you are also thread safe.
If you had some example use case it might lead to a more ideas...
I've used a pattern like this very successfully in our C++ classes that use dispatch queues for synchronization:
class Foo
{
public:
void doSomething() {
dispatch_sync(fQueue, ^{ doSomething_sync(); });
}
private:
void doSomething_sync() { ... }
private:
dispatch_queue_t fQueue;
};
The general convention here is that for any given _sync method in a class, you only call other _sync methods and not their non _sync public counterpart.
I have a singleton implemented in my app, but I've run into a problem when I switch between view controllers.
My app starts in one view controller, MainMenu, then switches to the Game view controller when the menu selection is made. I have a singleton class in the Game VC that is the object manager (called World) for the game. It loads content based on the menu selection in MainMenu. I can load up and quit back to the MainMenu VC fine. Singleton works fine. When I select from the MainMenu again (going from MainMenu VC to Game VC), my app crashes cause of an NSAssert to prevent the singleton World from allocating a second time, which is intentional.
How can I switch back to the Game VC without it trying to reinitialize my singleton?
Essentially, I want to skip the [[world alloc] init] line in my Game VC's init method. I can't figure out how to do this properly... it would need to be able to be handled the first time (when World doesn't exist) or any subsequent time (when World already exists as a singleton). I've tried if (!world) and that doesn't work.
This also begs the question... did I implement my singleton in the right place? Should I perhaps put it in the MainMenu instead? I just want to avoid it trying to reinitialize / reallocate the singleton when I switch between the two VCs.
If this helps, I'm exiting the Game VC by using [self.view removeFromSuperview]; Should I do it a different way?
If I understand the question correctly, you'd like to know how to create a Singleton class? A common way in recent times is to use grand-central-dispatch, as follows:
+ (MyViewController*)shared
{
static dispatch_once_t onceToken;
static MyViewController* instance;
dispatch_once(&onceToken, ^
{
instance = [[[self class] alloc] init];
});
return instance;
}
you can then access the instance with:
[MyViewController shared];
Before grand-central-dispatch, the technique was to put a static instance on the class and check if it's nil when calling the shared accessor. And the accessor would need to be wrapped with #synchronized(self) to ensure thread-safety. The GCD way has been shown to perform a little better.
Having said that, I recommend that you use singletons with volition. Do some research on why they're considered an anti-pattern, and investigate dependency injection as an alternative.
Dependency Injection vs Singletons
The problem with singletons is that they can lead to tight coupling. Let's say you're building an airline booking system. Your booking controller might use an:
id<FlightsClient>
A common way to obtain it within the controller would be as follows:
_flightsClient = [FlightsClient sharedInstance];
In order to test a class using the singleton, you now have to test the singleton at the same time, and this can get tricky, especially as your application gets more complex. Imagine testing Class A, depends on Class B, depends on Class C, depends on .... Not much fun!
An alternative is to use dependency injection, which simply means to pass the booking client to the booking controller using an initializer or property setter. You can do this manually or use a library for it. If you do it manually its still OK to declare the singleton, although arguably you will not need to as the top-level assembly class can retain the instance.
By using this alternative approach to singletons, classes will have loose coupling, and will be easy to test and maintain. (And with Dependency Injection, you'll have an equally fancy name ;) )
I wrote a dependency injection library, based on Spring: https://github.com/jasperblues/spring-objective-c
I was able to solve this by indeed moving the singleton initialization up into the MainMenu view controller as I was thinking. In my design, init for that VC is only called once upon app startup, whereas the custom init method in my Game VC gets called each time I switch to it.
Not sure if that's the optimal design I should be using, but it works for now.