Mapping a large JSON with Restkit - iphone

I am using restkit for a time now. And everything worked perfect. But now I want to map a json into my core database. This is a JSON of (10 MB). You can see the JSON over here.
I have an API class where I do my mapping
-(RKObjectManager *)mapGetItems{
RKEntityMapping* rubriekMapping = [RKEntityMapping mappingForEntityForName:#"Items" inManagedObjectStore:managedObjectStore];
rubriekMapping.identificationAttributes = #[#"itemNum"] ;
[rubriekMapping addAttributeMappingsFromDictionary:#{
#"ItemNum": #"itemNum",
#"ItemDescNl": #"itemDescNl",
#"ItemDescFr": #"itemDescFr",
#"Group1": #"group1",
#"Group2": #"group2",
#"Group3": #"group3",
#"Group4": #"group4",
#"DateCr": #"dateCr",
#"GrpItem": #"grpItem",
#"GrpDesc1": #"grpDesc1",
#"GrpDesc2": #"grpDesc2",
#"GrpDesc1Fr": #"grpDesc1Fr",
#"SalUnitNl": #"salUnitNl",
#"SalUnitFr": #"salUnitFr",
#"LadderQty": #"ladderQty",
#"Netprice": #"netPrice",
#"IsPromo": #"isPromo",
#"IsNew": #"isNew",
}];
RKResponseDescriptor *responseDescriptor = [RKResponseDescriptor responseDescriptorWithMapping:rubriekMapping
pathPattern:nil
keyPath:#"ds-ttitems.tt-items" statusCodes:[NSIndexSet indexSetWithIndex:200]];
NSArray *arrResponsDescriptor = [[NSArray alloc]initWithObjects:responseDescriptor, nil];
[objectManager addResponseDescriptorsFromArray:arrResponsDescriptor];
return objectManager;
}
And a dataModel class, in this class I setup my object store.
This is all going well and everything is set up correctly.
Now for my request I do this.
-(void)fetchRubrieken{
API *api = [API new];
RKManagedObjectStore *store = [[ClaesDataModel sharedDataModel] objectStore];
NSManagedObjectContext *context = store.mainQueueManagedObjectContext;
RKObjectManager *objectManager = [api mapGetItems];
NSString *request = #"/claes/items.json";
[objectManager getObjectsAtPath:request parameters:nil
success:^(RKObjectRequestOperation *operation, RKMappingResult *mappingResult) {
NSError *error = nil;
BOOL success = [store.mainQueueManagedObjectContext save:&error];
if (!success) RKLogWarning(#"Failed saving managed object context: %#", error);
NSLog(#"done fetching");
}
failure:^(RKObjectRequestOperation *operation, NSError *error) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error"
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil];
[alert show];
NSLog(#"Hit error: %#", error);
}];
NSError *error = nil;
[context save:&error];
}
The problem is not that it isn't working. It only takes a very very long time. So my question is, how can i make this go faster?
Hope that anybody can help me!
Kind regards,
PS. If you need more details, I will provide but I think this is the essential part.

Related

Loading images from parse to image views

I want to load images from parse as you can see in the screenshot.
i am using this code to load the header image into my imageview.
PFQuery *query = [PFQuery queryWithClassName:#"AppOfTheDay"];
[query getObjectInBackgroundWithId:#"WDJpxs4PzH"
block:^(PFObject *retreive, NSError *error) {
{
NSString *text = [retreive objectForKey:#"description"];
if (error) {
[MBProgressHUD hideHUDForView:self.view animated:YES];
UIAlertView *error=[[UIAlertView alloc]initWithTitle:#"Error" message:#"Connection Failed" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[error show];
}
else{
PFFile *imageFile = [retreive objectForKey:#"header"];
[imageFile getDataInBackgroundWithBlock:^(NSData *data, NSError *error) {
if (error) {
[MBProgressHUD hideHUDForView:self.view animated:YES];
UIAlertView *error=[[UIAlertView alloc]initWithTitle:#"Error" message:#"Something went wrong" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[error show];
}
else{
UIImage *image = [UIImage imageWithData:data];
_headerImage.image=image;
_appDescription.text=text;
[MBProgressHUD hideHUDForView:self.view animated:YES];
}
}];
}
}
}];
My question is how can i similarly load my other three images into imageviews?
implement lazy loading images.
for example-NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];
if ( queue == nil )
{
queue = [[NSOperationQueue alloc] init];
}
[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse * resp, NSData *data, NSError *error)
{
dispatch_async(dispatch_get_main_queue(),^
{
if ( error == nil && data )
{
UIImage *urlImage = [[UIImage alloc] initWithData:data];
thumbnail.image = urlImage;
}
});
}];
I hope it will help you alot,It will sort your problem with best loading speed
//yourclass.h
AsyncImageView *imageasy,*imageasy1, *imageasy2,imageasy3;
yourclass.m
PFQuery *query = [PFQuery queryWithClassName:#"AppOfTheDay"];
[query getObjectInBackgroundWithId:#"WDJpxs4PzH"
block:^(PFObject *comment, NSError *error) {
if (!error) {
PFFile *post = [comment objectForKey:#"PhotoName"];
PFFile *post2 = [comment objectForKey:#"logo"];
PFFile *post3 = [comment objectForKey:#"similar1"];
PFFile *post4 = [comment objectForKey:#"similar2"];
imageasy=[[AsyncImageView alloc] init];
imageasy1=[[AsyncImageView alloc] init];
imageasy2=[[AsyncImageView alloc] init];
imageasy3=[[AsyncImageView alloc] init];
[imageasy setImageURL:[NSURL URLWithString:[post url]]];
[imageasy1 setImageURL:[NSURL URLWithString:[post2 url]]];
[imageasy2 setImageURL:[NSURL URLWithString:[post3 url]]];
[imageasy3 setImageURL:[NSURL URLWithString:[post4 url]]];
}];

Dynamic variable empty on app restart, Core Data relationships lost

I'm having trouble on Core Data, been driving me crazy for over a day now. When I quit my app using Xcode I lose all Core Data relationships. All of the objects are still in the SQL database, but the relationships between them are gone. I looked at this which was the closest thing:
Some CoreData relationships are lost after closing app
I tried using mutableSetValueForKeyPath:
if ([[NSString stringWithFormat:#"%#",[item mutableSetValueForKeyPath:#"clothing_type"]] isEqualToString:#"Top"])
return item;
But I just get:
'NSInvalidArgumentException', reason: 'NSManagedObjects of entity 'ClothingItem' do not support -mutableSetValueForKey: for the property 'clothing_type''
Could someone help with this? The below code is where the main problem is happening. I set up the wardrobe and everything is fine. getTop, getBottom and getShoes work fine between views, etc. Even when the app goes to background and returns it's all fine. But I do the quitting of the app via xcode and when I come back I run the debugger and the wardrobe is there, but when I run getTop, getBottom or getShoes on it it returns nil because #dynamic clothes is nil. Here's the wardrobe file:
#import "Wardrobe.h"
#import "ClothingItem.h"
#implementation Wardrobe
#dynamic clothes;
- (ClothingItem*) getTop
{
for (ClothingItem *item in clothes){
if ([[item valueForKey:#"clothing_type"] isEqualToString:#"Top"])
return item;
}
return nil;
}
- (ClothingItem*) getBottom
{
for (ClothingItem *item in clothes){
if ([[item valueForKey:#"clothing_type"] isEqualToString:#"Bottom"])
return item;
}
return nil;
}
- (ClothingItem*) getShoes
{
for (ClothingItem *item in clothes){
if ([[item valueForKey:#"clothing_type"] isEqualToString:#"Shoes"])
return item;
}
return nil;
}
#end
Here is where I set up the favorite. I was initially saving it as a multidimensional NSMutableArray and storing it in NSUserDefaults but again when I returned it was gone. I guess a multidimensional NSMutableArray is not able to be stored that way. So I decided to go with Core Data which seems to be the most proper thing to do:
- (IBAction)saveCurrentAsFavorite:(id)sender {
AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
NSManagedObject *top = nil;
NSManagedObject *bottom = nil;
NSManagedObject *shoes = nil;
UIAlertView *myAlert;
if (delegate.topClothesList.count > delegate.currentTopNumber){
top = [delegate.topClothesList objectAtIndex:delegate.currentTopNumber];
}
else {
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle: #"No Top!" message: #"Please select a top if you want to add to favorites!" delegate: nil cancelButtonTitle:#"Okie dokie!" otherButtonTitles:nil];
[myAlert show];
return;
}
if (delegate.bottomClothesList.count > delegate.currentBottomNumber){
bottom = [delegate.bottomClothesList objectAtIndex:delegate.currentBottomNumber];
}
else {
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle: #"No Bottom!" message: #"Please select a bottom if you want to add to favorites!" delegate: nil cancelButtonTitle:#"Roger!" otherButtonTitles:nil];
[myAlert show];
return;
}
if (delegate.shoesClothesList.count > delegate.currentShoeNumber){
shoes = [delegate.shoesClothesList objectAtIndex:delegate.currentShoeNumber];
}
else {
//shoes = nil;
UIAlertView *myAlert = [[UIAlertView alloc] initWithTitle: #"No Shoes!" message: #"Please select shoes if you want to add to favorites!" delegate: nil cancelButtonTitle:#"Will do!" otherButtonTitles:nil];
[myAlert show];
return;
}
// The old way of doing it where I saved it all in an NSMutableArray, but it wouldn't save into NSUserDefaults as a multidimensional NSMutableArray…
/* NSMutableArray *wardrobe = [[NSMutableArray alloc] initWithObjects:top, bottom, shoes, nil];
for (int i = 0; i < delegate.favoriteWardrobes.count; i++){
if ([[[delegate.favoriteWardrobes objectAtIndex:i] objectAtIndex:0] isEqual: [wardrobe objectAtIndex:0]] && [[[delegate.favoriteWardrobes objectAtIndex:i] objectAtIndex:1] isEqual: [wardrobe objectAtIndex:1]] && [[[delegate.favoriteWardrobes objectAtIndex:i] objectAtIndex:2] isEqual: [wardrobe objectAtIndex:2]]){
myAlert = [[UIAlertView alloc] initWithTitle: #"Wardrobe Already In Favorites!" message: #"Very nice choice, again! You like this wardrobe, so you should just buy it! Click the images so you could visit their sites and buy them!" delegate: nil cancelButtonTitle:#"Nice!" otherButtonTitles:nil];
[myAlert show];
return;
}
}
[delegate.favoriteWardrobes addObject:wardrobe];
// save information
NSArray *values = [[NSArray alloc] initWithObjects:delegate.selectedTopStyles, delegate.selectedBottomStyles, delegate.selectedShoesStyles, delegate.selectedSexes, delegate.selectedPrices, delegate.favoriteWardrobes, nil];
[values writeToFile:[self saveFilePath] atomically:YES];
//[[NSUserDefaults standardUserDefaults] setObject:delegate.favoriteWardrobes forKey:#"favoriteWardrobes"];
myAlert = [[UIAlertView alloc] initWithTitle: #"Wardrobe Added To Favorites!" message: #"Very nice choice! Awesome style! \n\nReminder: if you select View Favorities you can send this wardrobe to yourself and your friends!" delegate: nil cancelButtonTitle:#"Sweet!" otherButtonTitles:nil];
[myAlert show];
*/
// TRY DOING IT THE CORE DATA WAY
// need to fetch the Wardrobe objects and check their children to see if they match; and if any of these children do not exist within that wardrobe, skip it. If there is a wardrobe that contains all three then say wardrobe is already added
NSEntityDescription *entitydesc = [NSEntityDescription entityForName:#"Wardrobe" inManagedObjectContext:context];
NSFetchRequest *request = [[NSFetchRequest alloc]init];
[request setEntity:entitydesc];
[request setIncludesSubentities:NO];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:request error:&error];
ClothingItem *clothingTop, *clothingBottom, *clothingShoes;
for (Wardrobe *ward in fetchedObjects) {
clothingTop = [ward getTop];
clothingBottom = [ward getBottom];
clothingShoes = [ward getShoes];
if (([[clothingTop valueForKey:#"clothing_id"] isEqual:[top valueForKey:#"clothing_id"]]) && ([[clothingBottom valueForKey:#"clothing_id"] isEqual:[bottom valueForKey:#"clothing_id"]]) && ([[clothingShoes valueForKey:#"clothing_id"] isEqual:[shoes valueForKey:#"clothing_id"]])){
myAlert = [[UIAlertView alloc] initWithTitle: #"Wardrobe Already In Favorites!" message: #"Very nice choice, again! You like this wardrobe, so you should just buy it! Click the images so you could visit their sites and buy them!" delegate: nil cancelButtonTitle:#"Nice!" otherButtonTitles:nil];
[myAlert show];
return;
}
}
// if there's no case like that and this wardrobe is unique then do the following:
// Grab the Wardrobe entity
Wardrobe *newWardrobe = [NSEntityDescription insertNewObjectForEntityForName:#"Wardrobe" inManagedObjectContext:context];
/*ClothingItem* topCloth = (ClothingItem *) top;
ClothingItem* bottomCloth = (ClothingItem *) bottom;
ClothingItem* shoesCloth = (ClothingItem *) shoes;*/
// Instead of doing straight casting because that doesn't seem recommended, do more fetch requests to be extra careful
// We're looking to grab ClothingItems
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"ClothingItem"
inManagedObjectContext:context];
[fetchRequest setEntity:entity];
NSPredicate *predicate = [NSPredicate predicateWithFormat:#"clothing_id == %#", [top valueForKey:#"clothing_id"]];
[fetchRequest setPredicate:predicate];
error = nil;
fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
ClothingItem* topCloth = [fetchedObjects objectAtIndex:0];
predicate = [NSPredicate predicateWithFormat:#"clothing_id == %#", [bottom valueForKey:#"clothing_id"]];
[fetchRequest setPredicate:predicate];
error = nil;
fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
ClothingItem* bottomCloth = [fetchedObjects objectAtIndex:0];
predicate = [NSPredicate predicateWithFormat:#"clothing_id == %#", [shoes valueForKey:#"clothing_id"]];
[fetchRequest setPredicate:predicate];
error = nil;
fetchedObjects = [context executeFetchRequest:fetchRequest error:&error];
ClothingItem* shoesCloth = [fetchedObjects objectAtIndex:0];
// adding wardrobe to the clothes
[topCloth addWardrobeObject:newWardrobe];
[bottomCloth addWardrobeObject:newWardrobe];
[shoesCloth addWardrobeObject:newWardrobe];
// adding clothes to wardrobe
// adding individually just to see if it works this way; the NSSet below was working fine
[newWardrobe addClothesObject:topCloth];
[newWardrobe addClothesObject:bottomCloth];
[newWardrobe addClothesObject:shoesCloth];
//[newWardrobe addClothes:[NSSet setWithObjects:topCloth, bottomCloth, shoesCloth, nil]];
if ([context save:&error]) {
NSLog(#"The save was successful!");
} else {
NSLog(#"The save wasn't successful: %#", [error localizedDescription]);
}
//[delegate saveContext]; // does this help?
//[newWardrobe addClothesObject:[delegate.topClothesList objectAtIndex:delegate.currentTopNumber]];
//[newWardrobe addClothesObject:[delegate.bottomClothesList objectAtIndex:delegate.currentBottomNumber]];
//[newWardrobe addClothesObject:[delegate.shoesClothesList objectAtIndex:delegate.currentShoeNumber]];
// not sure if this is going to work!
//[newWardrobe addClothesObject:(ClothingItem*) top];
//[newWardrobe addClothesObject:(ClothingItem*) bottom];
//[newWardrobe addClothesObject:(ClothingItem*) shoes];
delegate.numFavorites++; // add another favorite
[[NSUserDefaults standardUserDefaults] setInteger:delegate.numFavorites forKey:#"numFavorites"];
myAlert = [[UIAlertView alloc] initWithTitle: #"Wardrobe Added To Favorites!" message: #"Very nice choice! Awesome style! \n\nReminder: if you select View Favorities you can send this wardrobe to yourself and your friends!" delegate: nil cancelButtonTitle:#"Sweet!" otherButtonTitles:nil];
[myAlert show];
}
Here's the code where I'm calling getTop, getBottom, getShoes:
// Construct a fetch request
NSFetchRequest *request = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:#"Wardrobe"
inManagedObjectContext:context];
[request setIncludesSubentities:NO];
[request setEntity:entity];
NSError *error = nil;
NSArray *fetchedObjects = [context executeFetchRequest:request error:&error];
//ClothingItem *clothingTop, *clothingBottom, *clothingShoes;
NSManagedObject *top = [[fetchedObjects objectAtIndex:currentWardobe] getTop];//[[delegate.favoriteWardrobes objectAtIndex:currentWardobe] objectAtIndex:0];
NSManagedObject *bottom = [[fetchedObjects objectAtIndex:currentWardobe] getBottom];//[[delegate.favoriteWardrobes objectAtIndex:currentWardobe] objectAtIndex:1];
NSManagedObject *shoes = [[fetchedObjects objectAtIndex:currentWardobe] getShoes];//[[delegate.favoriteWardrobes objectAtIndex:currentWardobe] objectAtIndex:2];
Any ideas on what might be going wrong here?

iOS Facebook SDK 3.2 Image Publish w/Description Open Graph

No matter what I try I cannot get my description to show up on Facebook. I used the debugger and all is well with the generated link and the URL is populated with the appropriate data. The picture is uploaded fine, but the description is not there. Is there something I need to setup in Facebook settings for the app?
Here is the relevant code:
- (id<FBPost>)outfitObjectForOutfit{
id<FBPost> result = (id<FBPost>)[FBGraphObject graphObject];
NSString *format =
#"http://mysite.mobi/app/fbOpen.php?"
#"og:title=%#&og:description=%%22%#%%22&"
#"og:caption=%%22%#%%22&"
#"og:image=http://mysite.mobi/images/transBlank.png&"
#"body=%#";
result.url = [NSString stringWithFormat:format,
#"New Post Title",fldDescription.text,fldDescription.text,fldDescription.text];
return result;
}
And the portion that publishes to FB:
- (void)postOpenGraphActionWithPhotoURL:(NSString*)photoURL
{
id<FBPost> outfitObject = [self outfitObjectForOutfit];
id<FBPostOutfit> action =
(id<FBPostOutfit>)[FBGraphObject graphObject];
action.outfit=outfitObject;
if (photoURL) {
NSMutableDictionary *image = [[NSMutableDictionary alloc] init];
[image setObject:photoURL forKey:#"url"];
NSMutableArray *images = [[NSMutableArray alloc] init];
[images addObject:image];
action.image = images;
}
[FBSettings setLoggingBehavior:[NSSet
setWithObjects:FBLoggingBehaviorFBRequests,
FBLoggingBehaviorFBURLConnections,
nil]];
NSLog(#"%#",action);
NSMutableDictionary *params = [NSMutableDictionary dictionary];
[params setObject:fldDescription.text forKey:#"message"];
[FBRequestConnection startForPostWithGraphPath:#"me/appnamespace:action"
graphObject:action
completionHandler:
^(FBRequestConnection *connection, id result, NSError *error) {
NSString *alertText;
if (!error) {
alertText = [NSString stringWithFormat:
#"Posted Open Graph action, id: %#",
[result objectForKey:#"id"]];
} else {
alertText = [NSString stringWithFormat:
#"error: domain = %#, code = %d",
error.domain, error.code];
NSLog(#"%#",error);
}
[[[UIAlertView alloc] initWithTitle:#"Result"
message:alertText
delegate:nil
cancelButtonTitle:#"Thanks!"
otherButtonTitles:nil]
show];
}
];
}
I figured out my problem. I was confusing what the Facebook examples did (activity publishing) with publishing to a user's wall. This was all that I had to do to get it to work:
NSMutableDictionary* params = [[NSMutableDictionary alloc] init];
[params setObject:fldDescription.text forKey:#"message"];
[params setObject:UIImagePNGRepresentation(userImage) forKey:#"picture"];
[FBRequestConnection startWithGraphPath:#"me/photos"
parameters:params
HTTPMethod:#"POST"
completionHandler:^(FBRequestConnection *connection,
id result,
NSError *error)
{
if (error) {
[[[UIAlertView alloc] initWithTitle:#"Result"
message:#"Sorry there was an error posting to Facebook."
delegate:nil
cancelButtonTitle:#"OK"
otherButtonTitles:nil]
show];
}
}];
I should also mention that I had to go into the opengraph settings for my app and allow user messages and user generated photos.

Get facebook user details in ios 6 sdk?

How to retrieve facebook user details with ios 6 inbuilt facebook sdk? I tried few examples, but couldn't get work.
- (void) getFBDetails {
if(!_accountStore)
_accountStore = [[ACAccountStore alloc] init];
ACAccountType *facebookTypeAccount = [_accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
[_accountStore requestAccessToAccountsWithType:facebookTypeAccount
options:#{ACFacebookAppIdKey: #"514284105262105", ACFacebookPermissionsKey: #[#"email"]}
completion:^(BOOL granted, NSError *error) {
if(granted){
NSArray *accounts = [_accountStore accountsWithAccountType:facebookTypeAccount];
_facebookAccount = [accounts lastObject];
NSLog(#"Success");
[self me];
}else{
// ouch
NSLog(#"Fail");
NSLog(#"Error: %#", error);
}
}];
}
- (void)me{
NSURL *meurl = [NSURL URLWithString:#"https://graph.facebook.com/me"];
SLRequest *merequest = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET
URL:meurl
parameters:nil];
merequest.account = _facebookAccount;
[merequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSString *meDataString = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"%#", meDataString);
}];
}
But this fails to grab data from facebook. My app id is correct.
This the error message I got
Error: Error Domain=com.apple.accounts Code=7 "The Facebook server could not fulfill this access request: no stored remote_app_id for app" UserInfo=0x1d879c90 {NSLocalizedDescription=The Facebook server could not fulfill this access request: no stored remote_app_id for app}
Not sure if this will fix it or not, but have you set the Facebook App ID in your AppName-Info.plist file of your app?
The key required is FacebookAppID, which is of type String.
Try filling in your App ID there as well and see if it works.
In iOS6.0 ,you have to ask read and write permissions separately.
First ask for read permissions that is email then ask for other permissions according to the app requirement.
in .h file
#import <Accounts/Accounts.h>
#import <Social/Social.h>
#property (nonatomic, strong) ACAccountStore *accountStore;
#property (nonatomic, strong) ACAccount *facebookAccount;
in .m file
- (void) getuserdetails
{
self.accountStore = [[ACAccountStore alloc]init];
ACAccountType *FBaccountType= nil;
//[self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
if (! FBaccountType) {
FBaccountType = [_accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
}
NSString *key =kFBAppId;
NSDictionary *dictFB = [NSDictionary dictionaryWithObjectsAndKeys:key,ACFacebookAppIdKey,#[#"email"],ACFacebookPermissionsKey, nil];
[self.accountStore requestAccessToAccountsWithType:FBaccountType options:dictFB completion:
^(BOOL granted, NSError *e)
{
if (granted)
{
NSArray *accounts = [self.accountStore accountsWithAccountType:FBaccountType];
self.facebookAccount = [accounts lastObject];
NSLog(#"facebook account =%#",self.facebookAccount);
[self get];
}
else
{
NSLog(#"fb error %#",e.description);
dispatch_async(dispatch_get_main_queue(), ^
{
[self performSelectorOnMainThread:#selector(hideLoader) withObject:nil waitUntilDone:YES];
NSLog(#"%#",e.description);
if([e code]== ACErrorAccountNotFound)
{
UIAlertView* alt = [[UIAlertView alloc] initWithTitle:#"Account not found"
message:msgSetUpFBAccount delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok",nil];
[alt show];
}
else
{
UIAlertView* alt = [[UIAlertView alloc] initWithTitle:msgFBAccessDenied
message:#"" delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok",nil];
[alt show];
}
});
NSLog(#"error getting permission %#",e);
}
}];
}
-(void)get
{
NSURL *requestURL = [NSURL URLWithString:#"https://graph.facebook.com/me"];
SLRequest *request = [SLRequest requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodGET
URL:requestURL
parameters:nil];
request.account = self.facebookAccount;
[request performRequestWithHandler:^(NSData *data,
NSHTTPURLResponse *response,
NSError *error)
{
if(!error)
{
list =[NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error];
NSLog(#"Dictionary contains: %#", list );
if([list objectForKey:#"error"]!=nil)
{
[self attemptRenewCredentials];
}
dispatch_async(dispatch_get_main_queue(),^{
});
}
else
{
[self performSelectorOnMainThread:#selector(hideLoader) withObject:nil waitUntilDone:YES];
NSLog(#"error from get%#",error);
}
}];
}
-(void)attemptRenewCredentials{
[self.accountStore renewCredentialsForAccount:(ACAccount *)self.facebookAccount completion:^(ACAccountCredentialRenewResult renewResult, NSError *error){
if(!error)
{
switch (renewResult) {
case ACAccountCredentialRenewResultRenewed:
NSLog(#"Good to go");
[self get];
break;
case ACAccountCredentialRenewResultRejected:
{
NSLog(#"User declined permission");
UIAlertView* alt = [[UIAlertView alloc] initWithTitle:#"Access Denied"
message:#"You declined permission" delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok",nil];
[alt show];
break;
}
case ACAccountCredentialRenewResultFailed:
{
NSLog(#"non-user-initiated cancel, you may attempt to retry");
UIAlertView* alt = [[UIAlertView alloc] initWithTitle:#"Access Denied"
message:#"non-user-initiated cancel, you may attempt to retry" delegate:self cancelButtonTitle:nil otherButtonTitles:#"Ok",nil];
[alt show];
break;
}
default:
break;
}
}
else{
//handle error gracefully
NSLog(#"error from renew credentials%#",error);
}
}];
}
T**o get this code work the bundle Identifier with which you have registered your application with facebook and bundle identifier in application plist file should be same**

What is the correct way to write the video in asset library and then get their attributes

I am writing video in Asset library using
[library writeVideoAtPathToSavedPhotosAlbum:movieUrl completionBlock:^(NSURL *assetURL, NSError *error) block
gives the url before the video completely write to the asset library. And when i enumerate the library inside the block to get the attributes of video i did not get any video against the url given by above block.
If i manually re-enumerate the asset library 3 or 4 times with the same url i get the video attribures.
This problem mostly occurs when i make video of duration greater than 5 min
My code is:
library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:movieUrl completionBlock:^(NSURL *assetURL, NSError *error)
{
savedAssetURL = assetURL;
[self assetsEmumeration:assetURL];
NSLog(#"asset url %#",assetURL);
if(error)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Failed" message:[error localizedDescription] delegate:self cancelButtonTitle:#"OK" otherButtonTitles:Nil];
[alertView show];
}
}];
-(void) assetsEmumeration:(NSURL *)_url
{
NSLog(#"assets enumeration ");
ALAssetsLibrary *al;
void (^assetGroupEnumerator)(ALAssetsGroup *, BOOL *) = ^(ALAssetsGroup *group, BOOL *stop)
{
[group setAssetsFilter:[ALAssetsFilter allVideos]] ;
[group enumerateAssetsUsingBlock:^(ALAsset *asset, NSUInteger index, BOOL *stop)
{
if (asset)
{
ALAssetRepresentation *representation = [asset defaultRepresentation];
NSURL *url = [representation url];
if([[url absoluteString] isEqualToString:[_url absoluteString]])
{
found = TRUE;
NSDictionary *asset_options = [NSDictionary dictionaryWithObject:[NSNumber numberWithBool:YES] forKey:AVURLAssetPreferPreciseDurationAndTimingKey];
AVAsset *avAsset = [[AVURLAsset alloc] initWithURL:url options:asset_options];
Float64 dur = CMTimeGetSeconds(avAsset.duration);
NSString *fileName = [representation filename];
appDelegate.videoLength = [NSString stringWithFormat:#"%f seconds",dur];
appDelegate.videoSize = [NSString stringWithFormat:#"%lld bytes",[representation size]];
appDelegate.originalFileName = [NSString stringWithFormat:#"%#",fileName];
[MBProgressHUD hideHUDForView:self.view animated:YES];
ExtraInfoViewController *extraInfoViewObj = [[ExtraInfoViewController alloc] init];
[self.navigationController pushViewController:extraInfoViewObj animated:YES];
NSLog(#"duration:%f,fileName:%#",dur,fileName);
}
else
{
found = FALSE;
}
}
}];
if(found == FALSE)
{
NSLog(#"video not found");
}
};
void (^assetFailureBlock)(NSError *) = ^(NSError *error)
{
NSLog(#"failure");
if(ALAssetsLibraryAccessGloballyDeniedError)
{
UIAlertView *alerview = [[UIAlertView alloc] initWithTitle:#"Denied" message:#"Failed to get the meta data. Access to assets library is denied" delegate:self cancelButtonTitle:#"OK" otherButtonTitles:Nil];
[alerview show];
}
};
al=[RecordVideoViewController defaultAssetsLibrary];
[al enumerateGroupsWithTypes:ALAssetsGroupAll usingBlock:assetGroupEnumerator failureBlock:assetFailureBlock];
}
// find out alAsset for that url and then do whatever you want with alAsset.
library = [[ALAssetsLibrary alloc] init];
[library writeVideoAtPathToSavedPhotosAlbum:movieUrl completionBlock:^(NSURL *assetURL, NSError *error)
{
savedAssetURL = assetURL;
NSLog(#"asset url %#",assetURL);
if(error)
{
UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:#"Failed" message:[error localizedDescription] delegate:self cancelButtonTitle:#"OK" otherButtonTitles:Nil];
[alertView show];
}
else
{
[library assetForURL:assetURL
resultBlock:^(ALAsset* alAsset) {
// do whatever you want with alAsset
}];
}
}];