I'm experiencing a strange issue with WatchOS (but I suppose that this problem is similar with iOS and OSX).
I'm using a singleton to handle a WCSession delegate (The full code is by NatashaTheRobot, I paste here only a portion of her code, the full code is here ).
This class has a startSession function where the singleton is associated as delegate of the session:
func startSession() {
session?.delegate = self
session?.activateSession()
}
and all the delegate functions are defined inside the same class, like session:didReceiveMessage:replyHandler:
I'd like to be able to have the delegate called every time that the Watch app receives a message independently by the current InterfaceController.
I thought that a good place to achieve this goal might be the ExtensionDelegate class:
class ExtensionDelegate: NSObject, WKExtensionDelegate {
let session = WatchSessionManager.sharedManager // THE SINGLETON INSTANCE
func applicationDidFinishLaunching() {
session.startSession()
}
it seems that this code is not working and the delegate function are never called.
Then I decided to go for a less generic way and I started adding the reference to the singleton instance inside all the InterfaceController... but again it doesn't work and delegate methods are never been called.
Then, in my last attempt, I've implemented the session delegate protocol directly inside the InterfaceController code. In that case I receive the messages from the iOS app... it was working correctly (obviously only when the watch app is presenting that specific InterfaceController).
My question are: why implementing a generic singleton object doesn't work? Why I have to implement the delegate directly on the InterfaceController to make it work?
Try moving the startSession call from the ExtensionController's applicationDidFinishLaunching to its init method. The init gets called no matter which context (complication, app, glance, notification, etc) the extension is being loaded for.
Related
To start, let me say that I have read several questions here about SingleInstance, but still cannot find a direct answer that helps me. That said, I apologize if I missed anything.
Here's my question:
I am building a Xamarin Forms app for iOS and Android. I have a single AppInitializer class in a PCL where I register all of my interface dependencies using Autofac. I then assign the Container from the builder as a static property on the app class. The problem I encounter is that while I'm registering everything with .SingleInstance(), I'm not actually getting a single instance.
Init Logic Example:
var builder = new ContainerBuilder();
builder.RegisterType<ErrorHandler>().SingleInstance().As<IErrorHandler>();
…
builder.RegisterType<MemberViewModel>().SingleInstance().As<IMemberViewModel>();
…
AppContainer.Current = builder.Build();
I am letting Autofac handle resolving interfaces in my constructors. For example:
public MemberViewModel(ISettingsViewModel settings, IErrorHandler errorHandler, …) : base(settings, errorHandler){…}
I then use said model on a page as below:
Example page usage:
public ProfilePage()
{
InitializeComponent();
var displayModel = Model.CurrentMember;
…
}
…
**public IMemberViewModel Model =>
AppContainer.Current.Resolve<IMemberViewModel>();**
In this example I set Model.CurrentMember's properties immediately before arriving on this page. I've set breakpoints and know for a fact this is happening. However, when I resolve the instance of the model, the properties on CurrentMember are null.
Am I doing something wrong here or have I encountered a bug?
-Edit-
Made it clear that I'm using Autofac.
-Edit 2-
Adding more detail.
My implementation of the IMemberViewModel class has various properties on it, including an observable object called current member. It is declared as below:
public class MemberViewModel : ViewModelBase, IMemberViewModel
{
…
(see constructor above)
…
public MemberDisplay CurrentMember =>
m_CurrentMember ?? (m_CurrentMember = new MemberDisplay())
On the implementation of IMemberViewModel I have a method that sets the various properties on CurrentMember.
The order of operations is this:
The end user taps an image for a member. This fires a command on the (theoretically) singleton instance of the IMemberViewModel implementation. This command executes an async task that awaits an async call to the API to load the data for that member. After that data is loaded and the properties set on CurrentMember, the app navigates to the profile screen. The profile screen resolves IMemberViewModel (per above).
Expected Behavior:
The properties on CurrentMember from the resolved instance of IMemberViewModel are set to the values that have just been set from the load data method. This expectation arises from assuming that there is a single instance of IMemberViewModel.
Actual Behavior:
The CurrentMember's properties are at their default values, i.e. string.Empty, 0, null, etc.
The odd thing here is that this doesn't happen to every model. I have a message model that I am resolving in the same manner on the same screen and it seems to be fine.
This issue turned out to be caused by the way we were going about initializing everything. For posterity's sake, I will give a brief breakdown of what was happening and what I did to prevent it.
Previous App Flow:
App opens & constructor is called. This calls into the initialization routine above.
User logs in.
First instance of IMemberViewModel resolved using static container.
A message pops up asking the user for Push Notifications Permissions
When this happens, the app OnSleep is called (iOS)
After the user selects an answer, OnResume is called.
OnResume calls initialization routine
New container created.
Call to load data happens on old container, new pages reference new container.
Issue arises as described above.
Correction to the flow:
First, from what I can tell the init calls do not need to be made on resume and/or start if made in the app constructor. If the app is "killed" because other apps need the memory space, a fresh version of the app will be created on next launch (see the Android Activity Lifecycle and the iOS App Lifecycle).
Second, because I'm paranoid and because it can't hurt, in the app init routine I am now checking to determine whether the container exists and whether the interface is already registered.
public static void Init(ISetup setup)
{
if (Container != null && IsModelRegistered()) return;
RegisterDependencies(setup);
…
}
private static bool IsModelRegistered()
{
return Container.IsRegistered<IMemberViewModel>();
}
I subclass NSOperation to implement my operation.Let's call it MyOperation.
In the implementation of MyOperation, I override the main function and inside it I create some async network stuff and set the delegate to self(the operation object).But the operation objects never get those delegate callbacks, why? I didn't set finished before the callback are received.
Or does NSOperation just can't do that?
I find that if I manually "start" the operation, it will work. But if I add it to a operation queue, the operation is excuted but just can't get those callbacks.
If you're setting up your callback in the main method like this:
-(void)main{
// setup
object.delegate = self
}
then your main method will continue execution, complete, and go away before the delegate has a chance to complete the callback. You either need to override the start method in NSOperation and manually handle the isFinished and isExecuting properties, or you need to figure out a way to have the delegate method get called on an object that isn't going away.
See the NSOperation class reference for full details on overriding the proper methods and KVC notifications to make it work.
Do anyone know how to see the event listeners of any component in the debug mode of the Flex or Flash builder?
Cheers,PK
There is no straightfoward way to enumerate listeners AFAIK.
You can still do what you would usually have to do with methods from the IEventDispatcher interface:
package flash.events
{
public interface IEventDispatcher
{
function addEventListener(eventName:String,
listener:Object,
useCapture:Boolean=false,
priority:Integer=0,
useWeakReference:Boolean=false):Boolean;
function removeEventListener(eventName:String,
listener:Object,
useCapture:Boolean=false):Boolean;
function dispatchEvent(eventObject:Event):Boolean;
function hasEventListener(eventName:String):Boolean;
function willTrigger(eventName:String):Boolean;
}
}
Source of the above code: http://livedocs.adobe.com/flex/3/html/help.html?content=16_Event_handling_6.html
create a variable on the class called:
private var __numListeners:Number=0;
then create a set and get method to edit that variable...
and each time a listener is added or removed it adjusts that var using that method...
this.setNumListeners(1); or whatever
then it can be accessed through a
trace(someObject.getNumListeners())
There is no quick way to do this without editing all of the components in your app that implement the IEventDispatcher interface.
If the player was open source then you could extend the EventDispatcher class to add trace statements into it, but it isn't.
Currently I'm working on an application (Flex) which heavily uses external SWFs.
I'd like to create a static method which takes a filename as an argument and returns SWF wrapped in some other class.
public static function getSWFWrapperFromFile(path:string):SWFWrapper {
var loader:SWFLoader = new SWFLoader();
loader.addListener(Event.COMPLETE, onLoad);
loader.load(path);
// If I create new SWFWrapper object here and try to assign it the loader.content I get null reference
}
However, with this approach I'm not able to encapsulate logic in one function, because of non-blocking load() and the need of onLoad handler. Is there possibility to force a delay after calling load method? Or mayber there is another, better way?
Thank you,
Alonzo
The display list is well-designed for asynchronous loading. You'll notice that Loader is a DisplayObject-derived class and thus can be placed directly in the display list. When its content is loaded it will be a child of the Loader. Thus, if SWFWrapper is DisplayObject-derived, you can simply do the following at the end of your code:
var wrapper:SWFWrapper = new SWFWrapper();
wrapper.addChild(loader);
return wrapper;
You need to wait until your Loader object has completed. Try adding in an event handler. Yes, the whole thing gets murky after a point of time when you have multiple loaders and and have to wait till the last one has completed. But that's the way it is if you are going to use SWFLoader.
In flash you cannot block in a method - you always have to use the onLoad handler for loading data. (The as3 execution model is single threaded, if you block in a method the rest of the program will not get executed)
Like others said, you can't do that. However, take a look at the BulkLoader AS3 library, which takes the burden of managing multiple loaders simultaneously and waiting for their completion, off your shoulder. It is well documented, and requires only a few lines to use.
I've been utilizing the command pattern in my Flex projects, with asynchronous callback routes required between:
whoever instantiated a given command object and the command object,
the command object and the "data access" object (i.e. someone who handles the remote procedure calls over the network to the servers) that the command object calls.
Each of these two callback routes has to be able to be a one-to-one relationship. This is due to the fact that I might have several instances of a given command class running the exact same job at the same time but with slightly different parameters, and I don't want their callbacks getting mixed up. Using events, the default way of handling asynchronicity in AS3, is thus pretty much out since they're inherently based on one-to-many relationships.
Currently I have done this using callback function references with specific kinds of signatures, but I was wondering if someone knew of a better (or an alternative) way?
Here's an example to illustrate my current method:
I might have a view object that spawns a DeleteObjectCommand instance due to some user action, passing references to two of its own private member functions (one for success, one for failure: let's say "deleteObjectSuccessHandler()" and "deleteObjectFailureHandler()" in this example) as callback function references to the command class's constructor.
Then the command object would repeat this pattern with its connection to the "data access" object.
When the RPC over the network has successfully been completed (or has failed), the appropriate callback functions are called, first by the "data access" object and then the command object, so that finally the view object that instantiated the operation in the first place gets notified by having its deleteObjectSuccessHandler() or deleteObjectFailureHandler() called.
I'll try one more idea:
Have your Data Access Object return their own AsyncTokens (or some other objects that encapsulate a pending call), instead of the AsyncToken that comes from the RPC call. So, in the DAO it would look something like this (this is very sketchy code):
public function deleteThing( id : String ) : DeferredResponse {
var deferredResponse : DeferredResponse = new DeferredResponse();
var asyncToken : AsyncToken = theRemoteObject.deleteThing(id);
var result : Function = function( o : Object ) : void {
deferredResponse.notifyResultListeners(o);
}
var fault : Function = function( o : Object ) : void {
deferredResponse.notifyFaultListeners(o);
}
asyncToken.addResponder(new ClosureResponder(result, fault));
return localAsyncToken;
}
The DeferredResponse and ClosureResponder classes don't exist, of course. Instead of inventing your own you could use AsyncToken instead of DeferredResponse, but the public version of AsyncToken doesn't seem to have any way of triggering the responders, so you would probably have to subclass it anyway. ClosureResponder is just an implementation of IResponder that can call a function on success or failure.
Anyway, the way the code above does it's business is that it calls an RPC service, creates an object encapsulating the pending call, returns that object, and then when the RPC returns, one of the closures result or fault gets called, and since they still have references to the scope as it was when the RPC call was made, they can trigger the methods on the pending call/deferred response.
In the command it would look something like this:
public function execute( ) : void {
var deferredResponse : DeferredResponse = dao.deleteThing("3");
deferredResponse.addEventListener(ResultEvent.RESULT, onResult);
deferredResponse.addEventListener(FaultEvent.FAULT, onFault);
}
or, you could repeat the pattern, having the execute method return a deferred response of its own that would get triggered when the deferred response that the command gets from the DAO is triggered.
But. I don't think this is particularly pretty. You could probably do something nicer, less complex and less entangled by using one of the many application frameworks that exist to solve more or less exactly this kind of problem. My suggestion would be Mate.
Many of the Flex RPC classes, like RemoteObject, HTTPService, etc. return AsyncTokens when you call them. It sounds like this is what you're after. Basically the AsyncToken encapsulates the pending call, making it possible to register callbacks (in the form of IResponder instances) to a specific call.
In the case of HTTPService, when you call send() an AsyncToken is returned, and you can use this object to track the specific call, unlike the ResultEvent.RESULT, which gets triggered regardless of which call it is (and calls can easily come in in a different order than they were sent).
The AbstractCollection is the best way to deal with Persistent Objects in Flex / AIR. The GenericDAO provides the answer.
DAO is the Object which manages to perform CRUD Operation and other Common
Operations to be done over a ValueObject ( known as Pojo in Java ).
GenericDAO is a reusable DAO class which can be used generically.
Goal:
In JAVA IBM GenericDAO, to add a new DAO, the steps to be done is simply,
Add a valueobject (pojo).
Add a hbm.xml mapping file for the valueobject.
Add the 10-line Spring configuration file for the DAO.
Similarly, in AS3 Project Swiz DAO. We want to attain a similar feet of achievement.
Client Side GenericDAO model:
As we were working on a Client Side language, also we should be managing a persistent object Collection (for every valueObject) .
Usage:
Source:
http://github.com/nsdevaraj/SwizDAO