Saving to iCloud with saveToURL:forSaveOperation: completionHandler: fails - ios

I am trying to save a Dictionary of objects to iCloud but when I do it method saveToURL:forSaveOperation: completionHandler: fails. I also tried to override:
- (BOOL)writeContents:(id)contents
andAttributes:(NSDictionary *)additionalFileAttributes
safelyToURL:(NSURL *)url
forSaveOperation:(UIDocumentSaveOperation)saveOperation
error:(NSError **)outError
and of course the super call also returns false. Yet, I would have liked to read the error, but when I try to have the localizedError the compiler reports an error claiming it is not a structure or union.
This is the full piece of code:
-(instancetype)initWithSingleton{
NSURL *ubiq = [[NSFileManager defaultManager]
URLForUbiquityContainerIdentifier:nil];
NSURL *ubiquitousPackage = [[ubiq URLByAppendingPathComponent:
#"Stops"] URLByAppendingPathComponent:kFILENAME];
NSLog(#"file url=%#", ubiquitousPackage);
self=[self initWithFileURL:ubiquitousPackage];
if (self!=nil){
self.favoriteStops=[[NSMutableDictionary alloc] init];
NSURL *ubiq = [[NSFileManager defaultManager]
URLForUbiquityContainerIdentifier:nil];
if (ubiq) {
NSLog(#"iCloud access at %#", ubiq);
[self loadDocument];
} else {
NSLog(#"No iCloud access");
}
}
return self;
}
#define kFILENAME #"favorite.dox"
- (void)loadData:(NSMetadataQuery *)query {
if ([query resultCount] == 1) {
NSMetadataItem *item = [query resultAtIndex:0];
NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLResponse *response;
NSData *GETReply= [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:nil];
NSMutableDictionary* dict=[NSKeyedUnarchiver unarchiveObjectWithData:GETReply];
[self setFavoriteStops:dict];
NSLog(#"favorites: %#", favoriteStops);
[self openWithCompletionHandler:^(BOOL success) {
if (success) {
NSLog(#"iCloud document opened");
} else {
NSLog(#"failed opening document from iCloud");
}
}];
}
}
- (void)queryDidFinishGathering:(NSNotification *)notification {
NSMetadataQuery *query = [notification object];
[query disableUpdates];
[query stopQuery];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSMetadataQueryDidFinishGatheringNotification
object:query];
_query = nil;
[self loadData:query];
}
- (BOOL)loadFromContents:(id)contents ofType:(NSString *)typeName
error:(NSError **)outError
{
if ([contents length] > 0) {
[self setFavoriteStops:[NSKeyedUnarchiver unarchiveObjectWithData:contents]];
}
return YES;
}
- (BOOL)writeContents:(id)contents
andAttributes:(NSDictionary *)additionalFileAttributes
safelyToURL:(NSURL *)url
forSaveOperation:(UIDocumentSaveOperation)saveOperation
error:(NSError **)outError{
//logging
NSString *str;
str= [[NSString alloc] initWithData:contents encoding:NSUTF8StringEncoding];
NSLog(#"saving data %#", str);
//logging
NSMutableDictionary *dict=[NSKeyedUnarchiver unarchiveObjectWithData:contents];
NSLog(#"dict=%#", dict);
BOOL success= [super writeContents:contents
andAttributes:additionalFileAttributes
safelyToURL:url
forSaveOperation:saveOperation
error:outError];
NSLog(#"error :%#", outError.localizedDescription) //syntax error
return success;
}
-(void) save{
NSLog(#"file url=%#", [self fileURL]);
[self saveToURL:[self fileURL]
forSaveOperation:UIDocumentSaveForOverwriting
completionHandler:^(BOOL success) {
if (success) { //this returns false
[self openWithCompletionHandler:^(BOOL success) {
NSLog(#"new document saved on iCloud");
}];
} else {
NSLog(#"error in iCloud Saving");
}
}];
}
- (id)contentsForType:(NSString *)typeName error:(NSError **)outError
{
NSLog(#"favorite stops=%# class=%#", self.favoriteStops, [favoriteStops class]);
NSData *archivedData=[NSKeyedArchiver archivedDataWithRootObject:self.favoriteStops];
return archivedData;
}
When I log the url on which to save, that is:
file:///private/var/mobile/Library/Mobile%20Documents/iCloud~com~information~inArrivo/Stops/favorite.dox
And when I check the error on the debugger it is:
Error Domain=NSCocoaErrorDomain Code=4 "The operation couldn’t be
completed. (Cocoa error 4.)" UserInfo=0x17bd6cb0
{NSFileNewItemLocationKey=file:///private/var/mobile/Applications/445778BF-86AF-4DE3-9E1B-BAC8F79D14D0/tmp/(A%20Document%20Being%20Saved%20By%20In%20Arrivo%20HD)/favorite.dox,
NSFileOriginalItemLocationKey=file:///private/var/mobile/Library/Mobile%20Documents/iCloud~com~information~inArrivo/Stops/favorite.dox,
NSUnderlyingError=0x17bfa860 "The operation couldn’t be completed.
(Cocoa error 4.)",
NSURL=file:///private/var/mobile/Library/Mobile%20Documents/iCloud~com~information~inArrivo/Stops/favorite.dox}
How may I fix it or at least know more?

The TSI Apple team answered me and provided me with a working class. Upon checking their version with mine the change seems to boil down to an update to - (void)queryDidFinishGathering:(NSNotification *)notification; by adding:
if (query.results == 0)
{
[self save]; // no favorites file, so create one
}
to make it as follows:
- (void)queryDidFinishGathering:(NSNotification *)notification {
NSMetadataQuery *query = [notification object];
[query disableUpdates];
[query stopQuery];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSMetadataQueryDidFinishGatheringNotification
object:query];
//•• added
if (query.results == 0)
{
[self save]; // no favorites file, so create one
}
[self loadData:query];
_query = nil;
}

Related

iCloud file storage/exchange across devices

I am trying to store data to iCloud documents, and read it on another device logged in with the same account.
I can detect iCloud, send data to iCloud and read it back on the same device. I can detect the file is there from the second device, but I get an error 'NSCocoaDomainError - code 260' when I try to read or copy the file.
File Store code:
//CREATE FILE
NSError *error;
NSLog(#"string to write:%#",printString);
NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
if (ubiq == nil) {
return;
}
NSURL *cloudURL =[[ubiq URLByAppendingPathComponent:#"Documents" isDirectory:true] URLByAppendingPathComponent:#"CogwindInventory.txt"];
[printString writeToURL:cloudURL atomically:YES encoding:NSUTF8StringEncoding error:&error];
Code to run the query:
self.backups = [[NSMutableArray alloc] init];
self.query = [[NSMetadataQuery alloc] init];
[self.query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
NSPredicate *pred = [NSPredicate predicateWithFormat: #"%K like 'CogwindInventory.txt'", NSMetadataItemFSNameKey];
[self.query setPredicate:pred];
[[NSNotificationCenter defaultCenter] addObserver:self
selector:#selector(queryDidFinishGatheringRestore:)
name:NSMetadataQueryDidFinishGatheringNotification
object:self.query];
[self.CloudActivityIndicator startAnimating];
[self.query startQuery];
- (void)queryDidFinishGatheringRestore:(NSNotification *)notification {
NSMetadataQuery *query = [notification object];
[query disableUpdates];
[query stopQuery];
[self loadDataRestore:query];
[[NSNotificationCenter defaultCenter] removeObserver:self name:NSMetadataQueryDidFinishGatheringNotification object:query];
self.query = nil;
}
- (void)loadDataRestore:(NSMetadataQuery *)query {
[self.backups removeAllObjects];
for (NSMetadataItem *item in [query results]) {
NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
//[self.backups addObject:url.lastPathComponent];
[self.backups addObject: url.filePathURL];
}
if (self.backups.count > 0) {
[self retrievefile];
}
[self OperationComplete];
}
Code to do the read:
- (void) retrievefile
{
NSError *error = nil;
NSURL *ubiq = [self.manager URLForUbiquityContainerIdentifier:nil];
if (ubiq == nil) {
return;
}
NSURL *cloudURL =[self.backups objectAtIndex:0];
NSArray *localtoken = [[NSString stringWithContentsOfURL:cloudURL encoding:NSUTF8StringEncoding error:&error] componentsSeparatedByString:#"\n"];
if ((localtoken == nil) || (error !=nil)) {
[self.CloudStatusText setText: #"Restore operation failed."];
return;
} else {
[self.tokeninventory setPlayerInventoryNames:localtoken];
[self.CloudStatusText setText: #"Restore operation successful. New inventory available"];
}
}
The devices are OS 8.1.1 and OS 8.3. iCloud- Documents is enabled in Xcode, but not iCloudKit.
Any help appreciated. Thank you.

NSURLConnection Delegate not working properly in one situation

I've read lots of posts regarding this problem but I couldn't get the callback delegate to work...
I've read that delegate cannot be in a background Thread or it won't get called. I think that this may be the issue... but... well let me put some code here to explain better my problem and see what you guys think.
in main thread
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
#try {
ALAssetsLibrary *assetLibrary=[[ALAssetsLibrary alloc] init];
[assetLibrary assetForURL:[object valueForKey:UIImagePickerControllerReferenceURL] resultBlock:^(ALAsset *asset)
{
ALAssetRepresentation *rep = [asset defaultRepresentation];
Byte *buffer = (Byte*)malloc(rep.size);
NSUInteger buffered = [rep getBytes:buffer fromOffset:0.0 length:rep.size error:nil];
NSData *data = [NSData dataWithBytesNoCopy:buffer length:buffered freeWhenDone:YES];//this is NSData may be what you want
//[data writeToFile:photoFile atomically:YES];//you can save image later
UIImage *image = [UIImage imageWithData:data];
CGFloat compression = 0.9f;
CGFloat maxCompression = 0.5f;
int maxFileSize = 1280*720; //ou usar 40960 = 40MB ?
NSData *imageData = UIImageJPEGRepresentation(image, compression);
while ([imageData length] > maxFileSize && compression > maxCompression)
{
compression -= 0.1;
imageData = UIImageJPEGRepresentation(image, compression);
}
NSString *guid = [self.idMediasAvailable lastObject];
//NSString *guid = [[NSUUID UUID] UUIDString];
NSString *boundary = #"-endUploadBoundary-";
NSString *contentType = [NSString stringWithFormat:#"multipart/form-data; boundary=%#",boundary];
[client addBlobToContainer:[container objectAtIndex:self.mycontainerIndex] blobName:[NSString stringWithFormat:#"%#.jpg", guid] contentData:imageData contentType:contentType ];
[uploadedMediaID setObject:object forKey:guid];
[confirmMedias addObject:guid];
[listUploadedMedias addObject:object];
[self.idMediasAvailable removeLastObject];
// [allUploadedLock lock];
// [allUploadedLock unlockWithCondition:0];
}
failureBlock:^(NSError *err) {
NSLog(#"Error: %#",[err localizedDescription]);
[allUploadedLock lock];
[allUploadedLock unlockWithCondition:0];
}];
}
#catch (NSException *exception) {
NSLog(#"Error uploadMedia: %#",[object valueForKey:UIImagePickerControllerReferenceURL]);
}
});
[allUploadedLock lockWhenCondition:0];
[allUploadedLock unlock];
this is the addToBlobContainer selector:
- (void)addBlobToContainer:(BlobContainer *)container blobName:(NSString *)blobName contentData:(NSData *)contentData contentType:(NSString*)contentType withBlock:(void (^)(NSError*))block
{
CloudURLRequest* request = nil;
if(_credential.usesProxy)
{
request = [_credential authenticatedRequestWithEndpoint:#"/SharedAccessSignatureService/blob" forStorageType:#"blob" httpMethod:#"PUT" contentData:contentData contentType:contentType, #"x-ms-blob-type", #"BlockBlob", nil];
}
else
{
NSString* containerName = [container.name lowercaseString];
NSString* endpoint = [NSString stringWithFormat:#"/%#/%#", [containerName URLEncode], [blobName URLEncode]];
request = [_credential authenticatedRequestWithEndpoint:endpoint forStorageType:#"blob" httpMethod:#"PUT" contentData:contentData contentType:contentType, #"x-ms-blob-type", #"BlockBlob", nil];
}
[request fetchNoResponseWithBlock:^(NSError* error)
{
if(error)
{
if(block)
{
block(error);
}
else if([(NSObject*)_delegate respondsToSelector:#selector(storageClient:didFailRequest:withError:)])
{
[_delegate storageClient:self didFailRequest:request withError:error];
}
return;
}
if(block)
{
block(nil);
}
else if([(NSObject*)_delegate respondsToSelector:#selector(storageClient:didAddBlobToContainer:blobName:)])
{
[_delegate storageClient:self didAddBlobToContainer:container blobName:blobName];
}
}];
}
no breakpoint is hit inside the block [request fetchNoResponseWithBlock:ˆ(NSError *error) ...];
and this is the fetchNoResponseWithBlock:ˆ selector:
- (void) fetchNoResponseWithBlock:(noResponseBlock)block {
_noResponseBlock = [block copy];
[NSURLConnection connectionWithRequest:self delegate:self];
}
and in this same file I have the delegate selectors
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
and none of these are hit as well... btw the interface declaration is #interface CloudURLRequest : NSMutableURLRequest
Ok now the strange thing is that the breakpoints inside the delegate selectors
are hit when the page is opened and another request is made to get the Blob Containers... but when I try to send a file the file is sent and there is no callback! (I manually check the blob and it uploaded successfully)
I think that when I do this:
[assetLibrary assetForURL:[object valueForKey:UIImagePickerControllerReferenceURL] resultBlock:^(ALAsset *asset) {
is this block running on a background thread by any chance? or Any suggestions?
I do need the callback to work because I have to unlock a NSLock only when the file completes the upload.
Thanks a lot in advance!

Save recorded video from AVFoundation

I am not able to save the recorder video from AVFoundation... In didfinishcapture I check if file exists in the temporary folder, code always returns NO.
Also, this warning is printed when i stop the recording:
"cannot be saved to the saved photos album: Error Domain=NSOSStatusErrorDomain Code=2 "This movie could not be played." UserInfo=0x1c5696c0 {NSLocalizedDescription=This movie could not be played.}"
#define OP_PATH [NSTemporaryDirectory() stringByAppendingPathComponent:[#"movie" stringByAppendingPathExtension:#"mov"]]
- (IBAction) startSession:(id)sender
{
if(! self.captureSession)
{
//Session
self.captureSession = [[AVCaptureSession alloc] init];
//self.captureSession.sessionPreset = AVCaptureSessionPresetMedium;
//Layer of own view
CALayer *viewLayer = self.captureView.layer;
//AVCaptureVideoPreviewLayer
AVCaptureVideoPreviewLayer *avCaptureLayer = [[AVCaptureVideoPreviewLayer alloc] initWithSession:self.captureSession];
avCaptureLayer.frame = self.captureView.bounds;
[self.captureView.layer addSublayer:avCaptureLayer];
//AVCaptureDevice
AVCaptureDevice *device = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeVideo];
NSError *err = nil;
//Output - Image
self.stillImgOutput = [[AVCaptureStillImageOutput alloc] init];
[self.stillImgOutput setOutputSettings:[NSDictionary dictionaryWithObjectsAndKeys:
AVVideoCodecJPEG, AVVideoCodecKey,
nil]];
[self.captureSession addOutput:self.stillImgOutput];
//Output - Video
self.movieOutput = [[AVCaptureMovieFileOutput alloc] init];
// NSString* key = (NSString*)kCVPixelBufferBytesPerRowAlignmentKey;
//
// NSNumber* value = [NSNumber numberWithUnsignedInt:kCVPixelFormatType_32BGRA];
//
// NSDictionary* videoSettings = [NSDictionary dictionaryWithObject:value forKey:key];
if([self.captureSession canAddOutput:self.movieOutput])
{
NSLog(#"Movie out put added");
[self.captureSession addOutput:self.movieOutput];
}
else
{
NSLog(#"Cannot add movie out put");
}
//Input
AVCaptureDeviceInput *input = [AVCaptureDeviceInput deviceInputWithDevice:device error:&err];
if(! input)
{
NSLog(#"Error no camera");
return;
}
if([self.captureSession canAddInput:input])
{
[self.captureSession addInput:input];
}
else
{
NSLog(#"Cannot add input. Check Output Settings");
}
}
if(! [self.captureSession isRunning])
{
[self.captureSession startRunning];
}
else
{
NSLog(#"Session already running");
}
}
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error
{
NSLog(#"Did stop recording to - %# \n Any error ? - %#", outputFileURL, [error description]);
if([[NSFileManager defaultManager] fileExistsAtPath:[outputFileURL absoluteString]])
{
NSLog(#"YES file exists");
}
else
{
NSLog(#"NO File does not exist");
}
if(UIVideoAtPathIsCompatibleWithSavedPhotosAlbum([outputFileURL absoluteString]))
{
NSLog(#"YES file is compatible to be saved in Album");
UISaveVideoAtPathToSavedPhotosAlbum([outputFileURL absoluteString], self, #selector(video:didFinishSavingWithError:contextInfo:), nil);
}
else
{
NSLog(#"NO File is not compatible");
}
}
- (void)video:(NSString *)videoPath didFinishSavingWithError:(NSError *)error contextInfo:(void *)contextInfo
{
if(! error)
{
NSLog(#"Video Saved to Album");
}
else
{
NSLog(#"Video not saved to Album - %#", [error description]);
}
NSError *er;
[[NSFileManager defaultManager] removeItemAtPath:OP_PATH error:&er];
if(! er)
{
NSLog(#"Temporary file deleted");
}
else
{
NSLog(#"Temporary file not deleted - %#", [er description]);
}
}
You are missing the following piece of code. See below
//Use timestamp to get new movie name everytime you capture
NSString *timeStamp = [NSString stringWithFormat:#"%0.0f",[[NSDate date] timeIntervalSince1970] * 1000];
NSString *movieOutputUrl =[NSTemporaryDirectory() stringByAppendingPathComponent:[NSString stringWithFormat:#"%#.mov",timeStamp]];
NSURL *url = [NSURL URLWithString:movieOutputUrl];
[self.movieOutput startRecordingToOutputFileURL:url recordingDelegate:self];
I hope it helps.
Cheers.
- (void)captureOutput:(AVCaptureFileOutput *)captureOutputdidFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL fromConnections:(NSArray *)connections error:(NSError *)error
{
if (error)
{
NSLog(#"%#", error);
}
UIBackgroundTaskIdentifier backgroundRecordingID = [self backgroundRecordingID];
[self setBackgroundRecordingID:UIBackgroundTaskInvalid];
[[[ALAssetsLibrary alloc] init] writeVideoAtPathToSavedPhotosAlbum:outputFileURL completionBlock:^(NSURL *assetURL, NSError *error) {
if (error)
{
NSLog(#"%#", error);
}
[[NSFileManager defaultManager] removeItemAtURL:outputFileURL error:nil];
if (backgroundRecordingID != UIBackgroundTaskInvalid)
{
[[UIApplication sharedApplication] endBackgroundTask:backgroundRecordingID];
}
}];
}
Hope can help.

authorizeRequest oAuth not called from another class?

I'm currently using Oauth2SampleTouch by Google, so people can log-in with their google accounts into my app. However whenever I call a method from The SampleRootViewController it doesn't go through the authorizeRequest method (only if I call it from another class.).
Here's the method in SampleRootViewController that I'm calling form another class.(the user is already logged in by this time)
-(NSString *)hasLikedVideo:(NSString *)videoID {
liked = #"NULL";
NSString *clientID = #"myClientID";
NSString *clientSecret = #"myClientSecret";
self.auth = [GTMOAuth2ViewControllerTouch authForGoogleFromKeychainForName:kKeychainItemName
clientID:clientID
clientSecret:clientSecret];
NSString *urlStr = [NSString stringWithFormat:#"https://www.googleapis.com/youtube/v3/videos/getRating?id=%#&key=AIzaSyB437bMtpbJh-OrkieCDRtYLe6L1Ijb3Ww", videoID];
NSLog(#"URL FOR LIKE : %# auth:(%#)", urlStr, self.auth);
NSURL *url = [NSURL URLWithString:urlStr];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
NSLog(#"stage 1");
[self.auth authorizeRequest:request
completionHandler:^(NSError *error) {
if (error == nil) {
// the request has been authorized
NSLog(#"ERROR LOADING AUTH 1 : %#", [error description]);
} else {
NSLog(#"ERROR LOADING AUTH 2 : %#", [error description]);
}
NSLog(#"stage 2");
NSString *output = nil;
if (error) {
output = [error description];
NSLog(#"ERROR FROM LOADING LIKE INFO : %#", output);
} else {
NSLog(#"stage 3");
NSURLResponse *response = nil;
NSData *data = [NSURLConnection sendSynchronousRequest:request
returningResponse:&response
error:&error];
[self displayAlertWithMessage:output];
if (data) {
// API fetch succeeded
NSLog(#"stage 32");
output = [[NSString alloc] initWithData:data
encoding:NSUTF8StringEncoding];
// NSLog(#"%#", data);
[self displayAlertWithMessage:output];
} else {
NSLog(#"stage 34");
// fetch failed
output = [error description];
[self displayAlertWithMessage:output];
}
}
NSData* json = [output dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *allCourses = [NSJSONSerialization
JSONObjectWithData:json
options:kNilOptions
error:&error];
NSArray *monday = allCourses[#"items"];
for ( NSDictionary *theCourse in monday )
{
liked = theCourse[#"rating"];
NSLog(#"LIKE INSIDE ARRAY : %#", theCourse[#"rating"]);
}
if( error )
{
NSLog(#"%#", [error localizedDescription]);
}
}];
NSLog(#"stage 4");
return liked;
}
The method runs because I can see it log the string, however it doesn't go through the authorizeRequest, it doesn't even print out the error messages. HOWEVER if my viewController is SampleRootViewController and I call the method from itself it works.
So basically
TestViewcontroller calls a method in SampleRootViewController -> doesn't go through authorizeRequest.
SampleRootViewController calls a method in SampleRootViewController (from itself) -> goes through authorizeRequest and works.
EDIT:
I found out what I was doing "wrong"
I was calling the method like this in background
[self performSelectorInBackground:#selector(getAuthDetails) withObject:nil];
instead of
[self getAuthDetails];

shouldPerformSegueWithIdentifier issue

I tried too much to solve my bellow issue but i am failed.Please help me to solve this issue. I have login view and after validating id and password i am pushing it to next view controller.Please check bellow image.
Issue - When Id and Password is correct it's pushing to next view controller but after 2 clicks on login button.
Code -
ServiceManager.m
-(void)initGetAppServiceRequestWithUrl:(NSString *)baseUrl onCompletion:
(ServiceCompletionHandler)handler
{
NSString *fullUrl = [NSString stringWithFormat:#"%#",[baseUrl
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL
URLWithString:fullUrl]];
[NSURLConnection sendAsynchronousRequest:(NSURLRequest *)request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,NSData *data,NSError *error)
{
if (error) {
handler(nil,error);
// NSLog(#"error = %#",error);
}
else
{ handler(data, nil);
// NSLog(#"data = %#",data);
}
}];
}
JSONResponseHandler.m
+(void)handleResponseData:(NSData *)responseData onCompletion:(JSONHandler)handler
{
if (responseData) {
NSError *jsonParseError;
NSDictionary *json = [NSJSONSerialization JSONObjectWithData:responseData
options:kNilOptions error:&jsonParseError];
if (!json) {
handler(nil , jsonParseError);
}
else
{
handler (json , nil);
}
}
}
ASKevrServiceManager.m
-(void)login:(Login *)login completionHandler:(ServiceCompletionHandler)handler
{
NSString *loginUrl = [NSString
stringWithFormat:#"http://249development.us/johnsan/askever/login.php?
login=%#&password=%#",login.emailAddr , login.password];
[self initGetAppServiceRequestWithUrl:loginUrl onCompletion:^(id object, NSError
*error)
{
handler(object , error);
}
];
}
ASKevrOperationManager.m
+(void)login:(Login *)login handler:(OperationHandler)handler
{
ASKevrServiceManager *serviceManager = [[ASKevrServiceManager alloc]init];
[serviceManager login:login completionHandler:^(id object, NSError *error)
{
[JSONResponseHandler handleResponseData:object onCompletion:^(NSDictionary
*json , NSError *jsonError)
{
if(json)
{
handler(json , nil , YES);
}
else
{
handler(nil , jsonError , NO);
}
}];
}];
}
LoginViewController.m
-(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
if ([identifier isEqualToString:#"pushTab"])
{
if ([emailTxt.text isEqualToString:#""] || [passwordTxt.text
isEqualToString:#""])
{
[self showAlertWithMessage:#"Please write your id or password"];
return NO;
}
else
{
Login *loginModel = [[Login alloc]init];
loginModel.emailAddr =emailTxt.text;
loginModel.password = passwordTxt.text;
[ASKevrOperationManager login:loginModel handler:^(id object , NSError *error ,
BOOL success)
{
if (success)
{
NSLog(#"object =%#",object);
NSDictionary *arr = [object objectForKey:#"response"];
str = [arr objectForKey:#"flag"];
//check for error
NSDictionary *toDict = [object objectForKey:#"response"];
currentUserId = [toDict objectForKey:#"c_id"];
NSLog(#"currentUserId = %#",currentUserId);
}
else
{
[self showAlertWithMessage:#"Wrong Id or Password."];
}
}];
NSLog(#"str = %#",str);
if ([str isEqualToString:#"1"])
{
// [self showAlertWithMessage:#"Wrong Id or Password."];
return YES;
}
}
}
return NO;
}
When pressing login button do run the code
if (![emailTxt.text isEqualToString:#""] &&
![passwordTxt.text isEqualToString:#""]){
Login *loginModel = [[Login alloc]init];
loginModel.emailAddr =emailTxt.text;
loginModel.password = passwordTxt.text;
[ASKevrOperationManager login:loginModel handler:^(id object , NSError *error ,
BOOL success)
{
if (success){
NSLog(#"object =%#",object);
NSDictionary *arr = [object objectForKey:#"response"];
str = [arr objectForKey:#"flag"];
//check for error
NSDictionary *toDict = [object objectForKey:#"response"];
currentUserId = [toDict objectForKey:#"c_id"];
NSLog(#"currentUserId = %#",currentUserId);
//perform the segue only when succesful
[self performSegueWithIdentifier:#"yourSegue" sender:sender];
}else{
[self showAlertWithMessage:#"Wrong Id or Password."];
}
}];
}else {
[self showAlertWithMessage:#"Please write your id or password"];
}
Keep your shouldPerformSegueWithIdentifier simple
-(BOOL)shouldPerformSegueWithIdentifier:(NSString *)identifier sender:(id)sender
{
if ([identifier isEqualToString:#"pushTab"])
{
//don't put logic here
//put code here only if you need to pass data
//to the next screen
return YES:
}
return NO;
}

Resources