iOS UIWebView - trap exceptions loading invalid file format - objective-c

I have a UIViewController containing a UIWebView which I am using to view various documents. Occasionally a document may attempt to be loaded which is not supported by the UIWebView (e.g. old Excel 2.0 sheet). Currently this causes output in the debug window as follows :
exception: CPMessageException: The file format is invalid.
EXCEPTION CPMessageException: (null)
The webViewDidStartLoad method fires, but neither webViewDidFinishLoad or didFailLoadWithError fires.
The error doesn't crash the app, but I would like to trap this exception to provide my own message for the user. Can anybody suggest how to trap and handle this?
Many thanks,
Jonathan

Unfortunately CPMessageException is part of the private frameworks of Apple, in case of office files, OfficeImport.framework. This is thrown when the framework receives an unusable file.
The reason your application is not crashing is because it is probably being handled in the import code itself. Even setting NSSetUncaughtExceptionHandler will not work (as I have tried in the past).
The best way to go around this would be to use the shouldStartLoadWithRequest delegate method of UIWebView:
- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
Here you could preemptively stop the file from being loaded into the web view and avoid a clueless blank screen.
(Am not sure if there is a way to read NSLog output on the fly so you could monitor it. But that is probably not a right way to do it!)
Update: Just filed a bug regarding this. Let us see what the Apple Developers have to say on this.

Related

iOS9 storyboard what is unhandled action (handleNonLaunchSpecificActions)?

I've noticed the following error popping up in the console when running my app on iOS 9 when using a storyboard. I'm using xCode7. Is this something I need to be concerned about?
-[UIApplication _handleNonLaunchSpecificActions:forScene:withTransitionContext:completion:] ** unhandled action -> <FBSSceneSnapshotAction: 0x176bfb20> {
handler = remote;
info = <BSSettings: 0x176a5d90> {
(1) = 5;
};
}
There is nothing wrong with your code. This is a logging message internal to Apple, and you should file a radar about it.
There are two hints that show that this is probably Apple's code:
The underscore leading the method name _handleNonLaunchSpecificActions:forScene:withTransitionContext:completion is a convention indicating that the method is private/internal to the class that it's declared in. (See this comment.)
It's reasonable to guess that the two letter prefix in FBSSceneSnapshotAction is shorthand for FrontBoard, which according to Rene Ritchie in "iOS 9 wish-list: Guest Mode" is part of the whole family of software related to launching apps:
With iOS 8, Apple refactored its system manager, SpringBoard, into several smaller, more focused components. In addition to BackBoard, which was already spun off to handle background tasks, they added Frontboard for foreground tasks. They also added PreBoard to handle the Lock screen under secure, encrypted conditions. [...]
I have no idea what the BS prefix in BSSettings is for, but
BS is shorthand for BackBoard Settings, and an analysis of this log message would indicate that it's not anything you did, and you should file a radar with steps to reproduce the logging message.
If you want to try and grab a stack trace, you can implement the category linked to here. Some would argue that overriding private API is a bad idea, but in this case a temporary injection to grab a stack trace can't be too harmful.
EDIT:
But, we still want to know what this action is. So I put a breakpoint on -[UIApplication _handleNonLaunchSpecificActions:forScene:withTransitionContext:completion] and started printing out register values and found a class called FBSceneImpl which had a whole bunch of information about my application:
We are able to find out which private method is called next (stored in the program counter, instruction pointer, register 15.)
I tried finding the un-handled FBSceneSnapshotAction referenced in the log, but no dice. Then, I subclassed UIApplication, and overrode _handleNonLaunchSpecificActions:forScene:withTransitionContext:completion. Now I was able to get at the action directly, but still, we don't know what it is.
Then, I looked at the FBSceneSnapshotAction again. Turns out it has a superclass called BSAction.
Then I wrote a tool similar to RuntimeBrowser and looked up all of the subclasses of BSAction. It turns out that there's quite a list of them:
The two method names we have (one from the log and one from the program counter on the devices) indicate that these actions are used under the hood for passing actions around the system.
Some actions are probably sent up to the app delegate's callbacks, while others are handled internally.
What's happening here is that there is an action that wasn't handled correctly and the system is noting it. We weren't supposed to see it, apparently.
AFAIK, the info above is related to iOS during snapshot the screen (i suppose for double click home multitask related behaviour).I deeply investigated my application and seems that it does not get any side behaviours. You can safely ignore it, for now.
You can use the following gist simple category to test yourself against the calls to the above function:
I have figured it out, it will happen when you have IBAction method declared in .h or .m file but you have not bind it to any control.
.m example:
- (IBAction)click:(id)sender{
}
but not assigned this method to any control in storyboard.
haven't find out why it happens in my app, but at least you can catch the exception, if you want to keep this from popping up in your log pane. It's not a solution, but it might give you more insight why it is happing by inspecting any of the arguments that are passed in the catch.
swift 2 version:
import UIKit
extension UIApplication {
func _handleNonLaunchSpecificActions(arg1: AnyObject, forScene arg2: AnyObject, withTransitionContext arg3: AnyObject, completion completionHandler: () -> Void) {
//whatever you want to do in this catch
print("handleNonLaunchSpecificActions catched")
}
}

Xcode: "Spurious Update" console warning?

I'm writing a pretty straightforward ObjC app. (The only minor complexity is that it uses an external library called Chilkat for some basic networking, but I don't think that that's relevant.)
Occasionally, my project spontaneously pops up this warning message:
May 14 01:24:01 Neovenator-2.local Project[22645] : void
CGSUpdateManager::log() const: conn 0x4b29b: spurious update.
And I have no idea how to handle or even interpret it. There's nothing in my project called CGSUpdateManager, and my project doesn't call a log() function anywhere. I can't even reliably reproduce it, but it's popped up often enough to raise my interest level.
Searches at both Google and here for the term "spurious update" reveals a lightly scattered set of conversation, but nothing relevant to my project. Meanwhile, a Google search for "CGSUpdateManager" reveals it's something to do with Swift, which I'm not using at all.
Can anyone help me understand what this means? Or should I just disregard it?
Make sure to call super in viewDidLoad, viewWillAppear and viewWillDisappear.
Sorry, my code with correct Highlight/indentation:
- (void)setNeedsDisplay
{
//#if 1 //TEST (suppose we are only called by us)
if(wvImageRep_DoRebuild)
//#endif
[super setNeedsDisplay]; // "spurious update" ?
}
It's an example (#see my full response), it helped me

App crash - "DiskImageCache: Could not resolve the absolute path of the old directory."

I am working on an app, where I display the data entered by user in a PDF file. PDF File is also created dynamically.
All this is fine.
I have implemented QuickLook framework to display the pdf file. When I call the QL framework, PDF file id displayed quite fine but when come back to the calling screen, my app crashes without any crash log or memory warnings.
I am calling QL with below code:
[[self navigationController] presentModalViewController:qlPreviewer animated:YES];
logs created are
DiskImageCache: Could not resolve the absolute path of the old directory.
[Switching to process 3070 thread 0x17603]
[Switching to process 3070 thread 0x15503]
This is quite interesting.....
When I run the same program in Instruments to check for leaks and Memory Management, i can only find leaks when PDF document is scrolled and all the pages are viewed.
However, interestingly there is no app crash that I can see.
Also, I did try with ZombieEnabled = YES and without it but no app crash with Instruments.
I am quite clueless on how to interpret this and have been trying different things to solve this. Also, I have tried UIWebView but the result is the same.
I was again trying something to check out the issue and found something interesting.
When i execute the code directly from X-Code - i get the crash in as explained above.
In other instance, if I execute the app by clicking on the app in the sim... no crash
I am yet to check this on device. Can someone confirm the crash on the device?
Also, Google does not have answer to this question.
Thanks in advance for your answers.
Can anyone shed some light on this?
I'm having the exact same issue.
As a workaround, you can disable or remove your 'All Exceptions' breakpoint. This might make debugging a little more difficult, but it's not as bad as having to relaunch the application all the time.
This is the breakpoint causing the issue. I had set it so long ago that I'd forgotten it was there
Deleting application from device helped me to solve this problem.
Maybe also at first you should try "Product > Clean" to ensure that all resources will be copied to your device.
I was able to fix mine with this code:
FirstViewController.h
NSURLRequest* reqObj;
#property(nonatomic, retain) NSURLRequest* reqObj;
FirstViewController.m
reqObj = [NSURLRequest requestWithUrl:url cachePolicy:NSURLRequestReloadIgnoringCacheData timeoutInterval:60.0];
NSURLConnection* conn = [[NSURLConnection alloc] initWithRequest:reqObj delegate:self];
then instead of loading it on my view after this line i waited for the connectionDidFinishLoading then load it to my view
Interesting: This has just started with my app too. No errors when checking for leaks but running the app in the sim actually is causing a Breakpoint, not a crash. I can hit the continue and the app keeps running, no problem.
My issue also is relating to a PDF, but I'm just using a web view to display a PDF from the app bundle. I've checked everything in the dealloc, it's all good, this may be a iOS 5.1 bug. I will update as I learn more.
#JimP, It isn't an iOS 5.1 bug. It has just started happening to my app as well, on iOS5.0. It seems to only affect pdfs of more than one page length, and seems to trigger most commonly on scrolling past the end of the document (although sometimes earlier also). It also seems to happen more often on a second load.
This could happen when you delete the object reference in code but having its reference in xib. Delete the outlet that you no longer need.
Just ran into this problem of loading a pdf file in an App I am converting to iOS 8. This App has been running fine since the first iPhone. I just removed the All Exceptions breakpoint to work around it.
I don't know if it's the same problem but I had an issue where switching from a PDF view to another more than three times via the tab bar controller caused a crash.
Turned out that embedding the views I was switching to within Navigation controllers put a stop to the crashing.

Unrecognized selector sent to an instance after refactoring - Xcode4

I'm trying to clean up some old code that I wrote to comply with Apple's guidelines on method naming etc. and encountered this. Basically, I have a button in Interface builder and a tapDown action connected to an event handler in my implementation file. I've changed the name of this event handler via the refactor tool built into Xcode. The name of the method is updated in the .h / .m files and in the IB GUI. I've also looked at the raw xml .xib file and there's no trace of my old method name.
When I click on the button however, I get an error saying unrecognized selector oldMethodName:.
The error shows that something is still trying to call my older method, but I'm not sure what it is. What else can it be?
Thanks,
Teja.
Damn, figured it out a second after posting this question. The app on the simulator wasn't getting updated for some reason. Did a 'Reset content and settings' on the simulator and it works now.

Core data/NSPersistentDocument marking file "clean" every time any field finishes editing

I'm working with a document-based core-data OS X application. The problem I'm having is that whenever I edit any field on the document, after I press tab or click to something else (i.e. I finish editing/change focus), the document is marked as clean and undo is reset. When I try to save the file, however, the resulting document opens without the data I entered. What might be the problem, or, any pointers on where to look to fix this? Here's some stuff I know and things I've already tried:
I know it's not somehow saving because it never stops at the breakpoint in my overridden writeSafelyToURL:(NSURL *)inAbsoluteURL ofType:(NSString *)inTypeName forSaveOperation:(NSSaveOperationType)inSaveOperation error:(NSError **)outError and it also never sends an NSManagedObjectContextDidSaveNotification.
The documents are packaged in an NSFileWrapper directory with the core data store inside (and also some other files). I access the entities through an NSObjectController and a couple NSArrayControllers. It happens with both core data properties and manually registered changes in the rest of the file wrapper.
Update: At the suggestion of Martin, I tried NSUndoManager's notifications, and all I can seem to glean from it is that more than one undo manager is in play. If I add an observer for NSUndoManager, it won't post if I specify an object, and then if I don't, the notification object is not equal to [self undoManager]. I added updateChangeCount to my category on NSPersistentDocument, and it never gets called. setDocumentEdited basically confirmed that something about losing first responder is passing NO into that method. What could be causing this, and how can I fix it?
You could break on the method setDocumentEdited: of NSWindow to see which operation updates the change status.
In addition updateChangeCount: of NSDocument might be a place to take a look at.
NSUndoManager also posts several Notifications which can give additional hints what to look at.
The answer is actually pretty silly considering how long this stumped me. I was working on some objects on load, and I accidentally set [[self undoManager] disableUndoRegistration] at both the points where I should disable and enable. It was a little more than that, though. A related element in Interface Builder needed to be checked Prepares Content. When I had done both those things, the problem vanished.