I have a problem in my app.
I'm using ASIHttpRequest to download a pdf file with this code:
- (void) downloadPdf{
AppDelegate *appDelegate = (AppDelegate*) [UIApplication sharedApplication].delegate;
if (currentDownload) {
[currentDownload clearDelegatesAndCancel];
currentDownload = nil;
totalWorker = 0;
[workers release]; workers = nil;
progressView.progress = 0.0;
} else {
[self removeFile];
appDelegate.alertGlobal = [[UIAlertView alloc] initWithTitle: #"Download file..."
message: #""
delegate: self
cancelButtonTitle: #"Annul"
otherButtonTitles: nil];
progressView = [[UIProgressView alloc] initWithFrame:
CGRectMake(30.0f, 43.0f, 225.0f, 10.0f)];
[appDelegate.alertGlobal addSubview:progressView];
[progressView setProgressViewStyle: UIProgressViewStyleBar];
[appDelegate.alertGlobal show];
NSString *tmp = #"http://192.168.0.13:8888/file.pdf";
currentDownload = [[HappyDownload alloc] initWithURL:[NSURL URLWithString:tmp]];
currentDownload.numberOfWorkers = totalWorker;
currentDownload.totalChunk = 1;
currentDownload.delegate = self;
currentDownload.downloadProgressDelegate = self;
currentDownload.allowResumeForFileDownloads = YES;
documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:#"Documents"];
[currentDownload setDownloadDestinationPath:[documentsDirectory stringByAppendingPathComponent:#"file.pdf"]];
[workers removeAllObjects];
[currentDownload startAsynchronous];
start = [NSDate new];
}
}
- (void) removeFile{
NSString *pathTemp = [NSHomeDirectory()stringByAppendingPathComponent:#"Documents"];
//NSString *path = [pathTemp stringByAppendingPathComponent:#"file.pdf"];
NSFileManager* fm = [[[NSFileManager alloc] init] autorelease];
NSDirectoryEnumerator* en = [fm enumeratorAtPath:pathTemp];
NSError* err = nil;
BOOL res;
NSString* file;
while (file = [en nextObject]) {
res = [fm removeItemAtPath:[pathTemp stringByAppendingPathComponent:file] error:&err];
if (!res && err) {
NSLog(#"error: %#", err);
}
}
}
-(void)requestFinished:(ASIHTTPRequest *)request{
NSDateComponents *comps = [[NSCalendar currentCalendar] components:NSSecondCalendarUnit
fromDate:start
toDate:[[NSDate new] autorelease]
options:0];
int duration = [comps second];
NSLog(#"request finished, duration:%d", duration);
AppDelegate *appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
appDelegate.downloaded = TRUE;
[currentDownload clearDelegatesAndCancel];
currentDownload = nil;
totalWorker = 0;
[workers release]; workers = nil;
progressView.progress = 0.0;
[appDelegate.alertGlobal dismissWithClickedButtonIndex:0 animated:YES];
[appDelegate.alertGlobal release];
downloadedFirstTime = TRUE;
NSError *error;
NSString *pathTemp = [NSHomeDirectory()stringByAppendingPathComponent:#"Documents"];
NSFileManager *fileManager = [NSFileManager defaultManager];
NSLog(#"Documents directory: %#", [fileManager contentsOfDirectoryAtPath:pathTemp error:&error]);
[self openFile];
}
- (void) requestFailed:(ASIHTTPRequest *)request{
AppDelegate *appDelegate = (AppDelegate*) [UIApplication sharedApplication].delegate;
[currentDownload clearDelegatesAndCancel];
currentDownload = nil;
totalWorker = 0;
[workers release]; workers = nil;
progressView.progress = 0.0;
[appDelegate.alertGlobal dismissWithClickedButtonIndex:0 animated:YES];
[appDelegate.alertGlobal release];
NSLog(#"request failed");
NSLog(#"Error %#", [request error]);
int statusCode = [request responseStatusCode];
NSString *statusMessage = [request responseStatusMessage];
NSLog(#"statuscode:%d", statusCode);
NSLog(#"statusmessage:%#", statusMessage);
}
OK in this way I download correctly a pdf file and I open it in this way with this control:
https://github.com/vfr/Reader
the classic controller to open pdf file in iPhone and I use this method:
- (void) openFile{
AppDelegate *appDelegate = (AppDelegate*)[UIApplication sharedApplication].delegate;
NSString *phrase = nil; // Document password (for unlocking most encrypted PDF files)
NSString *pathTemp = [NSHomeDirectory()stringByAppendingPathComponent:#"Documents"];
NSString *path = [pathTemp stringByAppendingPathComponent:#"file.pdf"];
assert(path != nil); // Path to last PDF file
ReaderDocument *document = [ReaderDocument withDocumentFilePath:path password:phrase];
if (document != nil) // Must have a valid ReaderDocument object in order to proceed
{
readerViewController = [[ReaderViewController alloc] initWithReaderDocument:document];
readerViewController.delegate = self; // Set the ReaderViewController delegate to self
//mainWindow.rootViewController = readerViewController; // Set the root view controller
}
[self presentModalViewController:readerViewController animated:YES];
[readerViewController release];
}
It work fine the FIRTS TIME and I open a first file pdf without problems, but when I download a second different pdf that I upload on the server, I have a big problem...inside it I see two pdf file, one above the other, but I don't understand if the problem is the ASIHttpRequest or the readerViewController. As you can see I remove file inside HomeDirectory but I don't understand the problem, can you help me?
thanks
At your remove method, have you checked the path(with file name) is correct? Also, try one more thing the place where you delete your file,after that check for existence of that file.
May be it give some idea.
Related
I am trying this code to achieve online streaming/buffering with the help of amazing audio engine, but it throws me following error:
AEAudioFilePlayer.m:148: AudioFileOpenURL: 'wht?' (2003334207)
Here is the code:
- (void)viewDidLoad {
[super viewDidLoad];
self.audioController = [[AEAudioController alloc] initWithAudioDescription:[AEAudioController nonInterleaved16BitStereoAudioDescription] inputEnabled:YES];
_audioController.preferredBufferDuration = 0.005;
[_audioController start:NULL];
[self initWithAudioController:self.audioController];
AEAudioFilePlayer *oneshot = [AEAudioFilePlayer audioFilePlayerWithURL:[NSURL URLWithString:self.urlOfSong] error:NULL];
_oneshot.removeUponFinish = YES;
[_audioController addChannels:[NSArray arrayWithObject:oneshot]];
}
- (id)initWithAudioController:(AEAudioController*)audioController {
self.audioController = audioController;
NSError *error = NULL;
BOOL result = [self.audioController start:&error];
if ( !result ) {
// Report error
NSLog(#"The Amazing Audio Engine didn't start!");
} else {
NSLog(#"The Amazing Audio Engine started perfectly!");
}
return self;
}
in .h file
#property (nonatomic, strong) AEAudioFilePlayer *player;
#property (nonatomic, strong) AEAudioController *audioController;
in .m file
-(void)playAudio
{
self.audioController = [[AEAudioController alloc] initWithAudioDescription:[AEAudioController nonInterleaved16BitStereoAudioDescription] inputEnabled:YES];
_audioController.preferredBufferDuration = 0.005;
[_audioController start:NULL];
[self initWithAudioController:self.audioController];
if ( _player ) {
[_audioController removeChannels:#[_player]];
self.player = nil;
} else {
NSArray *documentsFolders = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [documentsFolders[0] stringByAppendingPathComponent:kFileName];
if ( ![[NSFileManager defaultManager] fileExistsAtPath:path] ) return;
NSError *error = nil;
self.player = [AEAudioFilePlayer audioFilePlayerWithURL:[NSURL fileURLWithPath:path] error:&error];
if ( !_player ) {
[[[UIAlertView alloc] initWithTitle:#"Error"
message:[NSString stringWithFormat:#"Couldn't start playback: %#", [error localizedDescription]]
delegate:nil
cancelButtonTitle:nil
otherButtonTitles:#"OK", nil] show];
return;
}
[self startTimer];
_player.removeUponFinish = YES;
_player.completionBlock = ^{
_audioController = nil;
[ _audioController removeChannels:#[_player]];
[self remveTimer];
self.player = nil;
};
[_audioController addChannels:#[_player]];
}
}
- (id)initWithAudioController:(AEAudioController*)audioController {
self.audioController = audioController;
NSError *error = NULL;
BOOL result = [self.audioController start:&error];
if ( !result ) {
// Report error
NSLog(#"The Amazing Audio Engine didn't start!");
} else {
NSLog(#"The Amazing Audio Engine started perfectly!");
}
return self;
}
Here is a function of progressbar. In the sdk v1 I can use "S3Objectsummary" to know the summary of the the file, but in the sdk v2 i can not found the "S3Objectsummary".
Which one is the similar one in the v2? If any one can show an example that will be great.
Also, i have the same question with
S3GetObjectRequest/S3GetObjectResponse/S3PutObjectRequest/AmazonClientException
Code is in the sdk ios v1:
-(AmazonS3Client *)s3{
[self validateCredentials];
return s3;}
-(void)validateCredentials{
NSLog(#"validating credentials.");
if (s3 == nil) {
[self clearCredentials];
s3 = [[AmazonS3Client alloc] initWithAccessKey:ACCESS_KEY_ID withSecretKey:SECRET_KEY];
}
}
-(void)setProgressBar{
[delegate setProgressStatus:progPercent];
}
-(void)downloadPlists{
#try {
NSArray *Plists = [[self s3] listObjectsInBucket:#"~~~~"];
float numfile = 1;
float totalfiles = [Plists count];
for (S3ObjectSummary *file in Plists) {
float percent = numfile/totalfiles;
progPercent = [NSNumber numberWithFloat:percent];
[self performSelectorOnMainThread:#selector(setProgressBar) withObject:progPercent waitUntilDone:YES];
numfile++;
NSString *key = [file key];
NSLog(#"key: %#", key);
if ([key rangeOfString:#".plist"].location != NSNotFound) {
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistFilePath = [NSString stringWithFormat:#"%#/Plists/%#",docDir, key];
NSLog(#"plistFilePath: %#", plistFilePath);
S3GetObjectRequest *plist = [[S3GetObjectRequest alloc] initWithKey:key withBucket:#"~~~~~"];
S3GetObjectResponse *getObjectResponse = [[self s3] getObject:plist];
NSData *data2 = [NSData dataWithData: getObjectResponse.body];
NSString *courseFilePath = [plistFilePath substringToIndex:[plistFilePath rangeOfString:#"/" options:NSBackwardsSearch].location];
bool testDirectoryCreated = [[NSFileManager defaultManager]createDirectoryAtPath: courseFilePath
withIntermediateDirectories: YES
attributes: nil
error: NULL];
if (!testDirectoryCreated)
NSLog(#"error creating test directory.");
if (![data2 writeToFile:plistFilePath atomically:YES])
NSLog(#"error writing to path.");
}
}
}
#catch (NSException *exception) {
UIAlertView *failureAlert = [[UIAlertView alloc] initWithTitle:#"Oops!" message:[NSString stringWithFormat: #"There was an error performing this operation. Please try again later. Error: %#", exception] delegate:nil cancelButtonTitle:#"Okay" otherButtonTitles: nil];
[failureAlert show];
}
}
I try to do the same thing in v2 in the code as follow, is the code right?
-(void)downloadPlists
{
AWSS3 *s3 = [AWSS3 defaultS3];
AWSS3ListObjectsRequest *listObjectReq=[AWSS3ListObjectsRequest new];
listObjectReq.bucket=#"PLists";
[[[s3 listObjects:listObjectReq] continueWithBlock:^id(BFTask *task) {
if(task.error){
NSLog(#"the request failed. error %#",task.error);
}
if(task.result){
AWSS3ListObjectsOutput *listObjectsOutput=task.result;
NSArray *Plists = task.result; //Is the result of task in listObjectOutput a NSArray?
float numfile = 1;
float totalfiles = [Plists count];
for(AWSS3Object *file in listObjectsOutput.contents){
float percent = numfile/totalfiles;
progPercent = [NSNumber numberWithFloat:percent];
[self performSelectorOnMainThread:#selector(setProgressBar) withObject:progPercent waitUntilDone:YES];
numfile++;
NSString *key = [file key];
NSLog(#"key: %#", key);
if ([key rangeOfString:#".plist"].location != NSNotFound) {
NSString *docDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
NSString *plistFilePath = [NSString stringWithFormat:#"%#/Plists/%#",docDir, key];
NSLog(#"plistFilePath: %#", plistFilePath);
AWSS3TransferManager *transferManager = [AWSS3TransferManager defaultS3TransferManager];
AWSS3TransferManagerDownloadRequest *downloadRequest = [AWSS3TransferManagerDownloadRequest new];
downloadRequest.bucket = #"PLists";
downloadRequest.key = key;
//downloadRequest.downloadingFileURL=[NSURL fileURLWithPath: #"???"]; I'm not sure the path. In sdk V1 there is no URL ?
[[transferManager download: downloadRequest] continueWithBlock:^id(BFTask *task) {
if (task.error) {
UIAlertView *failureAlert = [[UIAlertView alloc] initWithTitle:#"Oops!"
message:[NSString stringWithFormat: #"There was an error performing this operation. Please try again later. Error: %#", task.error]
delegate:nil
cancelButtonTitle:#"Okay"
otherButtonTitles: nil];
[failureAlert show];
}
if (task.result) {
AWSS3TransferManagerDownloadOutput *downloadOutput = task.result;
NSData *data2 = [NSData dataWithData: downloadOutput.body];
NSString *courseFilePath = [plistFilePath substringToIndex:[plistFilePath rangeOfString:#"/" options:NSBackwardsSearch].location];
bool testDirectoryCreated = [[NSFileManager defaultManager]createDirectoryAtPath: courseFilePath
withIntermediateDirectories: YES
attributes: nil
error: NULL];
if (!testDirectoryCreated)
NSLog(#"error creating test directory.");
if (![data2 writeToFile:plistFilePath atomically:YES])
NSLog(#"error writing to path.");
}
return nil;
}];
}
}
return nil;
}
return nil;
}] waitUntilFinished]; //In the integration test still use the "waitUntilFinisher".But in the "Working with BFTask" said the continueWithBolck won't execute until the previous asychronous call has already finished exceuting?
}
AWSS3Object in v2 is equivalent to S3ObjectSummary in v1.
You are not invoking - listObjects:, so your v2 code snippet does not work. You should take a look at the integration test as an example. Note that you should avoid calling - waitUntilFinished in your production app. See Working with BFTask for further details.
I am using iCloud for sqlite database sync between multiple devices.
i have implemented this functionality in my app for sqlite sync.
But data is updating after 5 mins on other devices.
is this problem from iCloud side because as far as i know we cannot manually update iCloud.
i know it is not correct to use sqlite for icloud sync but i have more 100 tables and i cannot migrate to core data.
Please find my code below:
AppDelegate.m
[self checkForiCloudAccess];
[[sqlmessenger shared] fireQueryForCloudData];
Check for iCloud Access
-(void)checkForiCloudAccess{
NSURL *ubiq = [[NSFileManager defaultManager] URLForUbiquityContainerIdentifier:nil];
if (ubiq) {
NSLog(#"iCloud access at %#", ubiq);
isCloudAccees= TRUE;
}
else {
isCloudAccees= FALSE;
UIAlertView *alertb = [[UIAlertView alloc] initWithTitle:#"Error" message:#"No iCloud acces" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:nil];
[alertb show];
}
}
sqlmessenger.m
Fire Query to get iCloud Data
- (void)fireQueryForCloudData{
NSMetadataQuery *query = [[NSMetadataQuery alloc] init];
[query setSearchScopes:[NSArray arrayWithObject:NSMetadataQueryUbiquitousDocumentsScope]];
NSPredicate *pred = [NSPredicate predicateWithFormat:#"%K ENDSWITH '.xml'", NSMetadataItemFSNameKey];
[query setPredicate:pred];
[[NSNotificationCenter defaultCenter] addObserver:self selector:#selector(queryDidFinishGathering:) name:NSMetadataQueryDidFinishGatheringNotification object:query];
[query startQuery];
}
- (void)queryDidFinishGathering:(NSNotification *)notification {
NSMetadataQuery *que = [[NSMetadataQuery alloc]init];
que = [notification object];
[que disableUpdates];
[que stopQuery];
[[NSNotificationCenter defaultCenter] removeObserver:self
name:NSMetadataQueryDidFinishGatheringNotification
object:que];
self.metaQuery = que;
que = nil;
UIAlertView *alrView = [[UIAlertView alloc]initWithTitle:#"" message:#"Cloud updated" delegate:Nil cancelButtonTitle:#"OK" otherButtonTitles:Nil, nil];
[alrView show];
//TODO: Comment this stupid method
//[self fetcLargeTableFromCloud];
}
Update database using Metadata query object
- (void)loadData:(NSString *)tableName {
_TblName = tableName;
for (NSMetadataItem *item in [self.metaQuery results])
{
NSString *filename = [item valueForAttribute:NSMetadataItemDisplayNameKey];
if([filename isEqualToString:tableName])
{
NSURL *url = [item valueForAttribute:NSMetadataItemURLKey];
//Conflict resolve
//[fileVersion replaceItemAtURL:url options:0 error:nil];
NSData *file = [NSData dataWithContentsOfURL:url];
[NSFileVersion removeOtherVersionsOfItemAtURL:url error:nil];
NSArray *conflicts = [NSFileVersion unresolvedConflictVersionsOfItemAtURL:url];
for (NSFileVersion *conflict in conflicts)
{
conflict.resolved = YES;
NSLog(#"conflict %#",conflict);
}
if (file) {
_arrCloudData = [[NSMutableArray alloc]init];
_tmpDict = [[NSMutableDictionary alloc]init];
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:file];
[parser setDelegate:self];
[parser parse];
if (_arrCloudData.count !=0) {
[self deleteTable:tableName];
_arrColumnList = [self getColumnsForTable:tableName];
//[_arrColumnList removeObjectAtIndex:3];
// [_arrColumnList removeObjectAtIndex:5];
// [_arrColumnList removeObjectAtIndex:8];
NSString *columnNames = [_arrColumnList componentsJoinedByString:#","];
/*
NSMutableArray *arrtmp = [NSMutableArray arrayWithArray:_arrColumnList];
for (int i = 0; i<[arrtmp count]; i++) {
[arrtmp replaceObjectAtIndex:i withObject:#"?"];
}*/
// NSString *blidString = [arrtmp componentsJoinedByString:#","];
//TODO: Uncomment this lines
//NSString *query = [NSString stringWithFormat:#"Insert into %# (%#) values (%#)",tableName,columnNames,blidString];
//TODO: comment this line
NSString *query = [NSString stringWithFormat:#"Insert into %# (%#) values",tableName,columnNames];
// NSDate *parseFinish = [NSDate date];
//[self insertRowIntblMealDetails:tableName :query];
int exCount = _arrCloudData.count/500;
for (int i=0; i<=exCount; i++) {
if ([tableName isEqualToString:#"tblRecipeSubtypes"]) {
[self insertRowIntblMealDetails:tableName :query:i];
}
else{
[self insertRowIntbl:tableName :query :i];
}
}
/*
for (int i=0; i<[_arrCloudData count]; i++) {
//Genralized method
//[self insertRowInTableName:tableName:i:query];
//
//[self insertRowIntblMealDetails:tableName :i :query];
[self insertRowIntblMealDetails:tableName :query];
}*/
sqlite3_close(database);
/*
NSDate *Complete = [NSDate date];
NSTimeInterval PraseComplete = [parseFinish timeIntervalSinceDate:start];
NSTimeInterval LoopTime = [Complete timeIntervalSinceDate:parseFinish];
NSTimeInterval totalTime = [Complete timeIntervalSinceDate:start];
NSLog(#"Parse Execution Time: %f", PraseComplete);
NSLog(#"Loop Execution Time: %f", LoopTime);
NSLog(#"Total Execution Time: %# %f ",tableName, totalTime);
*/
}
else{
NSLog(#"Empty Array %#",tableName);
}
}
else{
NSLog(#"Blank File %#",tableName);
}
}
}
}
i call loaddata from respective classes to update database.
is there anyway with that i can update data early/fast or is there any problem in my code?
Thanks in Advance
For an app I'm working on I need the users to be able to login to Facebook using the native SDK, but there is also a separate part of the app using an FB comments widget in a webview. The problem is after the user logs in using native SDK they are not logged in within the webview comments widget. Is there a way to have the user login using the native iOS SDK and then also log them into Facebook in a UIWebView. I tried using openAccessTokenFromData:completionHandler: in the FBSession class after the user signed in but couldn't get that to work, like below
- (void)didLogin
{
FBAccessTokenData *data = [FBAccessTokenData createTokenFromString:[FBSession activeSession].accessTokenData.accessToken
permissions:[FBSession activeSession].accessTokenData.permissions
expirationDate:[FBSession activeSession].accessTokenData.expirationDate
loginType:FBSessionLoginTypeWebView
refreshDate:nil];
[[FBSession activeSession] closeAndClearTokenInformation];
FBSession *session = [[FBSession alloc] init];
[session openFromAccessTokenData:data
completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
}];
}
I used following code to open Facebook iOs SDK login in Webview in my native app and its works fine for me.
-(void)openFacebookAuthentication
{
NSArray *permission = [NSArray arrayWithObjects:kFBEmailPermission,kFBUserPhotosPermission, nil];
FBSession *session = [[FBSession alloc] initWithPermissions:permission];
[FBSession setActiveSession: [[FBSession alloc] initWithPermissions:permission] ];
[[FBSession activeSession] openWithBehavior:FBSessionLoginBehaviorForcingWebView completionHandler:^(FBSession *session, FBSessionState status, NSError *error) {
switch (status) {
case FBSessionStateOpen:
[self getMyData];
break;
case FBSessionStateClosedLoginFailed: {
// prefer to keep decls near to their use
// unpack the error code and reason in order to compute cancel bool
NSString *errorCode = [[error userInfo] objectForKey:FBErrorLoginFailedOriginalErrorCode];
NSString *errorReason = [[error userInfo] objectForKey:FBErrorLoginFailedReason];
BOOL userDidCancel = !errorCode && (!errorReason || [errorReason isEqualToString:FBErrorLoginFailedReasonInlineCancelledValue]);
if(error.code == 2 && ![errorReason isEqualToString:#"com.facebook.sdk:UserLoginCancelled"]) {
UIAlertView *errorMessage = [[UIAlertView alloc] initWithTitle:kFBAlertTitle
message:kFBAuthenticationErrorMessage
delegate:nil
cancelButtonTitle:kOk
otherButtonTitles:nil];
[errorMessage performSelectorOnMainThread:#selector(show) withObject:nil waitUntilDone:YES];
errorMessage = nil;
}
}
break;
// presently extension, log-out and invalidation are being implemented in the Facebook class
default:
break; // so we do nothing in response to those state transitions
}
}];
permission = nil;
}
Create facebook Appid Facebook Appid creating link Creating time follow facebook guide lines you must give bundile identfier in register time
Then Use this Code
#interface LoginViewController : UIViewController<UIWebViewDelegate>
#property(nonatomic,retain)UIWebView *webview;
#property (nonatomic, retain) NSString *accessToken;
#property(nonatomic,retain)UIActivityIndicatorView *FbActive;
#end
#interface LoginViewController ()
#end
#implementation LoginViewController
#synthesize accessToken,webview,FbActive;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view.
//Removeing the UIWebview Cookies
NSHTTPCookie *cookie;
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [storage cookies]) {
[storage deleteCookie:cookie];
}
[[NSUserDefaults standardUserDefaults] synchronize];
}
-(IBAction)fbLoginPage:(UIButton *)sender1
{
NSString *facebookClientID =facebookAppId;
NSString *redirectUri = #"http://www.facebook.com/connect/login_success.html";
NSString *extended_permissions=#"user_photos,user_videos,publish_stream,offline_access,user_checkins,friends_checkins,email";
NSString *url_string = [NSString stringWithFormat:#"https://graph.facebook.com/oauth/authorize?client_id=%#&redirect_uri=%#&scope=%#&type=user_agent&display=touch", facebookClientID, redirectUri, extended_permissions];
NSURL *url = [NSURL URLWithString:url_string];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
CGRect webFrame =[self.view frame];
webFrame.origin.y = 0;
UIWebView *aWebView = [[UIWebView alloc] initWithFrame:webFrame];
[aWebView setDelegate:self];
self.webview = aWebView;
self.FbActive = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
self.FbActive.color=[UIColor darkGrayColor];
self.FbActive.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2);
[self.FbActive startAnimating];
[webview loadRequest:request];
[self.webview addSubview:self.FbActive];
[self.view addSubview:webview];
}
- (void)webViewDidFinishLoad:(UIWebView *)_webView {
/**
* Since there's some server side redirecting involved, this method/function will be called several times
* we're only interested when we see a url like: http://www.facebook.com/connect/login_success.html#access_token=..........
*/
//get the url string
[self.FbActive stopAnimating];
NSString *url_string = [((_webView.request).URL) absoluteString];
//looking for "access_token="
NSRange access_token_range = [url_string rangeOfString:#"access_token="];
//looking for "error_reason=user_denied"
NSRange cancel_range = [url_string rangeOfString:#"error_reason=user_denied"];
//it exists? coolio, we have a token, now let's parse it out....
if (access_token_range.length > 0) {
//we want everything after the 'access_token=' thus the position where it starts + it's length
int from_index = access_token_range.location + access_token_range.length;
NSString *access_token = [url_string substringFromIndex:from_index];
//finally we have to url decode the access token
access_token = [access_token stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
//remove everything '&' (inclusive) onward...
NSRange period_range = [access_token rangeOfString:#"&"];
//move beyond the .
access_token = [access_token substringToIndex:period_range.location];
//store our request token....
self.accessToken = access_token;
//remove our window
// UIWindow* window = [UIApplication sharedApplication].keyWindow;
// if (!window) {
// window = [[UIApplication sharedApplication].windows objectAtIndex:0];
// }
[self.webview removeFromSuperview];
self.webview=nil;
//tell our callback function that we're done logging in :)
// if ( (callbackObject != nil) && (callbackSelector != nil) ) {
// [callbackObject performSelector:callbackSelector];
// }
//the user pressed cancel
}
else if (cancel_range.length > 0)
{
//remove our window
// UIWindow* window = [UIApplication sharedApplication].keyWindow;
// if (!window) {
// window = [[UIApplication sharedApplication].windows objectAtIndex:0];
// }
[self.webview removeFromSuperview];
self.webview=nil;
//tell our callback function that we're done logging in :)
// if ( (callbackObject != nil) && (callbackSelector != nil) ) {
// [callbackObject performSelector:callbackSelector];
// }
}
[self getuserdetailes];
}
-(void)getuserdetailes
{
NSString *action=#"me";
NSString *url_string = [NSString stringWithFormat:#"https://graph.facebook.com/%#?", action];
//tack on any get vars we have...
NSDictionary *get_vars=nil;
if ( (get_vars != nil) && ([get_vars count] > 0) ) {
NSEnumerator *enumerator = [get_vars keyEnumerator];
NSString *key;
NSString *value;
while ((key = (NSString *)[enumerator nextObject])) {
value = (NSString *)[get_vars objectForKey:key];
url_string = [NSString stringWithFormat:#"%#%#=%#&", url_string, key, value];
}//end while
}//end if
if (accessToken != nil)
{
//now that any variables have been appended, let's attach the access token....
url_string = [NSString stringWithFormat:#"%#access_token=%#", url_string, self.accessToken];
url_string = [url_string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(#"%#",url_string);
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url_string]];
NSError *err;
NSURLResponse *resp;
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:&resp error:&err];
NSString *stringResponse = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSLog(#"%#",stringResponse);
NSError* error;
NSDictionary *FBResResjson = [NSJSONSerialization
JSONObjectWithData:response//1
options:kNilOptions
error:&error];
NSLog(#"%#",FBResResjson);
}
}
thank to Divya Bhalodiya answered. this is the swift 3 version with Facebook SDK 4.x. If the code has any problem, feel free to edit & comment. Hope this will help.
func verifyFromWebView() {
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.loginBehavior = FBSDKLoginBehavior.web
fbLoginManager.logIn(withReadPermissions: ["email"], from: self) { (result, error) in
if error != nil {
print(error!.localizedDescription)
self.dismiss(animated: true, completion: nil)
}else if (result?.isCancelled)!{
print("Cancelled")
self.dismiss(animated: true, completion: nil)
}else{
if let fbLoginResult = result {
if fbLoginResult.grantedPermissions != nil && fbLoginResult.grantedPermissions.contains("email"){
self.getFBData()
}
}
}
}
}
I am not quite sure how to download data from S3 with XCode. Any help on how to do this would be greatly appreciated. I have tried the following code to access an image from S3,
AmazonCredentials *cred = [[Amazon alloc] initWithAccessKey:accessKey withSecretKey:secretAccessKey];
AmazonS3Client *s3 = [[AmazonS3Client alloc] initWithCredentials:cred];
S3GetObjectRequest *s3Request = [[S3GetObjectRequest alloc] initWithKey:urlPath withBucket:bucket];
s3Request.delegate = self;
S3GetObjectResponse *s3Response = [s3 getObject:s3Request];
NSData*data = s3Response.body;
image = [UIImage imageWithData:data];
When I run the program, I get the exception "EXC_BAD_ACCESS (code = 2, address = 0x0)." I am also unsure about what exactly to include in the bucket name. Should the bucket string be just "nameOfBucket"? or something like "topLevelFolder/nameOfBucket"? Also, what specifically should be included in the "urlPath"? I think that my exception probably has to do with incorrect bucket and urlPath names.
EDIT: I found that we weren't getting any data from S3 and the solution was to remove the line that said "s3Request.delegate = self;".
Here are two helper methods for getting image and checking if image exists
#import <AWSiOSSDK/S3/AmazonS3Client.h>
+(NSData *)getImage:(NSString *)imageID inFolder:(NSString *)folderName
{
// Initial the S3 Client.
//folderName = bucket name
AmazonS3Client *s3 = [[AmazonS3Client alloc] initWithAccessKey:ACCESS_KEY_ID withSecretKey:SECRET_KEY];
s3.timeout = 1000;
#try {
NSString *pictName = [NSString stringWithFormat:#"%#%#", imageID, #".jpg"];
S3GetObjectRequest *porr = [[S3GetObjectRequest alloc] initWithKey:pictName withBucket:folderName];
// Get the image data from the specified s3 bucket and object.
S3GetObjectResponse *response = [s3 getObject:porr];
NSData *imageData = response.body;
return imageData;
}
#catch (AmazonClientException *exception) {
return nil;
}
}
+(BOOL)isImageExists:(NSString *)imageID inFolder:(NSString *)folderName
{
#try {
AmazonS3Client *s3 = [[AmazonS3Client alloc] initWithAccessKey:ACCESS_KEY_ID withSecretKey:SECRET_KEY];
NSString *pictName = [NSString stringWithFormat:#"%#%#", imageID, #".jpg"];
NSLog(#"Start checking a full size image %#", imageID);
S3GetObjectMetadataRequest *porr = [[S3GetObjectMetadataRequest alloc] initWithKey:pictName withBucket:folderName];
S3GetObjectResponse *response = [s3 getObjectMetadata:porr];
if(response)
{
return YES;
}
}
#catch (AmazonServiceException *ex) {
NSLog(#"AmazonServiceException in isImageExists %#", ex.description);
return NO;
}
#catch (NSException *exception) {
NSLog(#"NSException in isImageExists %#", exception.description);
return NO;
}
return NO;
}
Assigning a delegate s3Request.delegate = self; causes the AmazonS3Client to send messages to the delegate methods (AmazonServiceRequestDelegate) and preempts messages to S3GetObjectResponse
The two most common delegate methods are:
-(void)request:(AmazonServiceRequest *)request didCompleteWithResponse:(AmazonServiceResponse *)response
-(void)request:(AmazonServiceRequest *)request didFailWithError:(NSError *)error