facebook sharing from iPhone app - objective-c

In my iphone app i am accessing my facebook info and sending it to the server. From server facebook sharing should happen
I have created my app in FB and while clicking sync button i am able to go to the FB login page.After loged in it asks for the authentication
But it just asking for "basic info" not for public sharing etc (i have included that in my FB app)
-(IBAction)fbConnect:(id)sender{
flag = 1;
AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
if (appDelegate.session.isOpen) {
[self updateView];
} else {
if (appDelegate.session.state != FBSessionStateCreated) {
appDelegate.session = [[FBSession alloc] init];
}
[appDelegate.session openWithCompletionHandler:^(FBSession *session,
FBSessionState status,
NSError *error) {
[self updateView];
}];
}
NSLog(#"string issss %#",string);
}
- (void)updateView {
AppDelegate *appDelegate = [[UIApplication sharedApplication]delegate];
if (appDelegate.session.isOpen) {
string = [NSString stringWithFormat:#"%#",
appDelegate.session.accessToken];
NSLog(#"string issss %#",string);
NSString *urlstrng;
if(flag == 1){
urlstrng = [NSString stringWithFormat:#"https://graph.facebook.com/me?access_token=%#",string];
[self dataFetching:urlstrng];
}
if(flag == 2){
urlstrng = [NSString stringWithFormat:#"https://graph.facebook.com/me/friends? access_token=%#",string];
[self dataFetching:urlstrng];
}
} else {
string = [NSString stringWithFormat:#"%#",
appDelegate.session.accessToken];
NSString *urlstrng;
if(flag == 1){
urlstrng = [NSString stringWithFormat:#"https://graph.facebook.com/me?access_token=%#",string];
[self dataFetching:urlstrng];
}
if(flag == 2){
urlstrng = [NSString stringWithFormat:#"https://graph.facebook.com/me/friends?access_token=%#",string];
[self dataFetching:urlstrng];
}
}
}
-(void)dataFetching:(NSString*)strng1{
NSURL *url = [NSURL URLWithString:strng1];
ProfileConnector *obj = [[ProfileConnector alloc] init];
obj.delegate1 = self;
[obj parsingJson:url];
}

I believe you are not requesting extra items through your code. You can do it by using openSessionWithAllowLoginUI.
- (BOOL)openSessionWithAllowLoginUI:(BOOL)allowLoginUI {
NSArray *permissions = [[NSArray alloc] initWithObjects:
#"user_location",
#"user_birthday",
#"user_likes",
#"email",
nil];
return [FBSession openActiveSessionWithPermissions:permissions
allowLoginUI:allowLoginUI
completionHandler:^(FBSession *session,
FBSessionState state,
NSError *error) {
[self sessionStateChanged:session
state:state
error:error];
}];
}

Related

FBSDKLoginManager keep Facebook login since get user info

I get user name and email using this (see below).
the problem, are that the login webview close, the call to initWithGraphPath:#"me" was done async, so user can see empty field by the time I get response to this call.
Is there a way to keep the facebook login webview open since the call to initWithGraphPath was completed?
Thanks!
-(void)loginButtonClicked_Facebook{
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login
logInWithReadPermissions: #[#"public_profile", #"email"]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
NSLog(#"Process error");
} else if (result.isCancelled) {
NSLog(#"Cancelled");
} else {
if ([result.grantedPermissions containsObject:#"email"]){
NSLog(#"result is:%#",result);
[self fetchUserInfo];
}
}
}];
}
-(void)fetchUserInfo{
if ([FBSDKAccessToken currentAccessToken]){
NSLog(#"Token is available : %#",[[FBSDKAccessToken currentAccessToken]tokenString]);
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:#{#"fields": #"id, name, email"}]
startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error){
NSString *userName = [result valueForKey:#"name"];
NSString *email = [result valueForKey:#"email"];
self.tfName.text=userName;
self.tfEmail.text=email;
self.tfEmailConfirmation.text=email;
NSLog(#"resultis:%#",result);
}else{
NSLog(#"Error %#",error);
}
}];
}
}
//YOURCONTROLLER.M
#import <FBSDKCoreKit/FBSDKCoreKit.h>
#import <FBSDKLoginKit/FBSDKLoginKit.h>
NSString *getFbid;
NSString *getFbFirstName,*getFBlastName, *getFbemail,*getfbBirthday,*getfbGender,*getFBpHone,*getFBlocation,*getFBcountry;
- (void) loginButton: (FBSDKLoginButton *)loginButton
didCompleteWithResult: (FBSDKLoginManagerLoginResult *)result
error: (NSError *)error{
NSLog(#"facebook login button test");
}
- (void) loginButtonDidLogOut:(FBSDKLoginButton *)loginButton{
NSLog(#"facebook logout button test");
}
-(void)loginButtonClicked
{
NSUserDefaults *defFacebookData = [NSUserDefaults standardUserDefaults];
FBSDKLoginManager *login = [[FBSDKLoginManager alloc] init];
[login
logInWithReadPermissions: #[#"public_profile", #"user_friends", #"email"]
fromViewController:self
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error) {
if (error) {
DLog(#"Process error======%#",error.description);
indicators.hidden=YES;
[indicators stopAnimating];
} else if (result.isCancelled) {
DLog(#"Cancelled");
indicators.hidden=YES;
[indicators stopAnimating];
} else {
if ([FBSDKAccessToken currentAccessToken]) {
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"me" parameters:#{#"fields": #"id, name, link, first_name, last_name, picture.type(large), email, birthday, bio ,location ,friends ,hometown , gender ,friendlists"}]
startWithCompletionHandler:^(
FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error)
{
// NSLog(#"fetched user:%#", result);
// [self fetchingFacebookFriends];
[defFacebookData setObject:[result objectForKey:#"email"] forKey:#"fbEmail"];
[defFacebookData setObject:[result objectForKey:#"id"] forKey:#"fbID"];
//PASS ID
getFbid = [result objectForKey:#"id"];
NSLog(#"getFbid========>%#",getFbid);
//PASS FIRST NAME
getFbFirstName=[result objectForKey:#"first_name"];
NSLog(#"first======>%#",getFbFirstName);
//PASS LAST NAME
getFBlastName=[result objectForKey:#"last_name"];
NSLog(#"first======>%#",getFBlastName);
//PASS EMAIL
getFbemail=[result objectForKey:#"email"];
NSLog(#"first======>%#",getFbemail);
//PASS PHONE
getfbGender=[result objectForKey:#"gender"];
NSLog(#"first======>%#",getfbGender);
[defFacebookData setObject:[result objectForKey:#"name"] forKey:#"fbName"];
// Image
FBSDKGraphRequest *request = [[FBSDKGraphRequest alloc]
initWithGraphPath:[NSString stringWithFormat:#"me/picture?type=large&redirect=false"]
parameters:nil
HTTPMethod:#"GET"];
[request startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection,
id fbImageResult,
NSError *error) {
NSString *strURL = [NSString stringWithFormat:#"%#",[[fbImageResult objectForKey:#"data"] objectForKey:#"url"]];
NSLog(#"strURL=====>%#",strURL);
[defFacebookData setObject:strURL forKey:#"fbImage"];
[defFacebookData synchronize];
NSDictionary *fbdict=[NSDictionary dictionaryWithObjectsAndKeys:getFbid,#"id",getFbFirstName,#"first_name",getFBlastName,#"last_name",getFbemail,#"email",getfbGender,#"gender",strURL,#"fbImage", nil];
NSLog(#"done=========>%#",fbdict);
UIStoryboard*storyboard=[AppDelegate storyBoardType];
NSUserDefaults *defaults =[NSUserDefaults standardUserDefaults];
BOOL fblogin =[defaults boolForKey:#"KeyEditProfile"];
if (fblogin)
{
UIStoryboard*Storyboard=[AppDelegate storyBoardType];
DashboardVC* tabbarController = (DashboardVC*)[Storyboard instantiateViewControllerWithIdentifier:#"DashboardVCId"];
// tabbarController.dictFacebookdict =fbdict;
// tabbarController.strFBlogin =#"fbAllDataValue";
indicators.hidden=YES;
[indicators stopAnimating];
[self.navigationController pushViewController:tabbarController animated:YES];
}
else
{
EditFBVC *cpvc=(EditFBVC*)[storyboard instantiateViewControllerWithIdentifier:#"EditFBVCId"];
NSLog(#"get fb id ===%#",getFbid);
// cpvc.checkBtnclick =#"1";
cpvc.dictFacebookdict =fbdict;
cpvc.strFBlogin =#"fbAllDataValue";
indicators.hidden=YES;
[indicators stopAnimating];
[self.navigationController pushViewController:cpvc animated:YES];
} // [self facebookdataOnServer];
}];
}
else{
//[SVProgressHUD dismiss];
DLog(#"error is %#", error.description);
}
}];
}
}
}];
}

How to parse ShopStyle JSON in Objective-C

I have a snippet of some JSON which contains ShopStyle products here: https://docs.google.com/document/d/1konfjof33sgNngxIgq_sCyKmCcDda-ziXnOfUUxeKas/edit?usp=sharing
How do I go about getting the products' names and ids from the JSON? So far, I have the following code:
NSURL *URL = [NSURL URLWithString:[NSString stringWithFormat:#"http://api.shopstyle.com/api/v2/products?pid=%#&fts=%#&offset=0&limit=50", apiKey, searchkeywords]];
NSLog(#"%#", URL);
[NSURLConnection sendAsynchronousRequest:[[NSURLRequest alloc] initWithURL:URL] queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
if (error) {
//[self.delegate fetchingGroupsFailedWithError:error];
} else {
//[self.delegate receivedGroupsJSON:data];
NSDictionary *rest_data = [NSJSONSerialization JSONObjectWithData:data
options:0
error:NULL];
NSLog(#"rest_data = %#", rest_data);
for (NSDictionary *topComment in[rest_data objectForKey:#"products"]) {
[self processCommentThread:topComment andLevel:0];
}
NSLog(#"GET COMMENTS RETURN:%#", commentsContainer);
[self performSelectorOnMainThread:#selector(doneFormatting) withObject:nil waitUntilDone:YES];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:nil message:[NSString stringWithFormat:#"%#", rest_data] delegate:self cancelButtonTitle:#"Cancel" otherButtonTitles:nil, nil];
[alert show];
}
}];
/*
PSSProductQuery *productQuery = [[PSSProductQuery alloc] init];
productQuery.searchTerm = searchBar.text;
__weak typeof(self) weakSelf = self;
[[PSSClient sharedClient] searchProductsWithQuery:productQuery offset:nil limit:nil success:^(NSUInteger totalCount, NSArray *availableHistogramTypes, NSArray *products) {
weakSelf.products = products;
[resultsTableView reloadData];
NSLog(#"_products = %#", _products);
resultsTableView.hidden = NO;
} failure:^(int *operation, NSError *error) {
}];
*/
}
- (void)processCommentThread:(NSDictionary *)comments andLevel:(int)level {
#autoreleasepool {
NSMutableDictionary *comment = [[NSMutableDictionary alloc] init];
if (!([comments objectForKey:#"name"] == nil)) {
[comment setObject:[comments objectForKey:#"name"] forKey:#"name"];
}
if (!([comments objectForKey:#"id"] == nil)) {
[comment setObject:[comments objectForKey:#"id"] forKey:#"id"];
}
}
}
-(void)doneFormatting{
[myTableView reloadData];
}

Some data not staying in Core Data

I have a project where I'm consuming data from several web services and then storing them in separate entities in Core Data. To be precise there are 4 different entities. 3 of them are storing just fine. The 4th stores in Core Data and I can retrieve it later in other views but if I close the app and open it back up the InventoryImage Entity seems to be empty.
- (void)viewDidLoad {
[super viewDidLoad];
id delegate = [[UIApplication sharedApplication]delegate];
self.managedObjectContext = [delegate managedObjectContext];
_isConnected = TRUE;
[self checkOnlineConnection];
DealerModel *dealer = [[DealerModel alloc]init];
[dealer getDealerNumber];
_dealerNumber = dealer.dealerNumber;
//_dealerNumber = #"000310";
if (_isConnected == TRUE) {
[self downloadInventoryData:_dealerNumber];
[self downloadImages:_dealerNumber];
}
else{
[self loadInventory];
[self loadImages];
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
/* Table Data */
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_modelsArray count];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
InventoryCell *cell = (InventoryCell *)[tableView dequeueReusableCellWithIdentifier:[_inventoryCell reuseIdentifier]];
if (cell == nil) {
[[NSBundle mainBundle] loadNibNamed:#"InventoryCell" owner:self options:nil];
cell = _inventoryCell;
_inventoryCell = nil;
}
InventoryHome *currentHome = [_modelsArray objectAtIndex:indexPath.row];
NSNumber *imageCount = [self loadImagesBySerialNumber:currentHome.serialNumber];
cell.lblModelDescription.text = currentHome.homeDesc;
cell.lblSerialNumber.text = currentHome.serialNumber;
cell.lblImageCount.text = [NSString stringWithFormat:#"Images: %#", imageCount];
return cell;
}
/* End Table Data */
/* Start Downloads */
#pragma mark - Inventory and Image Data
- (void)downloadInventoryData:(NSString *)dealerNumber
{
[self loadInventory];
if (_isConnected == 1 && [_modelsArray count] > 0) {
[self clearModelEntity:#"InventoryHome"];
}
NSString *urlString = [NSString stringWithFormat:#"%#%#", webServiceInventoryListURL, dealerNumber];
NSURL *invURL = [NSURL URLWithString:urlString];
NSData *data = [NSData dataWithContentsOfURL:invURL];
NSLog(#"Inventory Web Service URL: %#", invURL);
// Sticks all of the jSON data inside of a dictionary
_jSON = [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil];
// Creates a dictionary that goes inside the first data object eg. {data:[
_dataDictionary = [_jSON objectForKey:#"data"];
// Check for other dictionaries inside of the dataDictionary
for (NSDictionary *modelDictionary in _dataDictionary) {
InventoryHome *home = [NSEntityDescription insertNewObjectForEntityForName:#"InventoryHome" inManagedObjectContext:[self managedObjectContext]];
NSString *trimmedSerialNumber = [NSString stringWithFormat:#"%#",[NSLocalizedString([modelDictionary objectForKey:#"serialnumber"], nil) stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
home.homeDesc = NSLocalizedString([modelDictionary objectForKey:#"description"], nil);
home.serialNumber = trimmedSerialNumber;
home.brandDesc = NSLocalizedString([modelDictionary objectForKey:#"branddescription"], nil);
home.beds = [NSNumber numberWithInt:[NSLocalizedString([modelDictionary objectForKey:#"numberofbedrooms"], nil) intValue]];
home.baths = [NSNumber numberWithInt:[NSLocalizedString([modelDictionary objectForKey:#"numberofbathrooms"], nil) intValue]];
home.sqFt = [NSNumber numberWithInt:[NSLocalizedString([modelDictionary objectForKey:#"squarefeet"], nil) intValue]];
home.length = [NSNumber numberWithInt:[NSLocalizedString([modelDictionary objectForKey:#"length"], nil) intValue]];
home.width = [NSNumber numberWithInt:[NSLocalizedString([modelDictionary objectForKey:#"width"], nil) intValue]];
}
[self loadInventory];
}
- (void)downloadImages:(NSString *)dealerNumber
{
[self loadImages];
if (_isConnected == 1 && [_imagesArray count] > 0) {
[self clearModelEntity:#"InventoryImage"];
}
NSString *stringImageURL = [NSString stringWithFormat:#"%#%#",inventoryImageURL, dealerNumber];
NSURL *url = [NSURL URLWithString:stringImageURL];
NSData *imageData = [NSData dataWithContentsOfURL:url];
_jSON = [NSJSONSerialization JSONObjectWithData:imageData options:kNilOptions error:nil];
_dataDictionary = [_jSON objectForKey:#"data"];
for (NSDictionary *imageDictionary in _dataDictionary) {
InventoryImage *image = [NSEntityDescription insertNewObjectForEntityForName:#"InventoryImage" inManagedObjectContext:[self managedObjectContext]];
NSString *trimmedSerialNumber = [NSString stringWithFormat:#"%#",[NSLocalizedString([imageDictionary objectForKey:#"serialnumber"], nil) stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]]];
image.assetID = NSLocalizedString([imageDictionary objectForKey:#"aid"], nil);
image.sourceURL = NSLocalizedString([imageDictionary objectForKey:#"imagereference"], nil);
image.serialNumber = trimmedSerialNumber;
image.group = NSLocalizedString([imageDictionary objectForKey:#"imagegroup"], nil);
image.imageTagId = [NSString stringWithFormat:#"%#", [imageDictionary objectForKey:#"searchtagid"]];
image.imagesId = [NSString stringWithFormat:#"%#", [imageDictionary objectForKey:#"imagesid"]];
image.imageCaption = NSLocalizedString([imageDictionary objectForKey:#"imagecaption"], nil);
image.imageSource = NSLocalizedString([imageDictionary objectForKey:#"imagesource"], nil);
image.inventoryPackageID = NSLocalizedString([imageDictionary objectForKey:#"inventorypackageid"], nil);
}
}
/* End Downloads */
/* Load Inventory and Image From Core Data */
- (void)loadInventory
{
_fetchRequest = [[NSFetchRequest alloc]init];
_entity = [NSEntityDescription entityForName:#"InventoryHome" inManagedObjectContext:[self managedObjectContext]];
_sort = [NSSortDescriptor sortDescriptorWithKey:#"homeDesc" ascending:YES];
_sortDescriptors = [[NSArray alloc]initWithObjects:_sort, nil];
[_fetchRequest setSortDescriptors:_sortDescriptors];
[_fetchRequest setEntity:_entity];
NSError *error = nil;
_modelsArray = [[self managedObjectContext] executeFetchRequest:_fetchRequest error:&error];
if (![[self managedObjectContext]save:&error]) {
NSLog(#"An error has occurred: %#", error);
}
[self.inventoryListTable reloadData];
}
- (NSNumber *)loadImagesBySerialNumber: (NSString *)serialNumber
{
_imagesFetchRequest = [[NSFetchRequest alloc]init];
_imagesEntity = [NSEntityDescription entityForName:#"InventoryImage" inManagedObjectContext:[self managedObjectContext]];
_imagesPredicate = [NSPredicate predicateWithFormat:#"serialNumber = %# && group <> 'm-FLP' && imageSource <> 'MDL'", serialNumber];
[_imagesFetchRequest setEntity:_imagesEntity];
[_imagesFetchRequest setPredicate:_imagesPredicate];
NSError *error = nil;
_imagesArray = [[self managedObjectContext] executeFetchRequest:_imagesFetchRequest error:&error];
NSNumber *imageCount = [NSNumber numberWithInteger:[_imagesArray count]];
return imageCount;
}
- (void)loadImages
{
_imagesFetchRequest = [[NSFetchRequest alloc]init];
_imagesEntity = [NSEntityDescription entityForName:#"InventoryImage" inManagedObjectContext:[self managedObjectContext]];
[_imagesFetchRequest setEntity:_imagesEntity];
NSError *error = nil;
_imagesArray = [[self managedObjectContext] executeFetchRequest:_imagesFetchRequest error:&error];
}
/* End Load Inventory and Image From Core Data */
- (void)clearModelEntity:(NSString *)entity
{
_fetchRequest = [[NSFetchRequest alloc]init];
_entity = [NSEntityDescription entityForName:entity inManagedObjectContext:[self managedObjectContext]];
[_fetchRequest setEntity:_entity];
NSError *error = nil;
_modelsArray = [[self managedObjectContext] executeFetchRequest:_fetchRequest error:&error];
for (NSManagedObject *object in _modelsArray) {
[[self managedObjectContext] deleteObject:object];
}
NSError *saveError = nil;
if (![[self managedObjectContext] save:&saveError]) {
NSLog(#"An error has occurred: %#", saveError);
}
}
- (void)clearImageEntity:(NSString *)entity
{
_fetchRequest = [[NSFetchRequest alloc]init];
_entity = [NSEntityDescription entityForName:entity inManagedObjectContext:[self managedObjectContext]];
[_fetchRequest setEntity:_entity];
NSError *error = nil;
_imagesArray = [[self managedObjectContext] executeFetchRequest:_fetchRequest error:&error];
for (NSManagedObject *object in _imagesArray) {
[[self managedObjectContext] deleteObject:object];
}
NSError *saveError = nil;
if (![[self managedObjectContext] save:&saveError]) {
NSLog(#"An error has occurred: %#", saveError);
}
}
Don't forget to call [save:conetext]. if you close without saving you will lost your data.

AVAudioPlayer breaking video capture

In one of the views of my app there's a button. When pressed it is supposed to begin taking a video, trigger a sound file to start, and hide itself from view while unhiding another button. The second button is supposed to stop the video recording and make it save. Here's the code I have for the video recording, which initially worked with no problems:
in viewDidLoad:
finishButton.hidden = TRUE;
session = [[AVCaptureSession alloc] init];
movieFileOutput = [[AVCaptureMovieFileOutput alloc] init];
NSError *error;
AVCaptureDeviceInput *videoInput = [[AVCaptureDeviceInput alloc] initWithDevice:[self cameraWithPosition:AVCaptureDevicePositionFront] error:&error];
if (videoInput)
{
[session addInput:videoInput];
}
AVCaptureDevice *audioCaptureDevice = [AVCaptureDevice defaultDeviceWithMediaType:AVMediaTypeAudio];
NSError *audioError = nil;
AVCaptureDeviceInput *audioInput = [AVCaptureDeviceInput deviceInputWithDevice:audioCaptureDevice error:&audioError];
if (audioInput)
{
[session addInput:audioInput];
}
Float64 TotalSeconds = 35; //Total seconds
int32_t preferredTimeScale = 30; //Frames per second
CMTime maxDuration = CMTimeMakeWithSeconds(TotalSeconds, preferredTimeScale);
movieFileOutput.maxRecordedDuration = maxDuration;
movieFileOutput.minFreeDiskSpaceLimit = 1024 * 1024;
if ([session canAddOutput:movieFileOutput])
[session addOutput:movieFileOutput];
[session setSessionPreset:AVCaptureSessionPresetMedium];
if ([session canSetSessionPreset:AVCaptureSessionPreset640x480]) //Check size based configs are supported before setting them
[session setSessionPreset:AVCaptureSessionPreset640x480];
[self cameraSetOutputProperties];
[session startRunning];
and for the button:
-(IBAction)start:(id)sender
{
startButton.hidden = TRUE;
finishButton.hidden = FALSE;
//Create temporary URL to record to
NSString *outputPath = [[NSString alloc] initWithFormat:#"%#%#", NSTemporaryDirectory(), #"output.mov"];
self.outputURL = [[NSURL alloc] initFileURLWithPath:outputPath];
NSFileManager *fileManager = [NSFileManager defaultManager];
if ([fileManager fileExistsAtPath:outputPath])
{
NSError *error;
if ([fileManager removeItemAtPath:outputPath error:&error] == NO)
{
//Error - handle if required
}
}
//Start recording
[movieFileOutput startRecordingToOutputFileURL:outputURL recordingDelegate:self];
finally, under the last button:
[movieFileOutput stopRecording];
and here's the code to save the video:
- (void)captureOutput:(AVCaptureFileOutput *)captureOutput
didFinishRecordingToOutputFileAtURL:(NSURL *)outputFileURL
fromConnections:(NSArray *)connections
error:(NSError *)error
{
NSLog(#"didFinishRecordingToOutputFileAtURL - enter");
BOOL RecordedSuccessfully = YES;
if ([error code] != noErr)
{
// A problem occurred: Find out if the recording was successful.
id value = [[error userInfo] objectForKey:AVErrorRecordingSuccessfullyFinishedKey];
if (value)
{
RecordedSuccessfully = [value boolValue];
}
}
if (RecordedSuccessfully)
{
//----- RECORDED SUCESSFULLY -----
NSLog(#"didFinishRecordingToOutputFileAtURL - success");
ALAssetsLibrary *library = [[ALAssetsLibrary alloc] init];
if ([library videoAtPathIsCompatibleWithSavedPhotosAlbum:outputURL])
{
[library writeVideoAtPathToSavedPhotosAlbum:outputURL
completionBlock:^(NSURL *assetURL, NSError *error)
{
if (error)
{
}
}];
}
}
}
All of this was working just fine. Then I added a few lines so that a song file would play when the start button was pressed.
in viewDidLoad:
NSURL *url = [NSURL fileURLWithPath:[NSString stringWithFormat:#"%#/Song.aiff", [[NSBundle mainBundle] resourcePath]]];
NSError *audioFileError;
player = [[AVAudioPlayer alloc] initWithContentsOfURL:url error:&audioFileError];
player.numberOfLoops = 0;
[self.player prepareToPlay];
and under the start button:
if (player == nil)
NSLog(#"Audio file could not be played");
else
[player play];
Now when the start button is pressed the song plays with no problems, but the video capture is messed up. Before adding the AVAudioPlayer stuff I would get the "didFinishRecordingToOutputFileAtURL - enter" and "didFinishRecordingToOutputFileAtURL - success" logs when I pressed the finish button, and now I get the first log as soon as I press the start button, nothing happens when I press the finish button, and no video is recorded. If I comment out the lines that make the song play then the video capture works just fine again. Any ideas what's going on here?
- (void)setupAudioSession
{
static BOOL audioSessionSetup = NO;
if (audioSessionSetup)
{
return;
}
[[AVAudioSession sharedInstance] setCategory:AVAudioSessionCategoryPlayback error: nil];
UInt32 doSetProperty = 1;
AudioSessionSetProperty (kAudioSessionProperty_OverrideCategoryMixWithOthers, sizeof(doSetProperty), &doSetProperty);
[[AVAudioSession sharedInstance] setActive: YES error: nil];
audioSessionSetup = YES;
}
- (void)playAudio
{
[self setupAudioSession];
NSString *soundFilePath = [[NSBundle mainBundle] pathForResource:#"btnClick" ofType:#"wav"];
NSURL *fileURL = [[NSURL alloc] initFileURLWithPath:soundFilePath];
AVAudioPlayer *newPlayer = [[AVAudioPlayer alloc] initWithContentsOfURL:fileURL error:nil];
[fileURL release];
self.audioPlayer = newPlayer;
[newPlayer release];
[audioPlayer setDelegate:self];
[audioPlayer prepareToPlay];
audioPlayer.volume=1.0;
[audioPlayer play];
}
NOTE: Add the framework: AudioToolbox.framework.
#import <AudioToolbox/AudioServices.h>

how to return result after OpenWithCompletionHandler: is complete

Want to query a photo in the Coredata database
this is my code
this is the NSObjectSubclass category
//Photo+creak.h
#import "Photo+creat.h"
#implementation Photo (creat)
+(Photo *)creatPhotoByString:(NSString *)photoName inManagedObjectContext:(NSManagedObjectContext *)context{
Photo *picture = nil;
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Photo"];
request.predicate = [NSPredicate predicateWithFormat:#"name = %#", photoName];
NSArray *matches = [context executeFetchRequest:request error:nil];
if (!matches || [matches count]>1) {
//error
} else if ([matches count] == 0) {
picture = [NSEntityDescription insertNewObjectForEntityForName:#"Photo" inManagedObjectContext:context];
picture.name = photoName;
} else {
picture = [matches lastObject];
}
return picture;
}
+ (BOOL)isPhoto:(NSString *)photoName here:(NSManagedObjectContext *)context{
NSFetchRequest *request = [NSFetchRequest fetchRequestWithEntityName:#"Photo"];
request.predicate = [NSPredicate predicateWithFormat:#"name = %#", photoName];
NSArray *matches = [context executeFetchRequest:request error:nil];
switch ([matches count]) {
case 1:
return YES;
break;
default:
return NO;
break;
}
}
#end
code inside of view controller
//View Controller
- (IBAction)insertData:(UIButton *)sender {
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:#"test"];
UIManagedDocument *defaultDocument = [[UIManagedDocument alloc] initWithFileURL:url];
if (![[NSFileManager defaultManager] fileExistsAtPath:[url path]]) {
[defaultDocument saveToURL:defaultDocument.fileURL forSaveOperation:UIDocumentSaveForCreating completionHandler:NULL];
}
[defaultDocument openWithCompletionHandler:^(BOOL success) {
[Photo creatPhotoByString:#"test" inManagedObjectContext:defaultDocument.managedObjectContext];
[defaultDocument saveToURL:defaultDocument.fileURL forSaveOperation:UIDocumentSaveForOverwriting completionHandler:NULL];
}];
[sender setTitle:#"Okay" forState:UIControlStateNormal];
[sender setEnabled:NO];
}
- (IBAction)queryFromDatabase:(UIButton *)sender {
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:#"test"];
UIManagedDocument *defaultDocument = [[UIManagedDocument alloc] initWithFileURL:url];
BOOL isItWorking = [checkPhoto isPhoto:#"test" inManagedDocument:defaultDocument];
if (isItWorking) {
[sender setTitle:#"Okay" forState:UIControlStateNormal];
} else {
[sender setTitle:#"NO" forState:UIControlStateNormal];
}
}
The NSObject Class that hook them up.
// checkPhoto.m
#import "checkPhoto.h"
#implementation checkPhoto
+ (BOOL)isPhoto:(NSString *)photoToCheck inManagedDocument:(UIManagedDocument *)document{
__block BOOL isPhotoHere = NO;
if (document.documentState == UIDocumentStateClosed) {
[document openWithCompletionHandler:^(BOOL success) {
isPhotoHere = [Photo isPhoto:photoToCheck here:document.managedObjectContext];
}];
}
return isPhotoHere;
}
#end
The coredata only have on Entity named "Photo", and it got only one attribute "name".
The problem is that the return always get execute before the block is complete and always return NO.
Test code here
Or should I do something else than openWithCompletionHandler when querying?
You need to rework your method to work asynchronously, like -openWithCompletionHandler:. It needs to take a block which is invoked when the answer is known and which receives the answer, true or false, as a parameter.
Then, the caller should pass in a block that does whatever is supposed to happen after the answer is known.
Or, alternatively, you should delay the whole chunk of logic which cares about the photo being in the database. It should be done after the open has completed.
You'd have to show more code for a more specific suggestion.
So, you could rework the isPhoto... method to something like:
+ (BOOL)checkIfPhoto:(NSString *)photoToCheck isInManagedDocument:(UIManagedDocument *)document handler:(void (^)(BOOL isHere))handler {
if (document.documentState == UIDocumentStateClosed) {
[document openWithCompletionHandler:^(BOOL success) {
handler([Photo isPhoto:photoToCheck here:document.managedObjectContext]);
}];
}
else
handler(NO);
}
Then you can rework this:
- (IBAction)queryFromDatabase:(UIButton *)sender {
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:#"test"];
UIManagedDocument *defaultDocument = [[UIManagedDocument alloc] initWithFileURL:url];
[checkPhoto checkIfPhoto:#"test" isInManagedDocument:defaultDocument handler:^(BOOL isHere){
if (isHere) {
[sender setTitle:#"Okay" forState:UIControlStateNormal];
} else {
[sender setTitle:#"NO" forState:UIControlStateNormal];
}
}];
}
Try that
+(BOOL)isPhoto:(Photo *)photo inDataBase:(UIManagedDocument *)defaultDocument{
__block BOOL isPhotoThere = NO;
dispatch_semaphore_t sema = dispatch_semaphore_create(0);
[defaultDocument openWithCompletionHandler:^(BOOL success) {
[defaultDocument.managedObjectContext performBlock:^{
isPhotoThere = [Photo checkPhoto:photo];
dispatch_semaphore_signal(sema);
}];
}];
dispatch_semaphore_wait(sema, DISPATCH_TIME_FOREVER);
dispatch_release(sema);
return isPhotoThere;
}