I am getting this error from SIMBL in the console:
05.09.11 17:00:09,165 SIMBL Agent: eventDidFail:'tvea' error:Error Domain=NSOSStatusErrorDomain Code=-1708 "The operation couldn’t be completed. (OSStatus error -1708.)" (the AppleEvent was not handled by any handler ) UserInfo=0x400e485c0 {ErrorNumber=-1708} userInfo:{
ErrorNumber = "-1708";
}
I am trying to debug this; but as I haven't really worked with AppleEvent that much yet, I'm not really sure how to interpret that.
I think the related code in the SIMBL Agent is this:
AEEventID eventID = 'load';
// Find the process to target
pid_t pid = [[appInfo objectForKey:#"NSApplicationProcessIdentifier"] intValue];
SBApplication* app = [SBApplication applicationWithProcessIdentifier:pid];
[app setDelegate:self];
if (!app) {
SIMBLLogNotice(#"Can't find app with pid %d", pid);
return;
}
// Force AppleScript to initialize in the app, by getting the dictionary
// When initializing, you need to wait for the event reply, otherwise the
// event might get dropped on the floor. This is only seems to happen in 10.5
// but it shouldn't harm anything.
[app setSendMode:kAEWaitReply | kAENeverInteract | kAEDontRecord];
id initReply = [app sendEvent:kASAppleScriptSuite id:kGetAEUT parameters:0];
// the reply here is of some unknown type - it is not an Objective-C object
// as near as I can tell because trying to print it using "%#" or getting its
// class both cause the application to segfault. The pointer value always seems
// to be 0x10000 which is a bit fishy. It does not seem to be an AEDesc struct
// either.
// since we are waiting for a reply, it seems like this object might need to
// be released - but i don't know what it is or how to release it.
// NSLog(#"initReply: %p '%64.64s'", initReply, (char*)initReply);
// Inject!
[app setSendMode:kAENoReply | kAENeverInteract | kAEDontRecord];
id injectReply = [app sendEvent:'SIMe' id:eventID parameters:0];
if (injectReply != nil) {
SIMBLLogNotice(#"unexpected injectReply: %#", injectReply);
}
The eventDidFail message also comes from the SIMBL Agent itself. It is this code:
- (void) eventDidFail:(const AppleEvent*)event withError:(NSError*)error
{
NSDictionary* userInfo = [error userInfo];
NSNumber* errorNumber = [userInfo objectForKey:#"ErrorNumber"];
// this error seems more common on Leopard
if (errorNumber && [errorNumber intValue] == errAEEventNotHandled) {
SIMBLLogDebug(#"eventDidFail:'%4.4s' error:%# userInfo:%#", (char*)&(event->descriptorType), error, [error userInfo]);
}
else {
SIMBLLogNotice(#"eventDidFail:'%4.4s' error:%# userInfo:%#", (char*)&(event->descriptorType), error, [error userInfo]);
}
}
And the error disappears if I comment out this code:
[app setSendMode:kAEWaitReply | kAENeverInteract | kAEDontRecord];
id initReply = [app sendEvent:kASAppleScriptSuite id:kGetAEUT parameters:0];
Related
I want to disable the journal mode in my core data app.
This is the code:
- (NSPersistentContainer *)persistentContainer {
// The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
#synchronized (self) {
if (_persistentContainer == nil) {
_persistentContainer = [[NSPersistentContainer alloc] initWithName:#"My_App"];
NSURL *url = [[self applicationFilesDirectory] URLByAppendingPathComponent:#"My_App.sqlite"];
NSPersistentStoreDescription *description=[[NSPersistentStoreDescription alloc]initWithURL:url];
NSMutableDictionary *pragmaOptions=[NSMutableDictionary dictionary];
[pragmaOptions setObject:#"DELETE" forKey:#"journal_mode"];
[description setOption:pragmaOptions forKey:#"NSQlitePragmaOptions"];
_persistentContainer.persistentStoreDescriptions=#[description];
[_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
if (error != nil) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
NSLog(#"Unresolved error %#, %#", error, error.userInfo);
abort();
}
}];
}
}
return _persistentContainer;}
I also verified with this:
NSArray *descriptionArray=[_persistentContainer persistentStoreDescriptions];
NSPersistentStoreDescription * description=[descriptionArray objectAtIndex:0];
NSLog(#"%#",description.options);
and the result of NSLog is:
{
NSInferMappingModelAutomaticallyOption = 1;
NSMigratePersistentStoresAutomaticallyOption = 1;
NSQlitePragmaOptions = {
"journal_mode" = DELETE;
};
but when I restart my app I always find in the application directory all the three file My_App.sqlite, My_App.sqlite-shm and My_App.sqlite-wal.
Why doesn't it work?
In my app delegate, I call
[Parse initializeWithConfiguration:[ParseClientConfiguration configurationWithBlock:^(id<ParseMutableClientConfiguration> configuration) {
configuration.applicationId = #"MYAPPKEY";
configuration.clientKey = #"";
configuration.server = #"DOMAIN/parse";
}]];
// test parse
PFObject *gameScore = [PFObject objectWithClassName:#"TestObject"];
gameScore[#"foo"] = #"bar";
[gameScore saveInBackgroundWithBlock:^(BOOL succeeded, NSError *error) {
if (succeeded) {
// The object has been saved.
NSLog(#"parse is working");
} else {
// There was a problem, check error.description
NSLog(#"parse is not working: %#",error);
}
}];
and I get the following error:
Error Domain=NSCocoaErrorDomain Code=3840 "JSON text did not start with array or object and option to allow fragments not set." UserInfo={NSDebugDescription=JSON text did not start with array or object and option to allow fragments not set.}
I get the error from any call to parse.
My server works well with the Android SDK and the JS SDK, but I keep getting this error on iOS. I've added my domain to the App Transport Security Settings.
You can not leave the clientKey empty. The parse server does not use clientKey any more but it still crashes when its null.
configuration.clientKey = #"47b6r78tb3ynf907ynoe";
You should try with adding a / after the
configuration.server = #"DOMAIN/parse";
so it looks like
configuration.server = #"DOMAIN/parse/";
The problem
I am using google-api-objectivec-client library to work with Google Drive API.
I am creating 10 folders inside appDataFolder (for example) without any delays and it is too fast and I am constantly getting errors for 9/10 of my requests:
Error Domain=com.google.GTLJSONRPCErrorDomain Code=500 "(Internal Error)" UserInfo={error=Internal Error, NSLocalizedFailureReason=(Internal Error)
some times these:
Error Domain=com.google.GTLJSONRPCErrorDomain Code=403 "(User Rate Limit Exceeded)" UserInfo={error=User Rate Limit Exceeded, NSLocalizedFailureReason=(User Rate Limit Exceeded),
Most likely, it is related to "spamming" or userRateLimit exceptions, because it easily can be fixed by "sleeps" (have reproduced this many times).
Suggested solution
Google suggest to retry request with such kind of errors, even it provides great API to do it automatically.
According to documentation:
GTL service classes and the GTMSessionFetcher class provide a mechanism for automatic retry of a few common network and server errors, with appropriate increasing delays between each attempt. You can turn on the automatic retry support for a GTL service by setting the retryEnabled property.
// Turn on automatic retry of some common error results
service.retryEnabled = YES;
The default errors retried are http status 408 (request timeout), 503 (service unavailable), and 504 (gateway timeout), NSURLErrorNetworkConnectionLost, and NSURLErrorTimedOut. You may specify a maximum retry interval other than the default of 1 minute, and can provide an optional retry selector to customize the criteria for each retry attempt.
But error with status 500 is not in default list. So, I tried to use this:
// Retry selector is optional for retries.
// If present, it should have the signature:
// -(BOOL)ticket:(GTLServiceTicket *)ticket willRetry:(BOOL)suggestedWillRetry forError:(NSError *)error
// and return YES to cause a retry. Note that unlike the fetcher retry
// selector, this selector's first argument is a ticket, not a fetcher.
GTLService.retrySelector
I have created a method which constantly returns YES, but it never get called and as a result request with errors are not retried.
Question
How to use automatic retry for google-api-objectivec-client?
Update. Code sample to reproduce the issue:
- (void) reproduceTheIssue: (GTMOAuth2Authentication *) authorizer {
GTLServiceDrive * driveService = [[GTLServiceDrive alloc] init];
driveService.retryEnabled = true;
driveService.authorizer = authorizer;
// driveService.fetcherService.retryEnabled = YES; //this also doesn't help
// driveService.retrySelector = #selector(ticket:willRetry:forError:);
const int DELAY = 0;
const int NUMBER_OF_FOLDERS = 50;
for (int i = 0; i < NUMBER_OF_FOLDERS; i++) {
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, DELAY * NSEC_PER_SEC), dispatch_get_main_queue(), ^{
GTLDriveFile * nestedFolder = [GTLDriveFile object];
NSString * folderName = [NSString stringWithFormat: #"folder-number-%i", i];
nestedFolder.name = folderName;
nestedFolder.mimeType = #"application/vnd.google-apps.folder";
nestedFolder.parents = #[#"appDataFolder"];
GTLQueryDrive * query = [GTLQueryDrive queryForFilesCreateWithObject: nestedFolder uploadParameters: nil];
[driveService executeQuery: query completionHandler: ^(GTLServiceTicket * ticket, GTLDriveFile * updatedFile, NSError * error) {
if (error == nil) {
NSLog(#"Successfully created a folder %#", updatedFile);
} else {
NSLog(#"Failed to a folder: %# error: %#", folderName, error);
}
}];
});
}
}
- (BOOL) ticket: (GTLServiceTicket *) ticket willRetry: (BOOL) suggestedWillRetry forError: (NSError *) error {
NSLog(#"I will never be called :( with this arguments ticket: %#, willRetry: %i, error :%#", ticket, suggestedWillRetry, error);
return YES;
}
Update Update The issue was discussed at library's GitHub. Short answer: it is not possible to retry these error automatically. It should be managed programmatically by user in handlers.
The retry logic is in the http fetcher class, so the retries only reflect errors that show up during network requests.
I'm using what seems to be a simple invocation of the NSFileVersion class method removeOtherVersionsOfItemAtURL: inside a coordinated writing block for some iCloud conflict resolution.
When my devices go into 'spaz mode', which is a technical term for repeatedly opening and closing the application on a few devices, an EXC_BAD_ACCESS exception is thrown internally. Code snippet:
- (void)compareVersionChanges:(NSFileVersion *)version {
if (![DataLoader iCloudPreferenceEnabled]) {
NSLog(#"Ignoring iCloud changes (version comparison) based on user preference");
return;
}
NSLog(#"compareVersionChanges");
dispatch_queue_t aQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(aQueue, ^(void) {
NSError *readError = nil;
NSFileCoordinator *coordinator = [[NSFileCoordinator alloc] initWithFilePresenter:(id)self];
[coordinator coordinateReadingItemAtURL:[version URL] options:0 error:&readError byAccessor:^(NSURL *newURL) {
DataContext *loadedContext = nil;
NSData *data = [NSData dataWithContentsOfURL:newURL];
NSError *e = nil;
loadedContext = [self convertXmlDataToContext:data error:&e];
if (e) {
NSLog(#"Done loading, error: %#", e);
[[DataLoader applicationDelegate] displayError:e];
loadedContext = nil;
}
if (!loadedContext) {
return;
}
id appDelegate = [DataLoader applicationDelegate];
DataContext *inMemoryContext = nil;
if (appDelegate != nil && [appDelegate respondsToSelector:#selector(context)]) {
inMemoryContext = [appDelegate performSelector:#selector(context)];
}
if (inMemoryContext) {
NSLog(#"Performing iCloud context synchronizating...");
DataContextSynchronizer *synchronizer = [[DataContextSynchronizer alloc] init];
ChangeSet *changes = [synchronizer compareLocalContext:inMemoryContext andRemoteContext:loadedContext];
if ([[changes changes] count] > 0) {
[SelectionManager disable];
#synchronized(appDelegate) {
NSLog(#"Applying synchronization changes...");
[synchronizer applyChangeSet:changes toDataContext:inMemoryContext];
NSLog(#"Synchronization changes applied");
}
[SelectionManager enable];
if ([appDelegate respondsToSelector:#selector(setSkipRefreshSave:)]) {
[appDelegate performSelector:#selector(setSkipRefreshSave:) withObject:[NSNumber numberWithBool:YES]];
}
dispatch_queue_t mainQueue = dispatch_get_main_queue();
dispatch_async(mainQueue, ^(void) {
[SelectionManager notifyListeners];
});
if ([appDelegate respondsToSelector:#selector(setSkipRefreshSave:)]) {
[appDelegate performSelector:#selector(setSkipRefreshSave:) withObject:[NSNumber numberWithBool:NO]];
}
[self save:[[DataLoader applicationDelegate] context]];
} else {
NSLog(#"No sync changes applicable.");
}
NSError *coordinateWriteRemoveError = nil;
[coordinator coordinateWritingItemAtURL:newURL options:NSFileCoordinatorWritingForDeleting error:&coordinateWriteRemoveError byAccessor:^(NSURL *theURL) {
theURL = [theURL copy];
NSError *removeOtherVersionsError = nil;
[NSFileVersion removeOtherVersionsOfItemAtURL:theURL error:&removeOtherVersionsError];
if (removeOtherVersionsError) {
NSLog(#"Error removing other versions: %#", removeOtherVersionsError);
}
}];
if (coordinateWriteRemoveError) {
NSLog(#"Error occurred coordinating write for deletion of other file versions: %#", coordinateWriteRemoveError);
}
}
}];
if (readError) {
NSLog(#"Done loading (outside block) error: %#", readError);
}
});
}
I thought a little syntax highlighting might make this easier to examine:
Link to image of code snippet and failure stack in Xcode
The error actually occurs on line 1404, and as you can see from the below screenshot, it's deep in Apple code territory.
Link to image of debugger
Before submitting a radar, I thought I'd check here to see if there's something I'm doing wrong? The extra [... copy] on line 1402 was just a quick check to make sure I'm not losing the reference to the block-provided argument, and will be removed.
Edit: An important note! I'm using ARC.
Edit 2: I've noticed that when calling:
[NSFileVersion otherVersionsOfItemAtURL:theURL]
The return value is nil, which indicates (via the documentation):
...or nil if there is no such file. The array does not contain the version object returned by the currentVersionOfItemAtURL: method.
So by checking the return value of this method before I make the call to removeOtherVersionsOfItemAtURL:, it has alleviated the issue. But I still find it strange that an EXC_BAD_ACCESS is thrown, rather than that method handling it properly.
I've noticed that when calling:
[NSFileVersion otherVersionsOfItemAtURL:theURL]
immediately prior to the call to removeOtherVersionsOfItemAtURL:, the return value is nil, which indicates (via the documentation):
Returns: An array of file version objects or nil if there is no such
file. The array does not contain the version object returned by the
currentVersionOfItemAtURL: method.
So by checking the return value of this method before I make the call to removeOtherVersionsOfItemAtURL:, it has alleviated the issue. But I still find it strange that an EXC_BAD_ACCESS is thrown by removeOtherVersionsOfItemAtURL:, rather than that method simply returning NO, or simply populating the provided NSError object.
I'll be filing a Radar and will update here when I hear back.
I'm writing an iOS App using an AudioQueue for recording. I create an input queue configured to get linear PCM, stated this queue and everything works as expected.
To manage interruptions, I implemented the delegate methods of AVAudioSession to catch the begin and the end of an interruption. The method endInterruption looks like the following:
- (void)endInterruptionWithFlags:(NSUInteger)flags;
{
if (flags == AVAudioSessionInterruptionFlags_ShouldResume && audioQueue != 0) {
NSLog(#"Current audio session - category: '%#' mode: '%#'",
[[AVAudioSession sharedInstance] category],
[[AVAudioSession sharedInstance] mode]);
NSError *error = nil;
OSStatus errorStatus;
if ((errorStatus = AudioSessionSetActive(true)) != noErr) {
error = [self errorForAudioSessionServiceWithOSStatus:errorStatus];
NSLog(#"Could not reactivate the audio session: %#",
[error localizedDescription]);
} else {
if ((errorStatus = AudioQueueStart(audioQueue, NULL)) != noErr) {
error = [self errorForAudioQueueServiceWithOSStatus:errorStatus];
NSLog(#"Could not restart the audio queue: %#",
[error localizedDescription]);
}
}
}
// ...
}
If the app gets interrupted while it is in foreground, everything works correct. The problem appears, if the interruption happens in the background. Activating the audio session result in the error !cat:
The specified audio session category cannot be used for the attempted audio operation. For example, you attempted to play or record audio with the audio session category set to kAudioSessionCategory_AudioProcessing.
Starting the queue without activating the session results in the error code: -12985
At that point the category is set to AVAudioSessionCategoryPlayAndRecord and the mode is AVAudioSessionModeDefault.
I couldn't find any documentation for this error message, nor if it is possible to restart an input audio queue in the background.
Yes it is possible, but to reactivate the session in the background, the audio session has to either set AudioSessionProperty kAudioSessionProperty_OverrideCategoryMixWithOthers
OSStatus propertySetError = 0;
UInt32 allowMixing = true;
propertySetError = AudioSessionSetProperty (
kAudioSessionProperty_OverrideCategoryMixWithOthers,
sizeof (allowMixing),
&allowMixing
);
or the app has to receive remote control command events:
[[UIApplication sharedApplication] beginReceivingRemoteControlEvents];
[self becomeFirstResponder];
At the present there is no way to reactivate if you are in the background.
Have you made your app support backgrounding in the info.plist? I'm not sure if recording is possible in the background, but you probably need to add "Required Background Modes" and then a value in that array of "App plays audio"
Update I just checked and recording in the background is possible.