Network connection is losing when the app goes to the background - iphone

I am using CMIS(Content management interoperability services) to download data from the alfresco server. I am using the following code and it works fine to some extent but when the application goes to background, the network connection is lost and when the app comes to foreground, it tries to retry the download and fails saying connection error. As I am a newbie any help will be much appreciated.
- (void)testFileDownload
{
[self runTest:^
{
[self.session retrieveObjectByPath:#"/ios-test" completionBlock:^(CMISObject *object, NSError *error) {
CMISFolder *testFolder = (CMISFolder *)object;
STAssertNil(error, #"Error while retrieving folder: %#", [error description]);
STAssertNotNil(testFolder, #"folder object should not be nil");
CMISOperationContext *operationContext = [CMISOperationContext defaultOperationContext];
operationContext.maxItemsPerPage = 100;
[testFolder retrieveChildrenWithOperationContext:operationContext completionBlock:^(CMISPagedResult *childrenResult, NSError *error) {
STAssertNil(error, #"Got error while retrieving children: %#", [error description]);
STAssertNotNil(childrenResult, #"childrenCollection should not be nil");
NSArray *children = childrenResult.resultArray;
STAssertNotNil(children, #"children should not be nil");
STAssertTrue([children count] >= 3, #"There should be at least 3 children");
CMISDocument *randomDoc = nil;
for (CMISObject *object in children)
{
if ([object class] == [CMISDocument class])
{
randomDoc = (CMISDocument *)object;
}
}
STAssertNotNil(randomDoc, #"Can only continue test if test folder contains at least one document");
NSLog(#"Fetching content stream for document %#", randomDoc.name);
// Writing content of CMIS document to local file
NSString *filePath = [NSString stringWithFormat:#"%#/testfile", NSTemporaryDirectory()];
// NSString *filePath = #"testfile";
[randomDoc downloadContentToFile:filePath
completionBlock:^(NSError *error) {
if (error == nil) {
// Assert File exists and check file length
STAssertTrue([[NSFileManager defaultManager] fileExistsAtPath:filePath], #"File does not exist");
NSError *fileError = nil;
NSDictionary *fileAttributes = [[NSFileManager defaultManager] attributesOfItemAtPath:filePath error:&fileError];
STAssertNil(fileError, #"Could not verify attributes of file %#: %#", filePath, [fileError description]);
STAssertTrue([fileAttributes fileSize] > 10, #"Expected a file of at least 10 bytes, but found one of %d bytes", [fileAttributes fileSize]);
// Nice boys clean up after themselves
[[NSFileManager defaultManager] removeItemAtPath:filePath error:&fileError];
STAssertNil(fileError, #"Could not remove file %#: %#", filePath, [fileError description]);
} else {
STAssertNil(error, #"Error while writing content: %#", [error description]);
}
self.testCompleted = YES;
} progressBlock:nil];
}];
}];
}];
}
The connection fail doesn't occurs when the user presses the home key. It fails only when the magnetic cover lid is closed or when there is a timeout.

When an app is moved to background, the OS gives the app 5s to finish what it is doing before it is suspended (keeps RAM, but stops the app receiving any messages or doing anything). If you have a task that needs to run to completion when the user presses the home button, you can use a background task. From apple's documentation:
Your app delegate’s applicationDidEnterBackground: method has
approximately 5 seconds to finish any tasks and return. In practice,
this method should return as quickly as possible. If the method does
not return before time runs out, your app is killed and purged from
memory. If you still need more time to perform tasks, call the
beginBackgroundTaskWithExpirationHandler: method to request background
execution time and then start any long-running tasks in a secondary
thread. Regardless of whether you start any background tasks, the
applicationDidEnterBackground: method must still exit within 5
seconds.
Note: The UIApplicationDidEnterBackgroundNotification notification is
also sent to let interested parts of your app know that it is entering
the background. Objects in your app can use the default notification
center to register for this notification.
From http://developer.apple.com/library/ios/#documentation/iphone/conceptual/iphoneosprogrammingguide/ManagingYourApplicationsFlow/ManagingYourApplicationsFlow.html

USE Reachability code Try this code to save data once downloaded:
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
//try to access that local file for writing to it...
NSFileHandle *hFile = [NSFileHandle fileHandleForWritingAtPath:self.localPath];
//did we succeed in opening the existing file?
if (!hFile)
{ //nope->create that file!
[[NSFileManager defaultManager] createFileAtPath:self.localPath contents:nil attributes:nil];
//try to open it again...
hFile = [NSFileHandle fileHandleForWritingAtPath:self.localPath];
}
//did we finally get an accessable file?
if (!hFile)
{ //nope->bomb out!
NSLog("could not write to file %#", self.localPath);
return;
}
//we never know - hence we better catch possible exceptions!
#try
{
//seek to the end of the file
[hFile seekToEndOfFile];
//finally write our data to it
[hFile writeData:data];
}
#catch (NSException * e)
{
NSLog("exception when writing to file %#", self.localPath);
result = NO;
}
[hFile closeFile];
}

Related

context not calling performblock

http://www.fileconvoy.com/dfl.php?id=g021ae486d8d8acb3999343609097fcba7f7befa53
this is the link to an assignment app which i got for my homework it most of its concepts taken from the stanford cs193p course as iam studing that too, this app has 3 modules
1 camera
2 map
3 contacts
the camera and map modules are working fine not as hoped but fine cut in the contacts module I
am using core data model to store contacts from contacts directory which you'll see when you run the app.
Now the problem is that my view adds the contacts to the core data but they are not showing in the table so when i tried to debug the application i saw that the method
[self.managedObjectContext performBlockAndWait:^{}];
is not calling the block of code inside it thats why the data is not even getting saved in the data model let alone show in table.
very very thanks in advance...
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:#"Demo Document"];
UIManagedDocument *document = [[UIManagedDocument alloc] initWithFileURL:url];
if (![[NSFileManager defaultManager] fileExistsAtPath:[url path]]) {
[document saveToURL:url
forSaveOperation:UIDocumentSaveForCreating
completionHandler:^(BOOL success) {
if (success) {
self.managedObjectContext = document.managedObjectContext;
}
}];
} else if (document.documentState == UIDocumentStateClosed) {
[document openWithCompletionHandler:^(BOOL success) {
if (success) {
self.managedObjectContext = document.managedObjectContext;
}
}];
} else {
self.managedObjectContext = document.managedObjectContext;
}
if(self.managedObjectContext==nil)
NSLog(#"nil object");

how to create folder on Google Drive using Google Drive SDK for iPhone?

I am using Google Drive SDK for iPhone and trying to upload Audio file in "TestAudio" folder.If "TestAudio" folder is not created at google drive then first create that folder and after that my audio should store to that folder only. Every thing is working gr8 except folder creation. can any buddy please help?
I am using below code for upload audio file.
GTLUploadParameters *uploadParameters = nil;
NSString *soundFilePath = [[NSBundle mainBundle]
pathForResource:#"honey_bunny_new"
ofType:#"mp3"];
if (soundFilePath) {
NSData *fileContent = [[NSData alloc] initWithContentsOfFile:soundFilePath];
uploadParameters = [GTLUploadParameters uploadParametersWithData:fileContent MIMEType:#"audio/mpeg"];
}
self.driveFile.title = self.updatedTitle;
GTLQueryDrive *query = nil;
if (self.driveFile.identifier == nil || self.driveFile.identifier.length == 0) {
// This is a new file, instantiate an insert query.
query = [GTLQueryDrive queryForFilesInsertWithObject:self.driveFile
uploadParameters:uploadParameters];
} else {
// This file already exists, instantiate an update query.
query = [GTLQueryDrive queryForFilesUpdateWithObject:self.driveFile
fileId:self.driveFile.identifier
uploadParameters:uploadParameters];
}
UIAlertView *alert = [DrEditUtilities showLoadingMessageWithTitle:#"Saving file"
delegate:self];
[self.driveService executeQuery:query completionHandler:^(GTLServiceTicket *ticket,
GTLDriveFile *updatedFile,
NSError *error) {
[alert dismissWithClickedButtonIndex:0 animated:YES];
if (error == nil) {
self.driveFile = updatedFile;
self.originalContent = [self.textView.text copy];
self.updatedTitle = [updatedFile.title copy];
[self toggleSaveButton];
[self.delegate didUpdateFileWithIndex:self.fileIndex
driveFile:self.driveFile];
[self doneEditing:nil];
} else {
NSLog(#"An error occurred: %#", error);
[DrEditUtilities showErrorMessageWithTitle:#"Unable to save file"
message:error.description
delegate:self];
}
}];
I don't see your code to create a folder, but I was having the same problem with folder creation myself. As you know, the mimeType must be "application/vnd.google-apps.folder". I ran into assert failures if the NSData parameter to uploadParametersWithData was nil. So I tried a zero length NSData object and that failed. Using a 1 byte NSData object also failed. The trick is to call queryForFilesUpdateWithObject with uploadParameters:nil. Then the folder creation works fine. I also discovered that the Objective-C code shown at the end of:
https://developers.google.com/drive/v2/reference/files/insert
is incorrect. The file.parents should be as follows:
GTLDriveParentReference *parentRef = [GTLDriveParentReference object];
parentRef.identifier = parentID;
if (parentID.length>0) file.parents = [NSArray arrayWithObjects:parentRef,nil];

Core Data - UIManagedDocument won't open

I am using Core Data to store a few simple strings related to each user. When the app first starts, everything seems to be fine. The database opens, and I am successfully able to save and retrieve data.
However, after some usage, sometimes the UIManagedDocument I use will just not open when the app starts. Here is the method I use for that (done in the app delegate):
-(void)initManagedDocument{
#try {
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:#"DataBase"];
self.managedDocument = [[UIManagedDocument alloc] initWithFileURL:url];
if ([[NSFileManager defaultManager] fileExistsAtPath:[url path]]){
[self.managedDocument openWithCompletionHandler:^(BOOL success){
if (success) {
[self documentIsReady];
}else{
NSLog(#"Could not open document");
}
}];
}else{
[self.managedDocument saveToURL:url forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success){
if (success) {
[self documentIsReady];
}else{
NSLog(#"Could not create document");
}
}];
}
}
#catch (NSException *e) {
}
}
This code gets called from my app's didFinishLaunchingWithOptions. The saveToURL half of the if-statement gets called initially, and returns a success. Then in the following few calls the openWithCompletionHandler: gets called, and returns successfully.
However, at some point after using the app for awhile, the openWithCompletionHandler: returns success = FALSE. I am not sure why, or how the UIManagedDocument gets messed up. The URL still seems to be the same, and the fileExistsAtPath is still returning YES.
Does anyone know why this might be happening? Or if there is a way for me to debug and find out what the actual error is that is causing the open to fail?

Can't use core database in IOS5

I am working with a core database, it is working in IOS 6 but when I trying to test it on IOS 5. It does not do anything. Let me explain what I'm doing.
First I do this in my viewWillAppear.
- (void)viewWillAppear:(BOOL)animated
{
NSLog(#"view appeared");
[super viewWillAppear:animated];
if (!self.genkDatabase) {
NSLog(#"comes to here");
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:#"Default appGenk Database2"];
// url is now "<Documents Directory>/Default Photo Database"
self.genkDatabase = [[UIManagedDocument alloc] initWithFileURL:url]; // setter will create this for us on disk
NSLog(#"database created on disk");
}
}
Then it comes in the UseDocument method.
- (void)useDocument
{
NSLog(#"Comses in the use document");
if (![[NSFileManager defaultManager] fileExistsAtPath:[self.genkDatabase.fileURL path]]) {
// does not exist on disk, so create it
[self.genkDatabase saveToURL:self.genkDatabase.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:^(BOOL success) {
NSLog(#"create");
[self setupFetchedResultsController];
[self fetchGenkDataIntoDocument:self.genkDatabase];
}];
} else if (self.genkDatabase.documentState == UIDocumentStateClosed) {
NSLog(#"closed news");
// exists on disk, but we need to open it
[self.genkDatabase openWithCompletionHandler:^(BOOL success) {
[self setupFetchedResultsController];
}];
} else if (self.genkDatabase.documentState == UIDocumentStateNormal) {
NSLog(#"normal");
// already open and ready to use
[self setupFetchedResultsController];
}
}
And finally it goes into the setDatabase Method.
- (void)setGenkDatabase:(UIManagedDocument *)genkDatabase
{
if (_genkDatabase != genkDatabase) {
_genkDatabase = genkDatabase;
[self useDocument];
}
NSLog(#"Comes in the setdatabase methode.");
}
Doing all this gives the following log.
2012-10-22 10:42:47.444 RacingGenk[4786:c07] view appeared
2012-10-22 10:42:47.445 RacingGenk[4786:c07] comes to here
2012-10-22 10:42:47.459 RacingGenk[4786:c07] Comses in the use document
2012-10-22 10:42:47.460 RacingGenk[4786:c07] Comes in the setdatabase methode.
2012-10-22 10:42:47.461 RacingGenk[4786:c07] database created on disk
Like you can see it does not print the create log in my use document. So it isn't able to execute the method FetchDataIntoDocument.
Can anybody help me with this problem. I am searching at this problem for ages for now.
Many thanks in advace.
Stef
Are you testing with the simulator or on the device?
The simulator is case-insensitive - the device is case-sensitive on file access, remember that!
But beside from that the documentation for NSFileManager recommends not checking to see if files exist, and instead just trying to read the file and handle any errors gracefully (e.g. file not found error). So just try loading the file instead of checking to see if it exists.
And i don't see any file extension for your database file! It just states ""Default appGenk Database2".
Is this already the file name or jut another subdirectory so far?
EDIT:
You can try the following code:
- (void) setupStore {
NSString* storePath = [[self applicationDocumentsDirectory] stringByAppendingPathComponent: #"mydatabase.sqlite"];
// Set up the store.
NSFileManager* fileManager = [NSFileManager defaultManager];
// If the expected store doesn't exist, create one.
if (![fileManager fileExistsAtPath: storePath]) {
// create your store here!
}
}
- (NSString*) applicationDocumentsDirectory {
return [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
}
"mydatabase.sqlite" is the name of the database-file you expect to be present in your documents directory.
If you would like to see a full-fledged example on how to set-up a core data persistent store you could check out apples own iPhoneCoreDataRecipes example. Just take a look at the
RecipesAppDelegate.m
implementation.

Xcode, ensure codes after blocks run later for NSURLConnection asynchronous request

Hi there: I have been writing an iOS program which uses many http queries to the backend rails server, and hence there are tons of codes like below. In this case, it is updating a UITableView:
//making requests before this...
NSOperationQueue* queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse* response, NSData* data, NSError* error)
{
NSLog(#"Request sent!");
NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
NSLog(#"Response code: %d", [httpResponse statusCode]);
if ([data length] > 0 && error == nil){
NSLog(#"%lu bytes of data was returned.", (unsigned long)[data length]); }
else if ([data length] == 0 &&
error == nil){
NSLog(#"No data was returned.");
}
else if (error != nil){
NSLog(#"Error happened = %#", error); }
id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingAllowFragments error:&error];
if (jsonObject != nil && error == nil){
NSLog(#"Successfully deserialized...");
if ([jsonObject isKindOfClass:[NSDictionary class]]){
NSDictionary *deserializedDictionary = (NSDictionary *)jsonObject;
NSLog(#"Dersialized JSON Dictionary = %#", deserializedDictionary);
[listOfItems addObject:deserializedDictionary];
}
else if ([jsonObject isKindOfClass:[NSArray class]]){
NSArray *deserializedArray = (NSArray *)jsonObject;
NSLog(#"Dersialized JSON Array = %#", deserializedArray);
[listOfItems addObjectsFromArray:deserializedArray];
}
else {
/* Some other object was returned. We don't know how to deal
with this situation as the deserializer only returns dictionaries
or arrays */ }
}
else if (error != nil){
NSLog(#"An error happened while deserializing the JSON data., Domain: %#, Code: %d", [error domain], [error code]);
}
[self.tableView performSelectorOnMainThread:#selector(reloadData) withObject:nil waitUntilDone:YES];
}];
//the place where never runs
NSLog(#"End of function.");
Here is the problem: the last line gets executed usually before the code block. How do I ensure that the code after block actually runs after the block?
I am aware that the block uses some other threads, which is why I use performSelectorOnMainThread function instead of a direct call of [self.tableView reloadData]. But if I want to do something else afterward, how am I supposed to do?
Also, can anyone show some better ways to do this? I am trying to figure out the best way to make massive calls to the backend. There are several ways to make asynchronous requests, including this block way and another old-fashioned way invoking delegate classes. In the progress to refactor the codes, I also tried to create my own delegate class and let other classes invoke that, but it is difficult to identify the correct behaviour of callback functions for which connection's data it returns, especially for classes that use multiple functions to call different requests. And I don't want to use synchronous calls.
Thanks very much for any answers. Also welcome to point out any bugs in the code.
You can using dispatch group
Sample code:
- (void)doSomethingAndWait {
// synchronous method
// called in main thread is not good idea.
NSAssert(! [NSThread isMainThread], #"this method can't run in main thread.");
dispatch_group_t group = dispatch_group_create();
dispatch_group_enter(group);
//making requests before this...
NSOperationQueue* queue = [[NSOperationQueue alloc] init];
[NSURLConnection sendAsynchronousRequest:request queue:queue completionHandler:^(NSURLResponse* response, NSData* data, NSError* error)
{
// your work here.
dispatch_group_leave(group);
}];
// wait for block finished
dispatch_group_wait(group, DISPATCH_TIME_FOREVER);
dispatch_release(group);
//will call until block is finished.
NSLog(#"End of function.");
}
And to call that method, you need avoid call it in main thread.
you should call it like this
dispatch_queue_t queue = dispatch_queue_create("com.COMPANYNAME.APPNAME.TASKNAME", NULL);
dispatch_async(queue, ^{
[self doSomethingAndWait];
});