How to crash a cordova ios app - ios

I am trying to write a small sample of cordova ios application. One of my requirements is to provide a button/link to allow user to crash the application.
I have tried to raise exception in CDVUIWebViewNavigationDelegate.m as follows,
- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:(UIWebViewNavigationType)navigationType
{
NSURL* url = [request URL];
if([url.path containsString:#"CRASH"])
{
NSLog(#"User crash bookmart with NSException");
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
NSDate *current = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle]; // Set date and time styles
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
NSString *currentTime = [dateFormatter stringFromDate:current];
[userInfo setObject:#"Crash Time" forKey:currentTime];
NSException *ex = [[NSException alloc] initWithName:#"BookmartCrashException" reason:#"User crashed bookmart!" userInfo:userInfo];
[ex raise];
}
...
}
But when I tried, I saw following log,
2017-09-04 17:09:57.148 HRent[96124:12077045] User crash bookmart with NSException
2017-09-04 17:09:57.149 HRent[96124:12077045] *** WebKit discarded an uncaught exception in the >webView:decidePolicyForNavigationAction:request:frame:decisionListener: delegate: User crashed bookmart!
The exception has been discarded and app hasn't crash : (
Is there any other way to crash the app for sure? Or with some configuration can I disable WebKit to discard such exception?
Much appreciate for your answers!
Regards
Rachel

Thanks Everyone.
I have tried with all the suggestion except for plugin suggested by Will.
Overall, there are 2 ways to crash the app.
As Michale suggested, use abort() to terminate the app.
Here is the piece of code I used,
- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:
(UIWebViewNavigationType)navigationType
{
NSURL* url = [request URL];
if([url.path containsString:#"CRASH"])
{
abort();
}
...
}
As shebuka's suggested, dispatch the exception on main thread. The trick here is that we can not use accessing nil array or dividing 0 to raise this exception but have to write I post in my question. Otherwise, the app won't crash and no log shown.
Here is the code piece I used,
- (BOOL)webView:(UIWebView*)theWebView shouldStartLoadWithRequest:(NSURLRequest*)request navigationType:
(UIWebViewNavigationType)navigationType
{
NSURL* url = [request URL];
if([url.path containsString:#"CRASH"])
{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"User crash bookmart with NSException");
NSMutableDictionary *userInfo = [NSMutableDictionary dictionary];
NSDate *current = [NSDate date];
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init];
[dateFormatter setTimeStyle:NSDateFormatterMediumStyle];
[dateFormatter setDateStyle:NSDateFormatterMediumStyle]; // Set date and time styles
[dateFormatter setTimeZone:[NSTimeZone localTimeZone]];
NSString *currentTime = [dateFormatter stringFromDate:current];
[userInfo setObject:#"Crash Time" forKey:currentTime];
NSException *ex = [[NSException alloc] initWithName:#"BookmartCrashException" reason:#"User crashed bookmart!" userInfo:userInfo];
[ex raise];
});
} ...}
I am going to choose solution 2 cause this crashes app with an exception which fits my requirement better.
Thanks everyone.

Try to launch your exception with dispatch on the main thread:
dispatch_async(dispatch_get_main_queue(), ^{
NSInteger asd = 5 / 0; // Simple division by 0
});
If it works then try NSException approach to have all that extra info.

Have you tried abort() as in the default core data implementation example? It causes the application to generate a crash log and terminate.

The hockeyapp plugin provides functionality that allows you to crash an app. You can use this as a temporary solution until you figure out the problem.
hockeyapp.forceCrash():void
Check out the repository https://github.com/Microsoft/cordova-plugin-hockeyapp

Related

Possible Object Deallocation Error, Background App Crash block_invoke_5

I am having an unexpected issue with a crash on my app which I am specifically struggling to debug because it occurs in background at a time determined by the iOS system. I have some capitalised comments to the code which show where the issue is being back traced to. I hope this is clear.
I believe it has to do with object deallocation.
I have tried using the __block before initialising the object but
this has not helped.
I have also tried dispatching the lines of code
in error to the main queue but that has not helped.
The actual crash is listed as AppName: __66-[BackgroundUpdateController initiateBackgroundHealthkitObservers]_block_invoke_5 + 160
I apologise if some of the code does not fit standard formatting and conventions. I am self taught from a variety of places and so do not have proper experience with code format.
Many Thanks
#import "BackgroundUpdateController.h"
NSUserDefaults *backgroundDefaults;
#implementation BackgroundUpdateController
-(id)init{
backgroundDefaults = [[NSUserDefaults alloc] initWithSuiteName:#"group.HeartAnalyzer"];
return [super init];
}
-(void)initiateBackgroundHealthkitObservers{
// Check we should be running here
if(([backgroundDefaults integerForKey:#"sleepAnalysisEnabled"] != 1) || (![backgroundDefaults boolForKey:#"AutomaticSleepAdd"])) return;
// Initiate some variables, Use __block to ensure the backgroundHealthStore object does not get deallocated
__block HKHealthStore *backgroundHealthStore = [[HKHealthStore alloc] init];
HKQuantityType *activeEnergy = [HKObjectType quantityTypeForIdentifier:HKQuantityTypeIdentifierActiveEnergyBurned];
// Enable background delivery of active energy data from HealthKit
[backgroundHealthStore enableBackgroundDeliveryForType:activeEnergy frequency:HKUpdateFrequencyHourly withCompletion:^(BOOL success, NSError *error) {
}];
// Now setup an HKOberverQuery which triggers hourly if there are new active energy data points in HealthKit
HKObserverQuery *query = [[HKObserverQuery alloc] initWithSampleType:activeEnergy predicate:nil updateHandler:^(HKObserverQuery *query, HKObserverQueryCompletionHandler completionHandler, NSError *error) {
UIApplicationState state = [[UIApplication sharedApplication] applicationState];
if (state == UIApplicationStateBackground || state == UIApplicationStateInactive){// Only run when app is not in foreground
// Load some more variables with checks to ensure they are valid objects
NSDate *previousSavedDate = [backgroundDefaults objectForKey:#"DateBackgroundSleepLastSaved"];
if(previousSavedDate == nil) previousSavedDate = [NSDate distantPast];
NSDate *lastSleepCheck = [backgroundDefaults objectForKey:#"LastSleepCheck"];
if(lastSleepCheck == nil) lastSleepCheck = [NSDate distantPast];
// If the last save date was long enough ago and the last sleep check was long enough ago, proceed
if(([previousSavedDate timeIntervalSinceNow] < -(3600*18)) && ([lastSleepCheck timeIntervalSinceNow] < -(3600*2))){
[backgroundDefaults setObject:[NSDate date] forKey:#"LastSleepCheck"];
[backgroundDefaults setBool:NO forKey:#"BackgroundSleepFound"];
SleepTimesCalculator *sleepClass = [[SleepTimesCalculator alloc] init];
[sleepClass calculateSleepTimes:^{
NSLog(#"Background sleep time calculations complete");
if([backgroundDefaults boolForKey:#"BackgroundSleepFound"]){// Only continue is a sleep time was found
__block NSMutableArray *savedSleepObjects = [backgroundDefaults valueForKey:#"SleepTimesDataBase"];
if(savedSleepObjects.count > 0){
__block NSMutableDictionary *sleepObject = [savedSleepObjects objectAtIndex:0]; // THE __BLOCK USED TO PREVENT THE OBJECT BEING DEALLOCATED, STILL SEEMS TO BE BASED ON THE CRASH
NSDate *sleepStart = [NSDate dateWithTimeIntervalSinceReferenceDate:[[sleepObject valueForKey:#"CalculatedSleepTime"]integerValue]];// Get the sleep time start date object
NSDate *sleepEnd = [NSDate dateWithTimeIntervalSinceReferenceDate:[[sleepObject valueForKey:#"CalculatedWakeTime"]integerValue]];
NSInteger sleepSavedToHealth = [[sleepObject valueForKey:#"SavedToHealth"] integerValue];// Check its not already been saved by some other element of the app
if(sleepSavedToHealth != 1){
HKCategorySample *sleepSample = [HKCategorySample categorySampleWithType:[HKCategoryType categoryTypeForIdentifier:HKCategoryTypeIdentifierSleepAnalysis] value:1 startDate:sleepStart endDate:sleepEnd];// Generate sleep object for HealthKit
[backgroundHealthStore saveObject:sleepSample withCompletion:^(BOOL success, NSError *error) {
if (!success) NSLog(#"Uncommon Error! saveObject:sleepSample");
else{
dispatch_async(dispatch_get_main_queue(), ^{// DISPATCH TO MAIN QUEUE AN ATTEMPTED FIX FOR CRASH
sleepObject = [savedSleepObjects objectAtIndex:0];// Choose the most recent sleep time to save
[sleepObject setValue:[NSNumber numberWithInteger:1] forKey:#"SavedToHealth"];// THIS IS WHERE THE 'Last Exception Backtrace (0)' ENDS UP
[savedSleepObjects replaceObjectAtIndex:0 withObject:sleepObject];// Replace the object which now has the 'Saved' tag
[backgroundDefaults setObject:[NSDate date] forKey:#"DateBackgroundSleepLastSaved"];// Save the data of the last time we reached this point
[backgroundDefaults setObject:savedSleepObjects forKey:#"SleepTimesDataBase"];// Save the sleep times back to the database
});
}
}];
}
completionHandler();// Call the completion handler as we've been throught the sleepObjects array
}
else completionHandler();// Call the completion handler anyway
}
else completionHandler();// Call the completion handler anyway
}];
}
else completionHandler();
}
}];
[backgroundHealthStore executeQuery:query];// Execute the HealthKit healthstore query
}
#end
Prefixing __block does not guarantees existence of an object for #"CalculatedSleepTime" key in sleepObject
I think you have misinterpreted how __block works. This will be a great guide.
On a quick overview of the code, it seems like [sleepObject valueForKey:#"CalculatedSleepTime"] is returning nil & without a nullability check you are trying to extract the integerValue
So, consider:
NSMutableDictionary *sleepObject = [savedSleepObjects objectAtIndex:0];
id calculatedSleepTime = [sleepObject valueForKey:#"CalculatedSleepTime"];
if(calculatedSleepTime){
NSDate *sleepStart = [NSDate dateWithTimeIntervalSinceReferenceDate:[calculatedSleepTime integerValue]];
}
And it looks like you also don't require the __block prefix in HKHealthStore *backgroundHealthStore = [[HKHealthStore alloc] init];

Crash [NSCalendar calendarWithIdentifier:] on ios 7

I've crashed app when my app run on iOS 7
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSCalendar calendarWithIdentifier:]: unrecognized selector sent to class 0x3b67718c'
I'm using the code on my project
- (instancetype)initWithLocale:(NSLocale *)locale andFirstWeekday:(NSUInteger)firstWeekday{
if (self = [super init]){
_calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
_calendar.timeZone = [NSTimeZone localTimeZone];
_calendar.locale = locale;
_calendar.firstWeekday = firstWeekday;
}
return self;
}
Someone guy please help me to solve that problem that help me save a ton of time in my life. Thanks.
[NSCalendar calendarWithIdentifier] is available for iOS 8+.
You can use initializer method instead, this works fine in all iOS:
_calendar = [[NSCalendar alloc] initWithCalendarIdentifier: NSGregorianCalendar];

Error Domain=EKCADErrorDomain Code=1013 "The operation couldn’t be completed. (EKCADErrorDomain error 1013.)" [duplicate]

This question already has answers here:
defaultCalendarForNewEvents failed
(8 answers)
Closed 7 years ago.
EKReminder *reminder = [EKReminder reminderWithEventStore:self.eventStore];
reminder.title = #"E-Cold 1mg";
reminder.calendar = [_eventStore defaultCalendarForNewReminders];
NSDate *date = [_myDatePicker date];
// get today date
NSDateFormatter *dateFormatter = [[NSDateFormatter alloc] init]; // here we create NSDateFormatter object for change the Format of date..
[dateFormatter setDateFormat:#"YYY-MM-dd"]; //Here we can set th
NSLog(#"%#",[dateFormatter stringFromDate:date]);
EKAlarm *alarm = [EKAlarm alarmWithAbsoluteDate:date];
[reminder addAlarm:alarm];
// EKRecurrenceFrequency frequency;
NSError *error = nil;
[_eventStore saveReminder:reminder commit:YES error:&error];
if (error)
{
NSLog(#"error = %#", error);
}`
above code is set to alarm is fine but When i reset the simulator call this method showing the this error Error getting default calendar for new reminders:
Error Domain=EKCADErrorDomain Code=1013 "The operation couldn’t be completed. (EKCADErrorDomain error 1013.)"
error = Error Domain=EKErrorDomain Code=1 "No calendar has been set." UserInfo=0x7f8fca4eac80 {NSLocalizedDescription=No calendar has been set.}
and the again stop and build the application working fine.Why this error coming first time launching
EKEventStore *eventStore = [[[EKEventStore alloc] init] autorelease];
if ([eventStore respondsToSelector:#selector(requestAccessToEntityType:completion:)]) {
// iOS 6 and later
[eventStore requestAccessToEntityType:EKEntityTypeEvent completion:^(BOOL granted, NSError *error) {
if (granted) {
// code here for when the user allows your app to access the calendar
[self performCalendarActivity:eventStore];
} else {
// code here for when the user does NOT allow your app to access the calendar
}
}];
} else {
// code here
[self performCalendarActivity:eventStore];
}
or may be have following problem
Quick Fix:
Goto Settings
Select Privacy
Select Reminders
Choose your application and allow access of "Reminders" to ON.

Local Notification Error iOS

when minimizing the application, all is well, but when I try to deploy the boom going on, this error
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[__NSArrayM insertObject:atIndex:]: object cannot be nil'
-(void) applicationDidEnterBackground:(UIApplication *)application
{
NSDate *alertTime = [[NSDate date] dateByAddingTimeInterval:5];
UIApplication* app = [[UIApplication sharedApplication] init];
UILocalNotification* notifyAlarm = [[UILocalNotification alloc] init];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:kAllNews]];
NSError *error = nil;
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error];
NSError *jsonParsingError = nil;
sortArray = [NSJSONSerialization JSONObjectWithData:response options:0 error:&jsonParsingError];
if (notifyAlarm)
{
if ([[NSUserDefaults standardUserDefaults] objectForKey:#"news"])
{
newsNew = [NSMutableArray arrayWithArray:[[NSUserDefaults standardUserDefaults] objectForKey:#"news"]];
}
if (newsNew.count > sortArray.count) {
notifyAlarm.fireDate = alertTime;
notifyAlarm.timeZone = [NSTimeZone defaultTimeZone];
notifyAlarm.repeatInterval = 0;
notifyAlarm.soundName = #"Glass.aiff";
notifyAlarm.alertAction = #"Gipoteza";
notifyAlarm.alertBody = #"Добавлена новая новость";
[app scheduleLocalNotification:notifyAlarm];
}
}
}
A couple of suggestions:
First; did you try putting your code in applicationWillResignActive instead?
Why are you getting a reference to UIApplication in your code? You already have that as a parameter to the method...
Try putting breakpoints in your code to see exactly where this error occurs. I would guess it happens on the last line: [app scheduleLocalNotification:notifyAlarm], and that it happens because your notifyAlarm object for some reason is nil. Use your debugger to step through the code to see if that object does indeed get set.
Also; be aware that your code has a maximum of 5 seconds from deactivation until it becomes suspended. When suspended; no code can run. If, for example, your NSURLConnection request for some reason takes long to respond, your app will be suspended before the code is finished.

Core Data: How to get a notification when document is saved?

I have noticed that when I call
[context save:nil];
the saving doesn't occur instantly. I tested that when I try to save and quit the app in one or two seconds. It only works if I keep the app open for 5+ seconds or so.
I have 2 questions:
How can I know when the save is complete? A simple NSLog() will be enough, just for testing purposes.
Can I force a save? Should I?
Testing if [context save] is synchronous
I have tested that many times and this is not the behavior that I'm getting. If I have this code:
[context save:nil]
NSLog(#"Saved");
I see the "Saved" log, quit the app, and when I launch it again and try to fetch the data - nothing there. This doesn't happen if I wait about 5-10 seconds after I see the "Saved" message.
Thoughts?
Some code
- (void)storeSales:(NSArray *)sales {
NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
[formatter setDateFormat:#"EE LLLL d HH:mm:ss Z YYYY"];
for (NSDictionary *saleDictionary in sales) {
Sale *sale = [NSEntityDescription insertNewObjectForEntityForName:#"Sale" inManagedObjectContext:self.context];
sale.productName = [saleDictionary objectForKey:#"description"];
sale.date = [formatter dateFromString:[saleDictionary objectForKey:#"occured_at"]];
NSLog(#"Stored new sale in database.");
}
[self.context save:nil];
}
How I setup the UIManagedDocument
#property (nonatomic, strong) UIManagedDocument *document;
#property (nonatomic, strong) NSManagedObjectContext *context;
...
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:#"SalesBot Database"];
self.document = [[UIManagedDocument alloc] initWithFileURL:url];
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.document.fileURL path]]) {
[self.document saveToURL:self.document.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {}];
} else if (self.document.documentState == UIDocumentStateClosed) {
[self.document openWithCompletionHandler:^(BOOL success) {}];
}
self.context = self.document.managedObjectContext;
UPDATE 1
I tried using NSNotificationCenter to receive NSManagedObjectContextDidSaveNotification - but - I'm receiving it twice! Once right after [context save:nil] and again 5-10 seconds later!
So it seems like you are using UIManagedDocument above Core Data. This explains some things.
At first, use -[UIDocument saveToURL:forSaveOperation:completionHandler:] to save your document. From docs:
You should typically use the standard UIDocument methods to save the document.
If you save the child context directly, you only commit changes to the parent context and not to the document store. If you save the parent context directly, you sidestep other important operations that the document performs.
UIManagedDocument works with two managed object contexts. One is working on main thread, the second is saving changes to file in background thread. This is why your changes were saved, but after reopening were lost. The second context did not finish save operation.
This explains also why your notification was triggered two times. One for each context.
The save method is not an asynchronous process. Anything that occurs after you call the save method will be executed after it has saved.
NSLog(#"About to force a save...");
[context save:nil];
NSLog(#"Now I know the save is complete!");
You can observe notification NSManagedObjectContextDidSaveNotification.

Resources