Update progress with MRProgress - ios

I'm looking for help with trying to update a progress indicator using the MRProgress framework. I was able to set up the progress indicator, but I have no idea how to calculate and update its progress. I'm using CloudKit and trying to show the progress when saving a CKRecord. Could someone provide me some direction? Thanks in advance!
self.hud = [MRProgressOverlayView showOverlayAddedTo:self.myCollectionView animated:YES];
self.hud.mode = MRProgressOverlayViewModeDeterminateCircular;
self.hud.titleLabelText = #"Uploading...";
// prepare the CKRecord and save it
[self.ckManager saveRecord:[self.ckManager createCKRecordForImage:self.imageDataAddedFromCamera] withCompletionHandler:^(CKRecord *record, NSError *error) {
if (!error && record) {
NSLog(#"INFO: Record saved successfully for recordID: %#", record.recordID.recordName);
// need to get the recordID of the just saved record before adding the CID to the CIDArray
self.imageDataAddedFromCamera.recordID = record.recordID.recordName;
[self.imageLoadManager addCIDForNewUserImage:self.imageDataAddedFromCamera]; // update the model with the new image
// update number of items since array set has increased from new photo taken
self.numberOfItemsInSection = [self.imageLoadManager.imageDataArray count];
//[MRProgressOverlayView dismissAllOverlaysForView:self.view animated:YES];
[self.hud dismiss:YES];
[self.hud removeFromSuperview];
} else {
NSLog(#"ERROR: Error saving record to cloud...%#", error.localizedDescription);
[self alertWithTitle:#"Yikes!" andMessage:#"We encountered an issue trying to upload your photo to the cloud."];
}
}];
Update: Converted cloudkit methods from convenience API to CKOperations in my CKManager class. I can see the progress updating through logging, but I don't see how to get it back to the viewcontroller. If I were to add it to the completion handler, wouldn't that only send it back once everything is completed? Here's my updated code...
CKManager.h
- (void)saveRecord:(NSArray *)records withCompletionHandler:(void (^)(NSArray *records))completionHandler;
CKManager.m
- (void)saveRecord:(NSArray *)records withCompletionHandler:(void (^)(NSArray *))completionHandler {
NSLog(#"INFO: Entered saveRecord...");
CKModifyRecordsOperation *saveOperation = [[CKModifyRecordsOperation alloc] initWithRecordsToSave:records recordIDsToDelete:nil];
saveOperation.perRecordProgressBlock = ^(CKRecord *record, double progress) {
if (progress <= 1) {
NSLog(#"Save progress is: %f", progress);
}
};
saveOperation.completionBlock = ^ {
NSLog(#"Save operation completed!");
completionHandler(records);
};
[self.publicDatabase addOperation:saveOperation];
}

if you want to show the progress of an operation, then you have to use the CKModifyRecordsOperation and use perRecordProgressBlock method.

Related

How to call same service multiple time and store data in ios

I have a situation where I will be getting more than 25000 records from web service, it is sending using pagination technique.
so the problem is I just want to store the data so for that I am thinking to run it in a loop but in future records may vary (i.e 30000,50000 etc)
from backend I am getting on each page 10000 records,but i dont know how many times i have run the loop so how do I handle this problem?
-(void)vendorsListCalling:(NSInteger)pageIndex{
[[ServicesHandler new] callVendorDetailsServiceWithParams:#{#"pageno":#(pageIndex)} CompletionBLock:^(NSDictionary *response, NSError *error) {
if (error) {
NSLog(#"error log %#",error.localizedDescription);
}else{
NSDictionary *dict = response[#"params"][#"data"];
[vendorDictionay addEntriesFromDictionary:dict];
pageCount++;
[[NSUserDefaults standardUserDefaults] setObject:vendorDictionay forKey:#"vendorsDict"];
}
}];
}
above block is where i stuck .
Any suggestions would be more appreciated.
You can store data into sqlite database. And for recursive calling for service, you can modify the same method as,
-(void)vendorsListCalling:(NSInteger)pageIndex {
if (!loader) {
//Write code to Show your loader here
}
[[ServicesHandler new] callVendorDetailsServiceWithParams:#{#"pageno":#(pageIndex)} CompletionBLock:^(NSDictionary *response, NSError *error) {
if (error) {
NSLog(#"error log %#",error.localizedDescription);
//If it fails you need to call the service again with the same Index
[self vendorsListCalling:pageCount];
} else {
if (!response[#"params"][#"data"]) {
//Stop loader since you didn't received any data
} else {
NSDictionary *dict = response[#"params"][#"data"];
[vendorDictionay addEntriesFromDictionary:dict];
pageCount++;
// Store Data in database here //
//Call service with incremented Index
[self vendorsListCalling:pageCount];
}
}
}];
}

Code Not Completing Before Next Method Is Called

In my iOS app, I am using the forecast.io API to get a weather forecast for 3 specific days. Once I get the array from all 3, I want to create an NSMutableArray and add all of those objects to it. The problem I am getting is that it is trying to create the NSMutableArray before the forecast data is retrieved. Here is what I have so far:
typedef void(^myCompletion)(BOOL);
-(void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:YES];
[self myMethod:^(BOOL finished) {
if(finished){
NSMutableArray *allOfIt = [[NSMutableArray alloc] initWithObjects:self.weatherSaturday, self.weatherSunday, self.weatherMonday, nil];
NSLog(#"%#", allOfIt);
}
}];
}
-(void) myMethod:(myCompletion) compblock{
//do stuff
ForecastKit *forecast = [[ForecastKit alloc] initWithAPIKey:#"MY-API-KEY"];
// Request the forecast for a location at a specified time
[forecast getDailyForcastForLatitude:37.438905 longitude:-106.886051 time:1467475200 success:^(NSArray *saturday) {
// NSLog(#"%#", saturday);
self.weatherSaturday = saturday;
} failure:^(NSError *error){
NSLog(#"Daily w/ time %#", error.description);
}];
[forecast getDailyForcastForLatitude:37.438905 longitude:-106.886051 time:1467561600 success:^(NSArray *sunday) {
// NSLog(#"%#", sunday);
self.weatherSunday = sunday;
} failure:^(NSError *error){
NSLog(#"Daily w/ time %#", error.description);
}];
[forecast getDailyForcastForLatitude:37.438905 longitude:-106.886051 time:1467648000 success:^(NSArray *monday) {
// NSLog(#"%#", monday);
self.weatherMonday = monday;
} failure:^(NSError *error){
NSLog(#"Daily w/ time %#", error.description);
}];
compblock(YES);
}
When the code is ran, it fires the NSLog for allOfIt, which shows as null, before it gets any of the forecast data. What am I missing?
The problem I am getting is that it is trying to create the NSMutableArray before the forecast data is retrieved
Yup, exactly. The problem is simply that you don't understand what "asynchronous" means. Networking takes time, and it all happens in the background. Meanwhile, your main code does not pause; it is all executed instantly.
Things, therefore, do not happen in the order in which your code is written. All three getDailyForcastForLatitude calls fire off immediately and the whole method ends. Then, slowly, one by one, in no particular order, the server calls back and the three completion handlers (the stuff in curly braces) are called.
If you want the completion handlers to be called in order, you need each getDailyForcastForLatitude call to be made in the completion handler of the getDailyForcastForLatitude call that precedes it. Or, write your code in such a way that it doesn't matter when and in what order the completion handlers come back to you.

On select row of WKInterfaceTable transfer data to Iphone

I'm making watch app for iOS application. I get data from parent application in watch main InterfaceController and pass it to other InterfaceController for creating table. Here code of configuring table:
- (void)configureTableWithData:(NSArray*)dataObjects {
[self.table setNumberOfRows:[dataObjects count] withRowType:#"rowType"];
for (NSInteger i = 0; i < self.table.numberOfRows; i++) {
RowType* row = [self.table rowControllerAtIndex:i];
NSObject* object = [dataObjects objectAtIndex:i];
[row.titleName setText:[object valueForKey:#"CharCode"]];
[row.bottomValue setText:[object valueForKey:#"Value"]];
}
}
When I select row, I want to transfer data back to first page. It's need for changing some label on first page. I'm doing it with transfer data to parent app and return it back to main InterfaceController
- (void)table:(WKInterfaceTable *)table didSelectRowAtIndex:(NSInteger)rowIndex {
//Here must be dictionary, where I put row
[WKInterfaceController openParentApplication:data reply:^(NSDictionary *replyInfo, NSError *error) {
NSLog(#"data transfer");
}];
[self dismissController];
}
How can I get data of row? (row.titleName, row.value) May be it's stupid question, I am still just a beginner, but I can get it. I tried to print on console row.titleName and row.bottomValue and of course I've get nothing. (sorry for my english, not my mother tongue) What did I miss?
I have same issue with watch kit in tableview. For now we only set the text in cell label not get back so you have to do like this
- (void)table:(WKInterfaceTable *)table didSelectRowAtIndex:(NSInteger)rowIndex {
//Here must be dictionary, where I put row
NSDictionary* object = [dataObjects objectAtIndex:rowIndex];
NSLog("used object as you want");
[WKInterfaceController openParentApplication:object reply:^(NSDictionary *replyInfo, NSError *error) {
NSLog(#"data transfer");
}];
[self dismissController];
}

AFNetworking 2.0, saving download state with CoreData (MagicalRecord)

i'm having an issue with a app that uses AFNetworking 2.0 and MagicalRecord. This app downloads data from a little JSON API in a podcast site and stores every podcast episode in a Podcast entity.
This Podcast Entity has another entity called PodcastDownload that keep information when a podcast is downloading (Download status and progress). In this PodcastDownload entity i use KVO to update this information observing the NSProgress object and state from the NSURLSessionDownloadTask. This works fine.
But I have a problem when I try to save the download status in my data context with this method in a singleton instance called PodcastManager:
- (void)saveContext{
[[NSManagedObjectContext defaultContext] saveToPersistentStoreWithCompletion:^(BOOL success, NSError *error) {
if (success) {
NSLog(#"Save OK");
} else if(error) {
NSLog(#"Error %#", error.description);
}
}];
}
When I call this method I get this EXC_BAD_ACCESS error in the AFURLSessionManager from AFNetworking, but saving seems tu run ok according to my log:
Context BACKGROUND SAVING (ROOT) is about to save. Obtaining permanent IDs for new 1 inserted objects
I don't know what is causing this error. I Also tried using MagicalRecord method saveWithBlock but I got the same result.
This is my source code for my KVO Observer inside PodcastDownload:
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
if (context == PodcastDownloadContext) {
if ([object isKindOfClass:[NSURLSessionDownloadTask class]]) {
NSURLSessionDownloadTask *task = (NSURLSessionDownloadTask *) object;
if (task.state == NSURLSessionTaskStateRunning) {
[self setStatus:PodcastDownloadRunning];
[[PodcastManager sharedManager] saveContext];
}
if (task.state == NSURLSessionTaskStateSuspended) {
[self setStatus:PodcastDownloadSuspended];
[[PodcastManager sharedManager] saveContext];
}
if (task.state == NSURLSessionTaskStateCanceling) {
[self setStatus:PodcastDownloadCanceling];
self.downloadTask = nil;
self.data = nil;
self.progress = 0;
[[PodcastManager sharedManager] saveContext];
}
if (task.state == NSURLSessionTaskStateCompleted) {
if (self.status == PodcastDownloadCanceling) {
[self setStatus:PodcastDownloadNotSet];
} else {
[self setStatus:PodcastDownloadCompleted];
self.downloadTask = nil;
self.data = nil;
self.progress = 0;
[[PodcastManager sharedManager] saveContext];
}
#try {
[object removeObserver:self forKeyPath:NSStringFromSelector(#selector(state)) context:PodcastDownloadContext];
[object removeObserver:self forKeyPath:NSStringFromSelector(#selector(fractionCompleted)) context:PodcastDownloadContext];
}
#catch (NSException * __unused exception) {}
}
}
}
}
Thank you so much
Well, making some changes I find out a solution, but not the cause.
I had three entities in my Core Data stack (Podcast, PodcastDownload and PodcastPlayback). The main entity is Podcast and PodcastDownload was used to save information about the download, as I explained in my question.
What I did was take the attributes out from PodcastDownload and put them in the Podcast entity. And now seems to work as it should.
I don't know the exact cause of the error, but I think it was related with threading (sorry, I'm still a little noob with objective-c).
Thanks for all the help.

gamecenter turnbased save match data out of turn

Any chance I can save/update matchdata even when it is not my turn?
[currentMatch saveCurrentTurnWithMatchData:data completionHandler:^(NSError *error) {
if (error)
{ }];
The above code can be used if it is still this user's turn, but what if it is not this user's turn? How do I send data between two players?
As of iOS 6.0, you cannot. :(
You can save match data without advancing the turn (assuming you are
the current player). see - saveCurrentTurnWithMatchData:completionHandler:
You can end a game out of turn. see - participantQuitOutOfTurnWithOutcome:withCompletionHandler:
However, you cannot update match data out of turn.
GKTurnBasedMatch Reference
Try this
- (void) advanceTurn
{
NSData *updatedMatchData = [this.gameData encodeMatchData];
NSArray *sortedPlayerOrder = [this.gameData encodePlayerOrder];
this.MyMatch.message = [this.gameData matchAppropriateMessage];
[this.myMatch endTurnWithNextParticipants: sortedPlayerOrder turnTimeOut: GKTurnTimeoutDefault
matchData: updatedMatchData completionHandler ^(NSError *error) {
if (error)
{
// Handle the error.
}
}];
}

Resources