I would like to open some iTunes song's link in my app, but I don't want to redirect from my app to app store. I would like to open iTunes Store as a modal view like Facebook do it when you press on a sponsored app. How can I do it? ( in "home made" modal view with web view?? I hope not )
For example how to open this link as a modal view, and user can buy right there: #"https://itunes.apple.com/us/album/how-i-feel/id731197191?i=731197197&ign-mpt=uo%3D4"
Right now I'm using this:
[[UIApplication sharedApplication]
openURL:[NSURL URLWithString:#"itms://itunes.apple.com/us/album/how-i-feel/id731197191?i=731197197&uo=4"]];
Of course it won't open in a modal view.
Ok, so I' ve solved my problem, and I won't delete my question, because I didn't find it in stack overflow :
SKStoreProductViewController *storeProductViewController = [[SKStoreProductViewController alloc] init];
[storeProductViewController setDelegate:self];
[storeProductViewController loadProductWithParameters:#{SKStoreProductParameterITunesItemIdentifier : #"731197191"} completionBlock:^(BOOL result, NSError *error) {
if (error) {
NSLog(#"Error %# with User Info %#.", error, [error userInfo]);
} else {
// Present Store Product View Controller
[self presentViewController:storeProductViewController animated:YES completion:nil];
}
}];
Related
What I am trying to do and it doesn't work is the following: post an image of my choise and also an url to facebook using the built in facebook sharer, the problem is that it doesn't work to upload both, it's either picture + text and works nice or url + text and works nice, but when I combine them text+picture+url it gets the picture from the url and not my uploaded pic. Any suggestions? I am doing this on iOS9
UIImage *tableViewScreenshot = [tblFeed screenshotOfCellAtIndexPath:idx];
SLComposeViewController *fbSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[fbSheet setInitialText:#"I need your vote"];
[fbSheet addURL:[NSURL URLWithString:str]];
[fbSheet addImage:tableViewScreenshot];
The problem is that Facebook has changed some policies and by this you can't have a text or an image present as a default. That's why you're not seeing the text and photo. Here are 2 scenarios one with Facebook app installed and another one without Facebook app installed. The below one is when the Facebook app is already installed on the device.
And this one is when the Facebook app is not installed on the device
And this is my code:
SLComposeViewController *controller = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[controller addURL:[NSURL URLWithString:#"https://www.google.com"]];
[controller addImage:[UIImage imageNamed:#"icon_circle"]];
[controller setInitialText:#"Bhavuk you're great!"];
[self presentViewController:controller animated:YES completion:nil];
So If you want to share everything, better use FB SDK.
So it seems at the moment there is no solution for this and we should find a workaround for it, maybe uploading everything first a picture to an url and then use fb sdk to point to a picture from that url + the link as an offline pic doesn't seem to work unfortunately.
Unfortunately, the problem remains even on iOS 10. An easy workaround is simply drop the URL, for example:
SLComposeViewController *fbSheet = [SLComposeViewController composeViewControllerForServiceType:SLServiceTypeFacebook];
[fbSheet setInitialText:#"I need your vote"];
[fbSheet addImage:tableViewScreenshot];
It's not a direct answer to the OP but in case of what you only care is showing text and image while sharing something, here is a possible solution:
If the image and the text that you want to show within your SlComposeView is the same as the information that exist within the web site that you are going to share; you don't need to do anything special at the iOS side at all.
If you are the one who also created the web page that you're sharing URL of, should you have proper Open Graph META Tags at the page, SLComposeView of type Facebook will show image and text which were set at the webpage within your app automagically.
For some information about Facebook Open Graph Markup; see https://developers.facebook.com/docs/sharing/webmasters/#markup
I have had facebook sharing working fine in my ios app when fb not install. and i have installed fb to use the latest api (4.7.x) and now sharing doesnt work at all. I check that I have publish_actions permission (which I do prior to this method being called, I have 'expicitly shared' checked in open graph settings, action types, capabilities. I am validating the content (I dont get an error) and have a delegate, none of its methods get called.
-(void)shareWithFacebook:(NSString *)message
{
if ([[FBSDKAccessToken currentAccessToken] hasGranted:#"publish_actions"])
{
NIDINFO(#"Facebook sharing has publish_actions permission");
}
else
{
FBSDKLoginManager *loginManager = [[FBSDKLoginManager alloc] init];
[loginManager logInWithPublishPermissions:#[#"publish_actions"]
handler:^(FBSDKLoginManagerLoginResult *result, NSError *error)
{
NIDERROR(#"Facebook sharing getting publish_actions permission failed: %#", error);
}
];
}
NSMutableDictionary *properties = [NSMutableDictionary dictionaryWithDictionary: #{
#"og:type": #"article",
#"og:title": #"Bloc",
#"og:description": message,
#"og:url": #"http://getonbloc.com/download"
}];
FBSDKShareOpenGraphObject *object = [FBSDKShareOpenGraphObject objectWithProperties:properties];
// Create the action
FBSDKShareOpenGraphAction *action = [FBSDKShareOpenGraphAction actionWithType:#"mynamespace:Share" object:object key:#"article"];
[action setString:#"true" forKey:#"fb:explicitly_shared"];
// Create the content
FBSDKShareOpenGraphContent *content = [[FBSDKShareOpenGraphContent alloc] init];
content.action = action;
content.previewPropertyName = #"article";
// Share the content
FBSDKShareAPI *shareAPI = [[FBSDKShareAPI alloc] init];
shareAPI.shareContent = content;
shareAPI.delegate = self;
NSError *error;
if([shareAPI validateWithError:&error] == NO)
{
NIDERROR(#"Facebook sharing content failed: %#", error);
}
[shareAPI share];
}
#pragma mark - FBSDKSharingDelegate
- (void) sharer:(id<FBSDKSharing>)sharer didCompleteWithResults:(NSDictionary *)results
{
NIDINFO(#"Facebook sharing completed: %#", results);
}
- (void) sharer:(id<FBSDKSharing>)sharer didFailWithError:(NSError *)error
{
NIDERROR(#"Facebook sharing failed: %#", error);
}
- (void) sharerDidCancel:(id<FBSDKSharing>)sharer
{
NIDINFO(#"Facebook sharing cancelled.");
}
Is there such feature that can be un-locked when the user shares my app via Facebook or Tweeter?
Like this:
1) The user clicks on "Share" button within my app
2) My app is then posted(shared or advertised) on the wall of the user's facebook
3) Some feature gets unlocked within my app
You can use the Facebook sharing delegate method to know whether the user has successfully shared OR not.
Below is FB developer link which show various sharing methods,according to your requirements.
https://developers.facebook.com/docs/sharing/ios
Below are the methods in which you can know the sharing status
- (void)sharer:(id<FBSDKSharing>)sharer didCompleteWithResults:(NSDictionary *)results{
//UNLOCK THE APP FEATURE IN THIS METHOD
}
- (void)sharerDidCancel:(id<FBSDKSharing>)sharer{
}
- (void)sharer:(id<FBSDKSharing>)sharer didFailWithError:(NSError *)error{
NSLog(#"%#",error);
}
See iOS Facebook Tutorial for an example of how its done on the facebook end.
On the app side you can setup a flag on NSUserDefaults or write to the app filesystem to check if the feature is unlocked.
This can be done relatively painlessly using UIActivityViewController and its completion handler.
NSString *message = #"my app is awesome.";
NSURL *link = [NSURL URLWithString:#"awesomeapp.com"];
UIActivityViewController *shareController = [[UIActivityViewController alloc] initWithActivityItems:#[message, link]
applicationActivities:nil];
//add whatever you don't want
shareController.excludedActivityTypes = #[UIActivityTypeMessage];
shareController.completionWithItemsHandler =
^(NSString *activityType, BOOL completed, NSArray *returnedItems, NSError *activityError) {
//Share wasn't completed, don't unlock
if (!completed || activityError) {
return;
}
//Facebook or Twitter
if ([activityType isEqualToString:UIActivityTypePostToFacebook] ||
[activityType isEqualToString:UIActivityTypePostToTwitter]) {
//Unlock item logic
}
};
[self presentViewController:shareController animated:YES completion:^{
//Whatever
}];
In my app I show more apps with SKStoreProductViewController, but the Apple store review team rejects it with the reason:
"An error message displays when tapping on the more apps button."
Everything works fine when I test it on my devices.
Below is the screenshot Apple sent me, what could be the problem?
Sample code:
__weak typeof(self) weakSelf = self;
SKStoreProductViewController* vc = [[SKStoreProductViewController alloc] init];
vc.delegate = self;
[vc loadProductWithParameters:#{SKStoreProductParameterITunesItemIdentifier : #1000000000} completionBlock:^(BOOL result, NSError * _Nullable error) {
if(result==NO){
//handle failure
return;
}
[weakSelf presentViewController:vc animated:YES completion:nil];
}];
ITMLKitErrorDomain errors frequently occur when a SKStoreProductViewController tries to call loadProductWithParameters with invalid parameters. Example full error:
<Warning>: [SKStoreProductViewController]: Did fail with error: Error Domain=ITMLKitErrorDomain Code=101 "The operation couldn’t be completed. (ITMLKitErrorDomain error 101.)" UserInfo={ ... } {ITMLKitErrorHTTPStatus=400}
Verify you do not have any typos or unexpected keys in your parameters dictionary when calling loadProductWithParameters. Verify the values for keys such as SKStoreProductParameterITunesItemIdentifier and SKStoreProductParameterAffiliateToken are valid.
If you are not experiencing this issue on test devices, just send it to review again, this could be a temporary issue with itunes site (it is used to show these "more apps", isn't it?). There are several mentions of that problem over the internet without any solution.
During investigation of youre issue it is possible to conclude that is quite rare case that could be connected with wrong product id in case of SkProductViewController. Also you should check if you are trying to show single app or amount of them. Because Apple have bug that is connected with showing of multiple items.
I am using SKStoreProductViewController in this way. This is code block that show app in App Store:
SKStoreProductViewController *storeProductViewController = [[SKStoreProductViewController alloc] init];
[storeProductViewController setDelegate:self];
[storeProductViewController loadProductWithParameters:#{SKStoreProductParameterITunesItemIdentifier : #"xxxxx"} completionBlock:^(BOOL result, NSError *error) {
if (error) {
NSLog(#"Error %# with User Info %#.", error, [error userInfo]);
} else {
[self presentViewController:storeProductViewController animated:YES completion:nil];
}
}];
Then i use delegate SKStoreProductViewControllerDelegate like this:
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController {
[self dismissViewControllerAnimated:YES completion:nil];
}
Also i use [button setExclusiveTouch:YES]; because customers some times press few buttons with products. Also test you're id if it is single product.
I just finished dealing with this same issue. Everything works just fine when testing the app but the App Review team was rejecting my app for showing an alert view with the error returned by the call to loadProductWithParameters.
I worked around the issue by launching the App Store in Safari if the call to loadProductWithParameters fails. This provides a useful fallback in the rare cases when SKStoreProductViewController isn't working.
SKStoreProductViewController *vc = [[SKStoreProductViewController alloc] init];
vc.delegate = self;
NSDictionary *parameters = #{ SKStoreProductParameterITunesItemIdentifier : someAppId };
[vc loadProductWithParameters:parameters completionBlock:^(BOOL result, NSError *error) {
if (result) {
[someController presentViewController:vc animated:YES completion:nil];
} else {
NSURL *appURL = [NSURL URLWithString:[NSString stringWithFormat:#"https://itunes.apple.com/app/id%#?mt=8", someAppId]];
if ([[UIApplication sharedApplication] canOpenURL:appURL]) {
[[UIApplication sharedApplication] openURL:appURL];
} else {
// display the error in an alert
}
}
}];
I've had a rejection for the same reason (2 rejections) and I've found that I get this exact error testing without Wi-Fi (on a Wi-Fi only device).
So my thought is that Apple is testing this on a Wi-Fi device (they said they are testing on a Wi-Fi iPad) and they have disabled Wi-Fi. It would be nice if in the rejection they told you about the fact that they were testing with no internet access but you need to read between the lines.
So since you can't display the controller without an internet connection you need to show an appropriate error like "Please check your internet connection and try again."
Definitely don't show the localized description for the Error returned to the user.
There are some apps (like the free version of Cut the Rope) that present the App Store page of other apps directly in the app (probably using a modal view controller).
How do I implement this in my own app?
Example from Cut the Rope:
You can use SKStoreProductViewController for this, check out documentation for more detail
if ([SKStoreProductViewController class]) {
NSString *yourAppID = #"";//Give your app id here
NSDictionary *appParameters = #{SKStoreProductParameterITunesItemIdentifier :yourAppID};
SKStoreProductViewController *productViewController = [[SKStoreProductViewController alloc] init];
[productViewController setDelegate:self];
[productViewController loadProductWithParameters:appParameters completionBlock:nil];
[self presentViewController:productViewController animated:YES completion:nil];
}
One can implement a App Store page of any application within their own app by using the SKStoreProductViewController class.
NSString *strURL = #"" //Keep the App store URL here.
if ([[[UIDevice currentDevice]systemVersion]floatValue] >= 6.0)
{
SKStoreProductViewController *storeProductViewController = [[SKStoreProductViewController alloc] init];
NSRange range = [strURL rangeOfString:#"/id"];
NSRange rangeID = {range.location + 3, 9};
NSString *strAppID = [strURL substringWithRange:rangeID];
NSLog(#"appid = %#", strAppID);
// Configure View Controller
[storeProductViewController setDelegate:self];
[storeProductViewController loadProductWithParameters:#{SKStoreProductParameterITunesItemIdentifier : strAppID}
completionBlock:^(BOOL result, NSError *error) {
if (error) {
NSLog(#"Error %# with User Info %#.", error, [error userInfo]);
} else {
}
}];
// Present Store Product View Controller
[self presentViewController:storeProductViewController animated:YES completion:nil];
}
The above code also extracts the app ID from the URL.
You can read about it in the class reference.
In iOS app,
Anytime I call this function to open app store,
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:#"itms-apps://app-url"]];
The Original app will be deactivated.
The user will then have to restart the original app after they exit the App Store.
It’s very inconvenient way of installation.
Is there any way to open App Store links without leaving the app?
For example, opened as popup window,
after installation just close the popup window, and I can see the original app.
Updated :
I found a great example!
Like this game's popup.
Yes, we can open an App store link without leaving the existing app in IOS 6+.
you can use below for it.
#import <StoreKit/StoreKit.h>
SKStoreProductViewController *storeController = [[SKStoreProductViewController alloc] init];
storeController.delegate = delegate;
NSDictionary *productParameters = #{ SKStoreProductParameterITunesItemIdentifier : appStoreID };
[storeController loadProductWithParameters:productParameters completionBlock:^(BOOL result, NSError *error) {
//Handle response
}
Thanks
My version is here.
1) #import <StoreKit/StoreKit.h> and set SKStoreProductViewControllerDelegate
2) add delegate response method,
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController
{
// if user do cancel, close it
[viewController dismissViewControllerAnimated:YES completion:nil];
}
3) add store open code.
void SomeClassName::openAppStore(string appStoreId, string appUrl)
{
// below iOS 6.0
NSString *appUrlStatic = [NSString stringWithUTF8String:appUrl.c_str()];
// iOS 6.0 or above, appstore id is 9-digin number
NSString *appId = [NSString stringWithUTF8String:appStoreId.c_str()];;
// check SKStoreProductViewController API exist or not
if(NSClassFromString(#"SKStoreProductViewController")) {
SKStoreProductViewController *storeController = [[SKStoreProductViewController alloc] init];
storeController.delegate = self;
NSDictionary *productParameters = #{ SKStoreProductParameterITunesItemIdentifier : appId };
[storeController loadProductWithParameters:productParameters completionBlock:^(BOOL result, NSError *error) {
if (result) {
[self presentViewController:storeController animated:YES completion:nil];
} else {
[[[UIAlertView alloc] initWithTitle:#"Error Occur"
message:#"Error to open App Store."
delegate:nil
cancelButtonTitle:#"Ok"
otherButtonTitles: nil] show];
}
}];
[storeController release];
} else {
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:appUrlStatic]];
}
}