In my experience (which is pretty limited) an insta-crash could mean:
- The framework was not properly linked in when the ANE was created (ex. You're using a non-standard .framework and adt doesn't know where to find it.)
- The iOS Build Packaging preferences (for your AIR project) don't know where the Apple iOS SDK's base directory is. (This can be an easy one to forget.)
I assume you've already ruled both of those out but just in case I thought I'd mention them.
Thanks for the response. A few questions on your insights.. I don't use the command line adt tool to do anything besides package the ANE. Otherwise I'm not sure why my AIR project would need to know where the iOS SDK base directory is. The static library is already produced.
Here's the simple code I'm using (just the NSURL* related stuff):
I'm producing the Static Lib using XCode 4.3.x. I only need NSURL* functionality which is found in Foundation.h which is included and required for compile in build phases. If I comment out anything to do with NSURL* and simply return a string (FREObject of a const char*) I get that string back to flash and can print it to prove I have the context/initializer/finalizers set up and the function named properly. So the bridge between AIR and ANE work just fine. It's only when I use a NSURL* function that I crash.
Since my troubles I read this extensively long PDF on creating native extensions:
To be brief, it warned that a FREObject only exists until the return of the function you call. What I'm wondering is if it's even possible to use NSURL* functions because they require a delegate and will be running async. So even if I make a request and a connection using that request, after I return from the FRE function the connection is probably being cleaned up.
That aside, I did make the connection and request a synthesized global hoping to get around this. Also to be brief I found an excellent post about debugging an IPA using XCode. Otherwise you're pretty much in a black hole debugging. Here's the post:
The recipe works although it didn't right out of the box.
XCode is telling me it's a EXC_BAD_ACCESS which typically means the object does not exist that I'm doing something to. My call stack looks like this (loosely, and the name of my static lib is libWebUtil):
3 -[NSURL(NSURL) initWithString:relativeToURL:]
4 -[NSURL(NSURL) URLWithString:relativeToURL:]
5 -[WebUtil performRequest] // this is my method
From that stack I see it firing off the NSURLRequest and NSURL itself is first taking my string and testing it (CFStringIsLegalURLString) and then it runs CFStringGetLength. I assume it has completed verifying the string and goes to send a message (0 objc_msgSend) and I get a EXC_BAD_ACCESS on that.
I see 9 threads running. This happens on Thread 1 (com.apple.main-thread). The stack traces all look like ASM code to me. Not very useful but at least I can tell the official error.
Mind you that code linked above works perfectly if I make a new empty app, import it and run it. I print out the response data and it's fine.
Right around the incident on the stack there's a avmplus::EventDispatcherObject::NativeDispatchEvent(MMgc::GCAPI::GCRef<avmplus::EventObje ct>, avmplus::WeakRefList<SObject> const*) + 1076; .. if that helps at all. It's like the event it dispatches (perhaps from NSURL) to signal that the NSURL I'm making on the fly is correct but there's no object to receive it. That might happen if my method finishes and the object is destroyed before NSURL can even fire off the message.
So I'm very interested in learning about object lifecycle in an ANE.
Like you, I also only used ADT from the command line to package the ANE. For everything else I have been using Flash Builder. I don't know, off the top of my head, why Flash Builder requires the base-directory for your iOS SDK. I only know that my app instantly crashed until I realized I had forgotten to specify that base directory. (Your mileage may vary, though.)
I'm not an Objective-C wizzard by any means. I know enough to get by but it's not a strong point. Maybe others will see some chatter on this thread and chime in.
Thanks so much for the link to the Xcode debugging article. I believe that will help me greatly, going forward.
It took some rigging to get that link to work. I posted a comment at the bottom which might help clarify some things.
Just having either the GDB or LLDB debuggers let you know "what" caused the crash is very valuable. Unfortunately what I find myself doing in a dev-on-win, debug-on-mac situation is I have to export my static library, remake the ANE, copy it back over to my xcode dummy project and test it. What the article made it seem like I could do was just adjust and debug the static library without having to wrap it back in an ANE. That appears not to be true. So expect to mod your static lib, remake the ANE and then test.
He does give the full adt command line to package which would solve that issue. Since I work on another workstation unfortunately I can't do that. Nor do I have any Adobe apps at all installed on the Mac. I use it exclusively for XCode. So I'm confused when you say I should point Flash to my iOS SDK. I'm pretty sure the Windows version of Flash Builder/Pro comes with what it needs due to, well, not being a Mac.
Let me know if you have success with that debugging route. So far I can't even see NSLogs()s.. But I can get it to compile the project, run it on my device and show me debug errors when it fails.
Very interested in this topic and would love to know if you get an answer to your original question. Did you resolve this yet?
I've been using Adobe Native Extensions for Native Alerts and NetworkInfo. I'd like to find more information on why native iOS visual classes can't be used in an ANE. Do you know why specifically?
I've only seen it in videos and have read about it and from what I've seen and read is pretty sparse on the subject. Only a presumption but probably the complexity of what devices do to optimize their displays has a lot to do with it.
For instance I'm sure you've noticed on an iOS device when viewing a component (list view, web view, etc) that it appears pixelated for a split second and then renders crisp and clear. Zoom in a lot with pinch zoom (web view) and pixelation happens again and then a split second later it's crisp. The reason why is the device takes a "screenshot" of the webpage so when you scroll up and down, all it does is pan an image. That's why it's so smooth. That's also why it takes a second to register a touch on a hyperlink. It needs to see where you are in the image, calculate what's under it and then select it on the (non fake image) website.
Transferring over tech like that isn't very easy and is device specific. Also Flex comes with most of the normal components that devices have anyhow. The lowest level (GPU) is also now accessible with Stage3D. All in all, they're doing pretty well.
Mind you, for example, there's absolutely no reason you need to use Native Alert (visual). You can EASILY re-create your own, better, sexier dialog instead.
The real work here which is 'apparently' possible is getting at libs we can't recreate. Like the lower level access of NSURL*. There is nothing that can replicate it with AIR on Mobile, it simply lacks the functionality (so far). The classes are there (SecureSocket, Socket, etc) that can be pretty low level but we still have no access to them and no workarounds.
interesting. I'm using the native alert just fine...i've also implemented an alert in AS, and it feels like the native alert is faster.
I just found this StackOverflow article on displaying a display in an ANE:
How much faster is "faster" for a modal? In all honestly do you think your users will know/care/see that actual speed difference however tiny it is? One of my favorite things about Flash is I'm not stuck with the standard iOS looking controls. I'd rather theme it toward my product.
Interesting read on the ANE but is there some reason you'd want to go through all that hassle to display exactly what a StageWebView is? Or are you just pointing out that it's a visual control and the ANE spawned it? If so, so isn't the iOS Alert.
Visual has a particular meaning. UIKit is the topmost, simple to use framework. Below that is a slightly more robust but complex Core Animation. Etc, and all goes down to directly using the GPU. Each framework sits on top of each other both reducing complexity and reducing features. I'm pretty sure they mean that level is going to be difficult to tap into, which is probably Core Animation and below, not just UIKit.
our product is continually limited by Flash running on iOS. However, there's things we need in Flash (real-time streaming video) that we can't easily duplicate on native iOS code. However, for the rest of our app (social login, event browsing etc.), we don't need Flash, so we're considering writing our whole app in native iOS, packaging that into an ANE, and then have Adobe Air launch and immediately load the ANE.
native iOS code runs faster than the Flash equivalent on iOS for every instance I've tested. Pop-up alerts, lists, buttons, view transitions, etc. Everything runs faster natively. Sure, the difference is usually small, but by no means negligible. And yes, our users absolutely notice. Native iOS code is multi-threaded, while the Flash Air runtime is not, and this has a big effect on display rendering, at least in all our development and testing.
How have you handled the login mechanism? Did you get the NSURL* libraries to work for you? Are you using sockets or some other protocol? This is why I'm wondering how I'm getting an EXC_BAD_ACCESS even attempting to instantiate an NSURLRequest.
When the IPA is compiled, AIR is no longer AIR. So I'm wondering where you found this info that Adobe has made no use of threads? It's not like threads are new to, any language or computer/device over the last 15 years. I'd be interested in knowing how you know that.
And yes, things like spark lists versus a native list makes complete sense that they'd be different given the order of magnitude of difference between how they're implemented, especially with cell dequeueing on native. That isn't to say I couldn't create a list that utilizes Stage3D that beats the native implementation either. Nor would I want to take the time to do that either but you get my point. We're in the middle right now with no known roadmap on optimization, except that it's certainly getting better
Now that dual tegra 3s, dual a5x (quad soon?), quad core tegras etc are all coming to devices I think, gladly, this conversation will be pointless in less than 12 months.
I haven't specifically implemented NSURLRequest in an ANE. However, the EXC_BAD_ACCESS error is happening because you're referencing a deallocated instance, so I'm not sure that error is related to not being able to access the underlying class framework. If it were, it would have thrown up sooner. Your call stack seems to execute fine until you try to reference the length of your string. That's when it throws EXC_BAD_ACCESS. Have you tried forming a string object explicitly instead like this?:
Not sure that would help but that's what I would try. actually from this article seems it shouldn't make a difference: http://stackoverflow.com/questions/3681133/objective-c-string-differences
I'm not sure what you mean by "Air is no longer AIR" when the IPA is compiled. From my understanding, the FlashBuilder IDE compiles both the application code and the Adobe AIR runtime down into the IPA. At that point, it's bytecode running on the device, but it's still "AIR", just compiled down to run on the device. However, since Flash/AIR is designed as a single-threaded runtime environment (this is well documented across the web), then the device doesn't make use of multi-threading when running the app, since there is no instruction within the bytecode on how to achieve this.
When NSURLRequest sends the NSString containing the URL to its own internal validator, somehow the string is lost. This ANE can be stripped down to just that one NSURLRequest line and it will fail. That makes no sense unless the creation of the NSURLRequest was async, but it certainly shouldn't be.
AIR is no longer AIR. You're right, it's compiled down into ARM. Where did you read that during the process of compiling Adobe never figured out how to integrate threads? This is a complete transcode. They have every opportunity to make use of threads any way they like during it.
Yes, everyone knows flash player runs on a single thread. It's always been a *****. Especially when designing kiosks that run in HD which I do more than less of. The vendor asks for specs and I always tell them 3GHz+ dual core or better and they end up lowballing me with a quad 2ghz saying "wwwhhaaattt?? that's 4x2GHz! 8GHz!".... Ugh
But just because Flash Player (for whatever reason) isn't multithreaded definitely doesn't mean when they compile down they made no use of threads.
In fact, that's how the ANE dispatches events. It's clearly documented that the ONLY thing that is cross-thread in an ANE is the event dispatcher.
Not beating a dead horse but you know there's a huge difference between code threading and CPU threading right? You know that flash only runs on a single thread but have you ever noticed a single CPU pegged out during that? No. That's not how a CPU works.
This just FYI land.
There's 3 tiers. Topmost is code.
Threads in code are designed for asynchronous operations so multiple things can concurrently happen which at most tells the OS you desire not to halt a particular thread for a response.
At that point the OS can intercept if it chooses. It can be responsible for delegating the workload directly to the CPU or to interfere and perform some sophisticated workload sharing. It can identify an overworked resource and reallocate.
At the CPU level this is an entirely different type of what you could consider threading. The CPUs job is to take the work (from all threads) and make realtime decisions on how to fill its pipelines (cores) with the load. Regardless if you use a single thread or 500 threads, it's the CPUs job at the opcode level to decide how to introduce the least amount of pipeline bubbles (wasted cycles). The CPU can only do "so much work" so it will intelligently spread the workload amongst its known resources and reassemble the work after computation.
There's no point in time on any multi-core or hyperthreaded system that you will only ever utilize one core. The CPU decides. Thus your AIR iOS apps are using all available CPU.
Take this with a grain of salt but as of the time of this discussion, visual classes were absolutely not supported. Only any obj-c/cocoa libs that were non-visual (logic, network, etc) were able to be wrapped in an ANE. Displaying the visual like cocos2d, etc were not supported at all.
To be honest, Flash is a far easier to develop graphics in so I can understand that limitation. I'm not saying 1 whole major version later since this post that this is still the case but it would make sense if it is. Stage3D is very similar to the lower level openGL ES programming in obj-c. With the frameworks you almost, or do, have a similar cocos2d workflow that directly uses the GPU for acceeleration.