Effective automatic refresh of UITableview without user interaction (IOS 5) - xcode

I have never coded an App with Push Notifications and I have a very general question.
I would like to refresh a UITableview's data (coming from a webservice) automaticaly without "pull to refresh" or any other user's interaction. Is it possible to use Push notifications to inform my app for a data change, in order to avoid polling every xx seconds wasting bandwidth and battery?
In other words, while my app runs in the foreground (maybe) I can handle the message and the user wont receive a popup but what happens otherwise?
Is there any other way to achieve the same result?
I am going to use IOS 5.0+
Thanks in Advance

You could make a server HTTP-Request which only returns something if there was a change. Then in case this response is not empty you can reload the data. The function you can call by a NSTimer.
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2 target:self selector:#selector(get) userInfo:nil repeats:YES];
and
-(void)get {
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:#"http://example.com/app.php"]];
[[NSURLConnection alloc] initWithRequest:request delegate:self];
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
NSString *responseString = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
if(![responseString isEqualToString:#""]) {
// reload
}
}

When your app is running, you can register to receive push notifications. Then it's simply a matter of implementing the method, making it update your tableview.
- (void)application:(UIApplication *)app didReceiveLocalNotification:(UILocalNotification *)notif {
It's pretty well documented by Apple.

Related

gcdasyncsocket background file transfer

Having two devices that need to keep transferring data while in background or in LockScreen.
The main resource about backgrounding is available on https://developer.apple.com/library/ios/documentation/iPhone/Conceptual/iPhoneOSProgrammingGuide/BackgroundExecution/BackgroundExecution.html
So far I'm looking forward to understand how is it expected to implement such above mentioned behaviour: in a scenario where a transfer is in progress and one of the apps (or both) goes into background. Obviously we have resumable transfer management working already.
I've been collecting stubs and answers about and I've ended up with the following:
Ensure every socket is backgroundable.
[socket performBlock:^{
[socket enableBackgroundingOnSocket];
}];
To keep backgrounding even when in Lock Screen, I read an answer saying that we should have something like at the end of didFinishLaunchingWithOptions but what code is in [self backgroundHandler] method?
BOOL backgroundAccepted = [[UIApplication sharedApplication]
setKeepAliveTimeout:600 handler:^{ [self backgroundHandler]; }];
if (backgroundAccepted)
NSLog(#"background handler accepted");
return YES;
The applicationDidEnterBackground delegate method of UIApplication shows
- (void)applicationDidEnterBackground:(UIApplication *)application {
NSLog(#"=== DID ENTER BACKGROUND ===");
if([[UIDevice currentDevice] respondsToSelector:#selector(isMultitaskingSupported)])
NSLog(#"Multitasking Supported");
else
return;
// Shall I remove my KVO observers when in background?? I guess NOT, right? :D
//[[NSNotificationCenter defaultCenter] removeObserver:self];
UIBackgroundTaskIdentifier bgTask = [[UIApplication sharedApplication] beginBackgroundTaskWithExpirationHandler:^{
NSLog(#"End of tolerate time. Application should be suspended now if we do not ask more 'tolerance'");
// [self askToRunMoreBackgroundTask]; This code seems to be unnecessary. I'll verify it.
}];
if (bgTask == UIBackgroundTaskInvalid)
NSLog(#"This application does not support background mode");
else
NSLog(#"Application will continue to run in background");
// Start the long-running task and return immediately.
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
});
I got it working following this tutorial but looks like GCDAsyncSocket is no longer maintained so it will work only on iOS7.
http://www.objc.io/issue-5/multitasking.html
To do background file transfer under iOS 8 I am using AFNetworking library (http://afnetworking.com)

UIDocumentInteractionController broken in iOS 8

The related code below worked perfect when i was building for iOS 7, but it seems now in iOS 8, it's not working properly.
By properly, I mean in the sense where it's not actually sending the file or whatever to the chosen app.
Example: If I selected Mail, it would open the mail app with the image or zip I chose in the text field. Now it won't send and it takes forever to call/dismiss the UIDocumentInteractionController.
What am I doing wrong?
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
[self.tableView deselectRowAtIndexPath:indexPath animated:NO];
NSString *fileName = [directoryContents objectAtIndex:indexPath.row];
NSString *path;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
path = [[paths objectAtIndex:0] stringByAppendingPathComponent:#"Downloads"];
path = [path stringByAppendingPathComponent:fileName];
documentController = [[UIDocumentInteractionController alloc] init];
documentController = [UIDocumentInteractionController interactionControllerWithURL:[NSURL fileURLWithPath:path]];
[documentController setDelegate:self];
[documentController presentOptionsMenuFromRect:CGRectZero inView:self.view animated:YES];
[documentController retain];
}
I have been playing around with the UIDocumentInteractionController and Delegate trying to fix a similar problem, the controller opened-up alright but selecting an application caused it to close without doing anything, my delegate method documentInteractionControllerDidDismissOpenInMenu also run alright afterwards.
In the console i got the notification enabledRemoteNotificationTypes is not supported in iOS 8.0 and later.
It turns out that this problem will accrue when one of these delegate methods is called :
documentInteractionControllerDidDismissOpenInMenu
documentInteractionControllerDidDismissOptionsMenu
(and possibly others, i did not check all of them)
I did not find any comment in the IOS Development Library or the UIDocumentInteractionController.h about these methods not supported for IOS 8.1 but at this point i cant find any other explanation.
Solution :
i replaced documentInteractionControllerDidDismissOpenInMenu
with didEndSendingToApplication
and it solved the problem for me.

Restkit multipartFormRequestForObject example does not build for me

My viewController has the following method, which gets called after an image gets selected via a UIImagePickerController. I'd like to upload the selected image to my web service, however, when attempting to follow the samples provided by RestKit I get the following error:
No visible #interface for 'RKObjectManager' declares the selector 'multipartFormRequestForObject:method:path:parameters:constructingBodyWithBlock:'
I'm using the most recent version of restkit, and right clicked went to definition to check the signature which seems correct.
It is worth noting that AFMultipartFormData is not highlighting in XCode. I tried including #import AFNetworking/AFHTTPClient.h but it still shows as plain text, which i suspect might be the problem?
-(void) imagePickerController:(UIImagePickerController *)picker didFinishPickingMediaWithInfo:(NSDictionary *)info
{
image = [info objectForKey:UIImagePickerControllerOriginalImage];
[imageView setImage:image];
ImageRecord *imageRecord = [ImageRecord new];
NSDictionary *params = #{#"param1" : #"value1",
#"param2" : #"value2",
#"param3" : #"value3"};
// Serialize the Article attributes then attach a file
NSMutableURLRequest *request = [[RKObjectManager sharedManager] multipartFormRequestForObject:imageRecord method:RKRequestMethodPOST path:#"stuff" parameters:params constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
[formData appendPartWithFileData:UIImagePNGRepresentation(image)
name:#"article[image]"
fileName:#"photo.png"
mimeType:#"image/png"];
}];
RKObjectRequestOperation *operation = [[RKObjectManager sharedManager] objectRequestOperationWithRequest:request success:nil failure:nil];
[[RKObjectManager sharedManager] enqueueObjectRequestOperation:operation]; // NOTE: Must be enqueued rather than started
[self dismissViewControllerAnimated:YES completion:NULL];
}
Thanks for any pointers!
That method is multipartFormRequestWithObject: (note that the method name you're using has ForObject). You shouldn't need to import any additional headers.

xcode presentModalViewController leaves old ViewController still active in background using AVCam

Have a problem with an application using AVCam. The application takes photos and saves them to the roll. Upon opening the app it takes the pictures perfectly and saves them just the way it should. However, once I leave that view controller to go to another view controller and then return, it saves images normal portrait images rotated 90 degrees. Very odd activities indeed.
After lots of hair pulling, I thought maybe I'm trying to run too many sessions, so I make sure I end the sessions in viewdidload and the viewdiddisappear:
-(void)viewDidUnload{
if([[self captureManager] session ]){
[[[self captureManager] session] stopRunning];
self.captureManager = nil;
}
}
-(void)viewDidDisappear:(BOOL)animated{
if([[self captureManager] session ]&&rollCancel==NO){
[[[self captureManager] session] stopRunning];
self.captureManager = nil;
}
}
Still not working. Still saving incorrectly after leaving.
I change views like so:
-(void)openMenu{
MenuViewController * vc = [[MenuViewController alloc] initWithNibName:#"MenuViewController" bundle:nil];
[self presentModalViewController:vc animated:YES];
[self dismissViewControllerAnimated:NO completion:nil];
}
Also tried:
-(void)openMenu{
[self dismissViewControllerAnimated:NO completion:^{
MenuViewController * vc = [[MenuViewController alloc] initWithNibName:#"MenuViewController" bundle:nil];
[self presentModalViewController:vc animated:YES];
[self dismissViewControllerAnimated:NO completion:nil];
}];
}
I don't need to release since I'm running on arc. This did not work as well, I wasn't even able to change screens with this option. SO, I added a timer to see if actions would keep acting after I leave the view controller:
updateTimer = [NSTimer timerWithTimeInterval: 5.0
target: self selector: #selector(autoTimer)
userInfo: nil repeats: YES];
[[NSRunLoop mainRunLoop] addTimer: updateTimer forMode: NSDefaultRunLoopMode];
-(void)autoTimer{
NSLog(#"blablabla");
}
And no big surprise, the blablabla continues to print into my console even after leaving the view controller. If I go back and forth, it will keep making new repeating timers and spam my console log.
This has got to have something to do with my application not saving correctly after returning to the screen. Which means that doing presentmodalviewcontroller does not actually remove everything from running.
Has anybody else ran into a similar issue like this or have any idea how to actually clear view controllers when switching between them?
didn't resolve the NSTimer still running in the background, but did fix the landscape thing which had nothing to do with stuff being open in the background
Found the solution here: https://stackoverflow.com/a/6335992/1688727

How to use NSTimer with data from NSURL pass to NSXMLParser display in TableView

How to use NSTimer with data from NSURL pass to NSXMLParser display in TableView
I have application display data from web server by PHP gen' to XML
In my xcode i use NSURL for connect to PHP file (in web server)
and use NSXMLParser to read XML data put value to array
and final display on TableView
I want to see data in TableView live update or update every x time
I think i can use NSTimer but i don't know how i can
where i can put NSTimer to the code in xcode
In short, something like:
// Schedule a timer repeating every 2 seconds
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self.tableView
selector:#selector(reloadData)
userInfo:nil
repeats:YES];
Longer version:
You need to call -doParse from a timer, fetch data, do parsing, and reload the data.
In order not to block main thread, you must NOT call [[NSXMLParser alloc] initWithContentsOfURL:theURL] from main thread.
Instead:
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_LOW, 0), ^{
NSXMLParser *nsXmlParser = [[NSXMLParser alloc] initWithContentsOfURL:theURL];
...
// finish parsing
dispatch_async(dispatch_get_main_queue(), ^{
[tableView reloadData];
});
});
And call -doParse with a NSTimer from -viewDidLoad :
[NSTimer scheduledTimerWithTimeInterval:2.0
target:self
selector:#selector(doParse)
userInfo:nil
repeats:YES];
Further reading:
WWDC 2012 Session 211 - Building Concurrent User Interfaces on iOS.

Resources