First of all i am using parse.com to store information.
This code simply opens the Maps app every time this method is run and saves the users location in a server.
MKDirectionsRequest *request = [[MKDirectionsRequest alloc] init];
[request setSource:[MKMapItem mapItemForCurrentLocation]];
[request setDestination:endingItem];
[request setTransportType:MKDirectionsTransportTypeAutomobile];
[request setRequestsAlternateRoutes:YES];
MKDirections *directions = [[MKDirections alloc] initWithRequest:request];
[directions calculateDirectionsWithCompletionHandler:^(MKDirectionsResponse *response, NSError *error) {
if ( ! error && [response routes] > 0) {
MKRoute *route = [[response routes] objectAtIndex:0];
//route.distance = The distance
NSLog(#"total %f",route.expectedTravelTime );
int time = ceil(route.expectedTravelTime/60);
self.ETA = [#(time) stringValue];
NSLog(#"test %d",time);
NSLog(#"Total Distance (in Meters) :%0.1f",route.distance/1000);
self.distance = [#(route.distance*4899) stringValue];
// IF decline was pressed, need to fix if it's accepted
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
[params setObject:self.distance forKey:#"dist"];
[PFCloud callFunctionInBackground:#"sendAccepted" withParameters:params block:^(id object, NSError *error) {
if (!error) {
NSLog(#"Success answer sent");
} else {
NSLog(#"Failed to push");
}
}];
}
}];
[endingItem openInMapsWithLaunchOptions:launchOptions];
}
What i noticed is that if Maps application is already open when this method is run then it does not save the users data until i return to the applikation. HOWEVER if i close the Maps application before this method is run the it is always sent to the server.
Now the problem i think is that it obviously takes more time for Maps app to open if it was not opened before hence giving my applikation more time to complete the update. How can i solve this so it will still update the location even if my applikation goes to the background?
Related
I'm sharing the video on Facebook (Without the SLComposer) from my IOS App. it will send successfully but I want To add the HashTag Text With it. Im Trying it But It will not get add shared with the video (only video get shared ).
FBSDKShareVideo *ShareVideo = [FBSDKShareVideo videoWithVideoURL:appDelegateObj.finalVideoUrl];
ShareVideo.videoURL = appDelegateObj.finalVideoUrl;
FBSDKShareVideoContent *ShareContnt = [[FBSDKShareVideoContent alloc] init];
ShareContnt.video = ShareVideo;
ShareContnt.hashtag = [FBSDKHashtag hashtagWithString:[NSString stringWithFormat:#"%#",#"We are #sharing this #video for the #testing of #video and the #HashTag Text"]];
[FBSDKShareAPI shareWithContent:ShareContnt delegate:self];
Please Help me for this issues ?
100% Working
I got the ANS Of these...
//Using these code we only share can't send the text / Title or name of video...
-(void)facbookSharng
{
NSLog(#"Permission for sharing..%#",[FBSDKAccessToken currentAccessToken].permissions);
if ([[FBSDKAccessToken currentAccessToken] hasGranted:#"contact_email"])
{
FBSDKShareVideo *ShareVideo = [FBSDKShareVideo videoWithVideoURL:appDelegateObj.finalVideoUrl];
ShareVideo.videoURL = appDelegateObj.finalVideoUrl;
FBSDKShareVideoContent *ShareContnt = [[FBSDKShareVideoContent alloc] init];
ShareContnt.video = ShareVideo;
[FBSDKShareAPI shareWithContent:ShareContnt delegate:self]
// write the deleate methdo for post ID..
}
}
//But for these Facebook gives another way,
NSLog(#"Permission for sharing..%#",[FBSDKAccessToken currentAccessToken].permissions);
if ([[FBSDKAccessToken currentAccessToken] hasGranted:#"contact_email"])
{
NSData *videoData = [NSData dataWithContentsOfURL:appDelegateObj.finalVideoUrl];
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithCapacity:3L];
[params setObject:videoData forKey:#"video_filename.MOV"];
[params setObject:#"Title for this post." forKey:#"title"];
[params setObject:#"#Description for this post." forKey:#"description"];
[[[FBSDKGraphRequest alloc] initWithGraphPath:#"/me/videos" parameters:params HTTPMethod:#"POST"]
startWithCompletionHandler:^(FBSDKGraphRequestConnection *connection, id result, NSError *error) {
if (!error) {
//video posted
NSLog(#"Facebook sharing completed %#:",result);
strFbSocialPostId = [result valueForKey:#"id"];//post ID
}
}];
}
I want to allow the users to search for a street name and have the results displayed in a UITableView.
For the moment the region is not important, it can be from any region.
I could not find any relevant example in my searches and I don't know if I should use CLLocation or MKLocalSearch.
Based on docs, I should use MKLocalSearch:
Although local search and geocoding are similar, they support
different use cases. Use geocoding when you want to convert between
map coordinates and a structured address, such as an Address Book
address. Use local search when you want to find a set of locations
that match the user’s input.
But I have tried both methods and it gives me only 1 result (even-though there is an NSArray returned.
This is the CLGeocoder approach:
CLGeocoder *geocoding = [[CLGeocoder alloc] init];
[geocoding geocodeAddressString:theTextField.text completionHandler:^(NSArray *placemarks, NSError *error) {
if (error) {
NSLog(#"%#", error);
} else {
NSLog(#"%i", [placemarks count]);
for(CLPlacemark *myStr in placemarks) {
NSLog(#"%#", myStr);
}
}
}];
And this is my MKLocalSearch try:
MKLocalSearchRequest *request = [[MKLocalSearchRequest alloc] init];
request.naturalLanguageQuery = theTextField.text;
request.region = self.region;
localSearch = [[MKLocalSearch alloc] initWithRequest:request];
[localSearch startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error){
if (error != nil) {
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(#"Map Error",nil)
message:[error localizedDescription]
delegate:nil
cancelButtonTitle:NSLocalizedString(#"OK",nil) otherButtonTitles:nil] show];
return;
}
if ([response.mapItems count] == 0) {
[[[UIAlertView alloc] initWithTitle:NSLocalizedString(#"No Results",nil)
message:nil
delegate:nil
cancelButtonTitle:NSLocalizedString(#"OK",nil) otherButtonTitles:nil] show];
return;
}
self.streets = response;
[self.streetsTableView reloadData];
}];
MKLocalSearch seems to return more than 1 response in some cases, but these are related to places not street names searches.
Thanks in advance.
This is the closest I could get. This involves using google places API Web Service.
Note: You could probably use their Google Maps API, etc. I am sure there are other ways to get this information from the various Google APIs.
NSURL *googlePlacesURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://maps.googleapis.com/maps/api/place/autocomplete/json?input=%#&location=%f,%f&sensor=true&key=API_KEY", formattedSearchText, location.coordinate.latitude,
location.coordinate.longitude]];
The response is a JSON object. Convert it to a dictionary.
NSDictionary *response = [NSJSONSerialization JSONObjectWithData:_googlePlacesResponse
options:NSJSONReadingMutableContainers error:&error];
if([[response objectForKey:#"status"] isEqualToString:#"OK"])
{
NSArray *predictions = [response objectForKey:#"predictions"];
for(NSDictionary *prediction in predictions)
{
NSArray *addressTypes = [prediction objectForKey:#"types"];
if([addressTypes containsObject:#"route"])
{
//This search result contains a street name.
//Now get the street name.
NSArray *terms = [prediction objectForKey:#"terms"];
NSDictionary *streetNameKeyValuePair = [terms objectAtIndex:0];
NSLog(#"%#",[streetNameKeyValuePair objectForKey#"value"]);
}
}
}
The possible types seem to be
Route -> Street name
Locality -> City/location name
Political -> State, etc
Geocode -> lat/long available
You could populate the table view with those predictions that ONLY contain route as an address type. This could work.
CLGeocoder simply returns address format.
Slap this in your code and play with the contents of mapitems
MKLocalSearchRequest *request = [MKLocalSearchRequest new];
request.naturalLanguageQuery = #"Pizza";
request.region = MKCoordinateRegionMake(location.coordinate, MKCoordinateSpanMake(.01, .01));
MKLocalSearch *search = [[MKLocalSearch alloc]initWithRequest:request];
[search startWithCompletionHandler:^(MKLocalSearchResponse *response, NSError *error) {
NSArray *mapItems = response.mapItems;
for (MKMapItem *mapItem in mapItems) {
MKPointAnnotation *point = [MKPointAnnotation new];
point.coordinate = mapItem.placemark.coordinate;`
}
}];
The array returned contains mapItems, you can iterate over the array to pull out all the mapItems like this:
myMatchingItems = [[NSMutableArray alloc] init];
for (MKMapItem *item in response.mapItems){
[myMatchingItems addObject:item];
}
Each mapItem.placemark.thoroughfare contains the Street of the location that was found.
I am adding share functionalities on my facebook app.Like When a "saying" is selected there is a button for sharing that "saying" on facebook.And while clicking this button I can only see the shared saying on my facebook page,there isnt any information about my ios app.How can I make everyone knows that this saying is shared through my iOS app? Please help me....
I may be a little late. Hope this helps.
You have to use the Accounts framework and the Social framework to share with your app name.
First make sure you have set up your App on Facebook correctly. Then you can use the Facebook App ID to share your posts through your app.
Here is a sample code that shows you how to use the Accounts framework with the Social Framework :
ACAccountType * facebookAccountType = [self.accountStore accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierFacebook];
// At first, we only ask for the basic read permission
NSArray * permissions = #[#"email"];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] initWithObjectsAndKeys:#"275485699289493", ACFacebookAppIdKey, permissions, ACFacebookPermissionsKey, ACFacebookAudienceOnlyMe, ACFacebookAudienceKey, nil];
NSArray *accounts = [self.accountStore accountsWithAccountType:facebookAccountType];
//it will always be the last object with single sign on
self.facebookAccount = [accounts lastObject];
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:dict completion:^(BOOL granted, NSError *error) {
if (granted && error == nil) {
/**
* The user granted us the basic read permission.
* Now we can ask for more permissions
**/
NSArray *readPermissions = #[ #"publish_actions"];
[dict setObject:readPermissions forKey: ACFacebookPermissionsKey];
[self.accountStore requestAccessToAccountsWithType:facebookAccountType options:dict completion:^(BOOL granted, NSError *error) {
if(granted && error == nil) {
NSDictionary *parameters = #{#"message": #"This Should Work Perfectly !! "};
NSURL *feedURL = [NSURL URLWithString:#"https://graph.facebook.com/me/feed"];
SLRequest *feedRequest = [SLRequest
requestForServiceType:SLServiceTypeFacebook
requestMethod:SLRequestMethodPOST
URL:feedURL
parameters:parameters];
feedRequest.account = self.facebookAccount;
[feedRequest performRequestWithHandler:^(NSData *responseData,
NSHTTPURLResponse *urlResponse, NSError *error)
{
// Handle response
}];
} else {
NSLog(#"error is: %#",[error description]);
}
}];
} else {
NSLog(#"error is: %#",[error description]);
}
}];
}
I m using the following twitter api to get the friends list:
https://api.twitter.com/1.1/friends/list.json?
And using [SLRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) to get the response data, and perform UI Changes and model data changes in performRequestWithHandler block.
But a single request at the maximum retrieves only 20 friends.(if you set the cursor parameter in api to -1).
I can use the cursor parameter of the api to send request to get the next 20 friends and so on until the cursor value is 0.
cursor parameter can be set to the 'next_cursor' parameter in the response data of the previous request.
But i m not aware of how to call another SLRequest with in the performRequestWithHandler of the previous request, until the 'next_cursor' value in response data of previous request is 0.
Can anybody tell me how to get all the friends using SLRequest or using any other way.
Any help is appreciated.
Thank you.
u can call the next request in the request handler just after you get the response of twitter friends.
Sorry for not elaborating. I thought you would understand.
Here is the code.
ACAccountStore *account = [[ACAccountStore alloc] init];
ACAccountType *accountType = [account accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
// Request access from the user to access their Twitter account
[account requestAccessToAccountsWithType:accountType options:nil completion:^(BOOL granted, NSError *error)
{
// Did user allow us access?
if (granted == YES)
{
// Populate array with all available Twitter accounts
NSArray *arrayOfAccounts = [account accountsWithAccountType:accountType];
// Sanity check
if ([arrayOfAccounts count] > 0)
{
[self postRequest];
}
}
}];
- (void)PostRequest
{
// Keep it simple, use the first account available
ACAccount *acct = [arrayOfAccounts objectAtIndex:0];
NSMutableDictionary *tempDict = [[NSMutableDictionary alloc] init];
[tempDict setValue:#"Posting video" forKey:#"status"];
// Build a twitter request
SLRequest *postRequest = [SLRequest requestForServiceType:SLServiceTypeTwitter requestMethod:SLRequestMethodPOST URL:[NSURL URLWithString:#"https://api.twitter.com/1.1/statuses/update.json"] parameters:tempDict];
[postRequest setAccount:acct];
[postRequest performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
NSLog(#"Twitter response, HTTP response: %i", [urlResponse statusCode]);
NSString *output = [[NSString alloc] initWithData:responseData encoding:NSUTF8StringEncoding];
NSLog(#"%#", output);
**// calling this again and again will help you with multiple post request.**
[self postRequest]
}];
}
Similar thing can be done for friend list too.
Hope I helped.
So I'm trying to use the built in Twitter API in iOS 5 to retrieve a list of all the followers for a given user. In all the example documentation I can find, requests are made to the API passing inline blocks to be executed when the request returns, which is fine for most of the simpler stuff, BUT when I'm trying to get ~1000 followers, and the request is returning them paged in sizes ~100, I'm stuck on how to recursively call the request again using the 'next paging address' returned and processed inside the completion block. Here is the code:
- (void)getTwitterFollowers {
// First, we need to obtain the account instance for the user's Twitter account
ACAccountStore *store = [[ACAccountStore alloc] init];
ACAccountType *twitterAccountType =
[store accountTypeWithAccountTypeIdentifier:ACAccountTypeIdentifierTwitter];
// Request access from the user for access to his Twitter accounts
[store requestAccessToAccountsWithType:twitterAccountType
withCompletionHandler:^(BOOL granted, NSError *error) {
if (!granted) {
// The user rejected your request
NSLog(#"User rejected access to his account.");
}
else {
// Grab the available accounts
NSArray *twitterAccounts =
[store accountsWithAccountType:twitterAccountType];
if ([twitterAccounts count] > 0) {
// Use the first account for simplicity
ACAccount *account = [twitterAccounts objectAtIndex:0];
// Now make an authenticated request to our endpoint
NSMutableDictionary *params = [[NSMutableDictionary alloc] init];
[params setObject:#"1" forKey:#"include_entities"];
// The endpoint that we wish to call
NSURL *url = [NSURL URLWithString:#"http://api.twitter.com/1/followers.json"];
// Build the request with our parameter
request = [[TWRequest alloc] initWithURL:url
parameters:params
requestMethod:TWRequestMethodGET];
[params release];
// Attach the account object to this request
[request setAccount:account];
[request performRequestWithHandler:^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
if (!responseData) {
// inspect the contents of error
FullLog(#"%#", error);
}
else {
NSError *jsonError;
followers = [NSJSONSerialization JSONObjectWithData:responseData
options:NSJSONReadingMutableLeaves
error:&jsonError];
if (followers != nil) {
// THE DATA RETURNED HERE CONTAINS THE NEXT PAGE VALUE NEEDED TO REQUEST THE NEXT 100 FOLLOWERS,
//WHAT IS THE BEST WAY TO USE THIS??
FullLog(#"%#", followers);
}
else {
// inspect the contents of jsonError
FullLog(#"%#", jsonError);
}
}
}];
} // if ([twitterAccounts count] > 0)
} // if (granted)
}];
[store release];
}
Ideally I'd like some way to listen for this data being returned, check for a next page value and if it exists, reuse the code block and append the data returned. I', sure there must be a 'best-practice' way to achieve this, any help would be much appreciated!
To use any block recursively you have to declare it first and define it later. Try this:
__block void (^requestPageBlock)(NSInteger pageNumber) = NULL;
requestPageBlock = [^(NSInteger pageNumber) {
// do request with some calculations
if (nextPageExists) {
requestPageBlock(pageNumber + 1);
}
} copy];
// now call the block for the first page
requestPageBlock(0);
To expand on #Eimantas' answer, your request handler is expecting a specific block signature, so you need a different way to handle the page number.
-(void)getTwitterFollowers {
// set up request...
__block int page = 0;
__block void (^requestHandler)(NSData*, NSHTTPURLResponse*, NSError*) = null;
__block TWRequest* request = [[TWRequest alloc] initWithURL:url
parameters:params
requestMethod:TWRequestMethodGET];
requestHandler = [^(NSData *responseData, NSHTTPURLResponse *urlResponse, NSError *error) {
followers = [NSJSONSerialization JSONObjectWithData:responseData
options:NSJSONReadingMutableLeaves
error:&jsonError];
if (followers != nil) {
// process followers
page++;
NSMutableDictionary *params = [NSMutableDictionary dictionaryWithDictionary:request.parameters];
// update params with page number
request = [[TWRequest alloc] initWithURL:url
parameters:params
requestMethod:TWRequestMethodGET];
[request performRequestWithHandler:requestHandler];
}
} copy];
// now call the block for the first page
[request performRequestWithHandler:requestHandler];
}