Flex: PopUpManager giving "...null object reference" error - apache-flex

I have a main application calling several ViewStack states, each with popup windows. If I don't open any popup windows, I can move between states fine. If I open a popup window then try to change the state using currentState=... I get the error:
TypeError: Error #1009: Cannot access a property or method of a null object reference.
at spark.components::Scroller/focusInHandler()[E:\dev\4.y\frameworks\projects\spark\src\spark\components\Scroller.as:2139]
at flash.display::Stage/set focus()
at mx.core::UIComponent/setFocus() [E:\dev\4.y\frameworks\projects\framework\src\mx\core\UIComponent.as:9905]
...
I see others having the same problem, for example here:
http://forums.adobe.com/thread/1031531
http://forums.adobe.com/message/2767130
http://forums.adobe.com/message/3448443
http://forums.adobe.com/thread/655749?tstart=-1
http://forums.adobe.com/thread/801149
http://flex4examples.wordpress.com/2011/05/05/skinnabletextbase-focusmanager-runtime-error-popup/
http://bugs.adobe.com/jira/browse/SDK-32036?page=com.atlassian.jira.plugin.system.issuetabpanels%3Aall-tabpanel
But I haven't figured out how to implement the recommended solution. It sounds like I should just include:
import mx.managers.PopUpManager; PopUpManager;
inside my main application and it should work, but it doesn't work for me.
My application has each view state in a different file, each defined using <views:View>. Also, all of the popups are separate files defined as <s:TitleWindow>. Each file includes this line:
import mx.managers.PopUpManager;
I wonder if this means each file is using a different popup manager(?), when it's a singleton and only one should be used for the whole app (how to set that up?).
The code I use to call a popup is:
var _popupName:MyTitleWindowFileName = MyTitleWindowFileName(
PopUpManager.createPopUp(this, MyTitleWindowFileName, true));
_popupName.addEventListener(MyAppController.CLOSE_POPUP,onClosePopUp);
PopUpManager.centerPopUp(_popupName); // call popup
Note that when the main application (the one defined as <s:Application>) runs, the ViewStack states have not been loaded yet (since they get loaded when they are used the first time). Not sure if that has any cause/effect here.
I've tried to follow Adobe's example code in the "Passing data to and from a Spark pop-up window" section here:
http://help.adobe.com/en_US/flex/using/WS6c678f7b363d5da52e8f1ca1124a0430dcf-8000.html#WS6c678f7b363d5da52e8f1ca1124a0430dcf-7ffe
Any ideas much appreciated.

Based on your comments, it seems like the error occurs because the focus remains in the popup. I would expect the PopUpManager and FocusManager classes to handle this better.
One thing I can think of is that the FocusManager may be trying to handle this. But since the state changes, the item that originally had focus (in the view stack child, before the pop up was opened) may no longer be there when the view state changes. Just a hunch, w/out seeing your code.
Here's some things you can do to either work around the problem (or better) further debug it to understand what is happening:
Use FocusManager.setFocus() to move the focus back to an object in the view stack child before closing the pop up
Use FocusManager.getFocus() to debug and see where it thinks the focus is at various stages (before opening popup, before/after changing state, and before/after closing pop up).

It appears this is the situation I'm experiencing:
Adobe Air: scroller throws error when changes focus between different applications
It's an Adobe bug. Solution from Adobe is:
This bug is easily fixed by changing Scroller to do a null pointer check on focusManager before using it.
which is what the first link above attempts to do.
Another link: http://forums.adobe.com/message/3812805

Related

Custom button for cocos2d

I was working on creating my custom "Button" class... Im not using CCMenuItems because I need some flexibility in my buttons.
My implementation is the following:
DMenuButton : CCSprite <CCTargetedTouchDelegate>
When created, the button receives a target and selector, and builds an NSInvocation. When touched, the invocation is called. I will use this buttons mainly to go from one layer to another.
The problem is that when going from a layer to the next, and then back to the previous, something strange occurs: either no sprites are loaded into the next view or an EXC_BAD_ACCESS error is thrown.
Can anyone help me with this?
Thanks!
PS: My theory is that it has to do with the NSInvocation and the "dealloc" method.
Am I doing something wrong?

Flex - How to get the parent of a custom grid column filter editor and open a pop up window?

I am trying to figure out how to open a pop up window in my Air application, in a secondary Window, instead of the main application window.
I am using the ReusableFX components, which include a custom DataGrid with filtering and other capabilities. The filtering feature displays a pop up window via PopUpManager when you click on the top of a column in the grid.
PopUpManager.addPopUp(this, FlexGlobals.topLevelApplication as DisplayObject);
The problem is that the pop up window opens in the main application - I am assuming because of the 'topLevelApplication' reference.
So, I need a way to open this window in the current Air "s:Window".
I am assuming I need a way to walk up : this.parent.parent or this.owner.owner - though I have tried that and it did not seem to work (it said null reference).
OR, is there a way to get the current top most window / component (NOT the main application / window)?
Update:
I decided to create a new project for the component, and add in the Air libraries. Now I am able to access the "NativeApplication.nativeApplication.activeWindow" call. That gives me the correct Air window. However, it does not seem to be working:
PopUpManager.addPopUp(this, NativeApplication.nativeApplication.activeWindow as DisplayObject);
My popup does not appear. I am assuming because "activeWindow" is not actually a DisplayObject? (so how do I get the DisplayObject if that's the case?)
Update:
Could it be that I am a victim of this adobe bug? (found here originally)
Well, I came up with some changes that seem to work, though there is probably a much cleaner way to do this - I was just not able to figure a way to get a reference to the current air application window except this way (this is using the ReuableFX custom flex component by the way):
First, in my custom DataGridColumn component, I added a public property
public var pApp:Object;
Next, I modified the DropDownFilterHeaderRenderer (extends HBox , implements IListItemRenderer), showFilterDropDown method and right before it calls dropDown.startEdit(column); , added:
column.pApp = parentApplication;
Finally, I modified DropDownFilterEditor (which extends FilterEditorBase), the method startEdit(column:MDataGridColumn) (the previous PopUpManager was calling FlexGlobals.topLevelApplication, which is not the correct window when opening a s:Window in an Air native application:
var editorInstance:Object = _editor.parent;
var columnInstance:Object = editorInstance.column;
var parAppInstance:Object = columnInstance.pApp;
PopUpManager.addPopUp(this, parAppInstance as DisplayObject);

Sometimes willHideViewController from UISplitViewControllerDelegate is not called

I have a problem.
My app is a tab bar controller and its first view controller is a split view controller.
This seems to be not ok for Apple because documents say a split voew controller must be the root, so perhaps that is the reason of my problems.
The problem is that sometimes, willHideViewController from UISplitViewControllerDelegate is not called, so, for this reason, the upper/left button sometimes is not created, which is anoying.
I realised, to reproduce this error, try several times this:
-Landscape mode.
-Select a tab different to split view controller tap.
-Move the iPad to portrait in that tab.
-Go to the split view controller tab, and sometimes, willHideViewController is not called so you will not see the upper button. However if I rotate my iPad to landscape and after that to portrait, it's fixed.
I tried to force manually several rotations to work around this problem, but no luck.
I still have to try any split view controller clone class from github or similar.
Do you have idea what's going on or any work around?
Here I show you two examples working properly.
Thanks a lot for your help.
Where do you set the splitViewControllers delegate? Perhaps you can set the delegate when you load the tab. It sounds like you set it only when you have rotated once?
Otherwise, see this example
Here they have the TableViewController be the delegate of the splitviewcontroller. Perhaps you could do the same with the TabBarController?
I've concluded that this can't be done in any way that I consider 'sufficiently' legitimate. It's possible to get frustratingly close, but the issue of having the willShow..., willHide disseminated to the split view controllers under each tab remains.
The solution that seems most likely to work is,
https://github.com/grgcombs/IntelligentSplitViewController/blob/master/IntelligentSplitViewController.m
Though this code is undoubtedly clever, it's a bit too 'side door' for me. I suspect (but don't know) that just invoking the delegate methods is not sufficient. Surely the UISplitViewController itself needs to change it's internal state as well as calling the delegate methods? This method 'just' invokes the delegate methods when there's an orientation change.
So... I've decided on a more legitimate solution, which is to use the new method introduced in iOS 5.
- (BOOL) splitViewController:(UISplitViewController *)svc
shouldHideViewController:(UIViewController *)vc
inOrientation:(UIInterfaceOrientation)orientation
{
return NO;
}
So, the master menu is never hidden, and therefore the problem of managing the popover doesn't arise.
Of course, this is still not totally 'legit' as it still includes UISplitViewControllers that are not at the top level (the UITabViewController is at the top level, and the split views are on each tab)
Good luck with whichever solution you choose.
I'll update this reply when I've confirmed Apple will approve an app using this solution.

How to suppress Flash migration warnings (1090)

In Flash Professional CS4, I get "migration issue" warnings when I use mouse/keyboard input handler names such as onMouseDown, onKeyUp, etc., even though I have added event listeners for them. These names are perfectly legal for functions, but since these were automatically fired in ActionScript 2.0, we are now (albeit sensibly) warned that their use is no longer automatic in AS3.
I understand the purpose of the warnings, but they aren't useful for me. I want to suppress these warnings, but without suppressing any other warnings, which I generally do find useful.
E.g., when I use code like this:
/** #constructor */
public function MyClass() {
addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
}
protected function onMouseDown(e:MouseEvent):void {
I get an annoying warning like this:
Warning: 1090: Migration issue: The onMouseDown event handler is not triggered automatically by Flash Player at run time in ActionScript 3.0. You must first register this handler for the event using addEventListener ( 'mouseDown', callback_handler).
There are flex compiler (mxmlc) flags (and a Flash Pro setting) which can suppress actionscript warnings, or all warnings, but I don't want that. That's too general.
Ideally I could suppress a specific error/warning number (Warning #1090).
Edit: I've found more "advanced" compiler flags with mxmlc -help advanced, which look promising. Specifically, the following seem like likely candidates:
warn-deprecated-event-handler-error
warn-deprecated-function-error
warn-deprecated-property-error
How do I get Flash to use these?
Edit 2: I found a flex-info.xml style document in the Flash User Data dir.
[userdatafolder]/Adobe/Flash CS4/en/Configuration/ActionScript 3.0/FlexInfo.xml
However, this file contains a disappointing comment: <!-- Flash does not support most flex-config options. -->, and doesn't seem to respond to my directives even after restarting flash.
This is getting sad.
Edit 3: Found an issue "Erroneous, annoying "Migration issue" warnings" on Adobe bug tracker. A fix is confirmed for the Flex SDK, but no mention of Flash...
You can if you edit EnabledWarnings.xml in $Flash/$LOCALE/Configuration/Actionscript 3.0/EnabledWarnings.xml, where $Flash is the path to Flash inside your Applications/Program Files folder and $LOCALE is your language.
e.g.
/Applications/Adobe Flash CS4/en/Configuration/ActionScript 3.0/EnabledWarnings.xml
You will need to edit line 29, setting the enabled attribute to false for warning with id 1090:
<warning id="1090" enabled="false" label="kWarning_DepricatedEventHandlerError">EventHandler was not added as a listener.</warning>
Quick sidenote:
"Flash Builder (CS4)" is a confusing term. After Flex Builder 3, Flex Builder got renamed to Flash Builder, there is no Flash Builder CS4. The regular Flash IDE is known as Flash Professional/Flash Professional CS4, this was to avoid confusion between products with similar names: Flash Catalyst, Flash Builder(was Flex Builder), Flash Professional. Obviously it doesn't always work that great :)
What about changing the name of the function being called from onMouseDown to handlerOnMouseDown. Would it solve the issue?
Are you using Flex Builder?
If so, go to Project -> Properties -> Flex Compiler. There you can add arguments to the compiler.
Why are you overriding that? It never existed in the first place. The error message is actually telling you something useful. Don't suppress it.
If you want to create an event handler called onMouseDown, try something like
private function onMouseDown(e:MouseEvent) : void {
// statements
}
I agree with the previous post; the message is trying to tell you that you need to register that event handler. Just adding a method called onMouseDown() won't do it. What you need to do is to add something like
addEventListener(MouseEvent.MOUSE_DOWN, onMouseDown);
in either your constructor or maybe in the parent component.
You can filter out these warnings using Flash Builder's problems filtering capability:
open problems view
on the right click on the small triangle that opens a drop-down menu
select Configure Contents...
on the left side, create a new configuration, name it as you wish
on the right side adjust its settings:
Scope: On any element in the same project (or anything you want)
Description: choose doesn't contain and type in Migration issue (this will filter out warnings with migration issue in the description)
choose at least Flex problems
You can combine predefined and custom configurations by selecting more then one on the left side.

IOErrorEvent Eluding Capture

I'm working on a Flex application that processes and displays small amounts of HTML, sometimes including images. I'm getting the HTML out of third-party RSS feeds. Sometimes, I see this in a pop-up window:
Error #2044: Unhandled IOErrorEvent:. text=Error #2035: URL Not Found.
The RSS URL is just fine, but there's apparently something in the downloaded HTML that's causing a problem. Since the application is meant to run as part of a non-interactive digital sign, anything that requires a click to continue is completely unacceptable. I don't care how useless or malformed a URL is; the app needs to ignore the problem without pestering the user.
Unfortunately, I'm having no luck trapping this event. I'm sprinkling calls like this liberally through the code:
[object].addEventListener(IOErrorEvent.IO_ERROR, handleIOError);
... where [object] is everything from the mx:Text object rendering the HTML to its mx:Canvas parent to the mx:Application top-level app, and handleIOError is a simple function that looks like this:
private function handleIOError(event:IOErrorEvent):void {
trace ("IO error occurred: " + event);
}
But so far, nothing; that bloody error keeps popping up in the Flash player. Does anybody have any insight as to where I'm going wrong?
Make sure you are putting the event on the right object. I haven't done a whole lot of remote loading in Flex, but in Flash, a hilarious and annoying quirk is that when you use the Loader class to load images, the object you need to put event handlers on is NOT the Loader itself, but a property of the loader called contentLoaderInfo.
Read the docs carefully on the objects you are using, a similar pitfall might be at play.
IOErrorEvent is not bubbled so you cant catch or control it if someone else is implementing it.
Please find out which third party component you are using and try to get source if its open source or read some documentation or ask support guys on how to turn off this alert.
For example, if I made RSS component for flex and on error if I displayed the alert, if you use my component, whatever you can do you cant turn off my error alert unless i have provided you a boolean switch to turn it off. So this is really a problem with who has written the code for this alert box. Whatever you do you will not be able to turn this thing off. Except reverse engineer, change the code and recompile it, but it should be legal.

Resources