I am tring to open appstore page as model view inside application using following code
[NSDictionary dictionaryWithObject:#"APPID" forKey:SKStoreProductParameterITunesItemIdentifier];
SKStoreProductViewController *productViewController = [[SKStoreProductViewController alloc] init];
[self presentViewController:productViewController animated:YES completion:nil];
but when appstore is open inside application, it is opening as blank page.
Please refer screenshoot attached
I dont understand why appstore page of my app is not opening. I am passing APPID in above code.
Is there any other way to rate application without closing app ?
basically, something like this could help on you, after you linked the StoreKit.framework to your project. please note, it may not be working on simulator; on real device it works well.
.h
#interface UIYourViewController : UIViewController <SKStoreProductViewControllerDelegate> { }
.m
- (void)myOwnCustomMethod {
SKStoreProductViewController *_controller = [[SKStoreProductViewController alloc] init];
[_controller setDelegate:self];
[_controller loadProductWithParameters:[NSDictionary dictionaryWithObjectsAndKeys:#"364709193", SKStoreProductParameterITunesItemIdentifier, nil] completionBlock:^(BOOL result, NSError *error) {
if (result) {
[self.navigationController presentViewController:_controller animated:TRUE completion:nil];
} else {
// you can handle the error here, if you'd like to.
}
}];
}
#pragma mark - <SKStoreProductViewControllerDelegate>
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController {
[self dismissViewControllerAnimated:TRUE completion:nil];
}
In Swift 3,
import StoreKit
class DetailViewController: UIViewController {
#IBAction func onEditButton(_ sender: UIBarButtonItem) {
let vc = SKStoreProductViewController()
vc.delegate = self
present(vc, animated: true, completion: nil)
vc.loadProduct(withParameters: [SKStoreProductParameterITunesItemIdentifier: 351091731]) { (success, error) in
if !success {
print("\(error)")
}
}
}
}
extension DetailViewController: SKStoreProductViewControllerDelegate {
func productViewControllerDidFinish(_ viewController: SKStoreProductViewController) {
viewController.dismiss(animated: true, completion: nil)
}
}
Make sure SKStoreProductParameterITunesItemIdentifier's value is Number, as stated in its head file, though String value is currently OK.
Related
I've just implemented a commenting feature in my app. Ideally when someone leaves a comment, I'd like all notified people be able to swipe the push notification and open the app on that post.
I assume you want to open the concerned page directly. There are many ways to go about this, and it depends on how your app is laid out.
If you want to open an inner page upon app launch, you can programmatically trigger the segues that the user would otherwise need to make manually. (this ensures the back/home buttons work as opposed to loading the desired page directly).
Here's an excerpt from one of my own code, your use case may not be the same, but this is all i can do unless you give us more details.
- (BOOL) navigateToRespectiveSectionforPushNot:(NSDictionary*)pushNot
{
id rootVC = self.window.rootViewController;
NSLog(#"ROOT CLASS : %#", [rootVC class]);
if ([rootVC isKindOfClass:[SWRevealViewController class]])
{
NSLog(#"Root Class looking good... mission Navigate!!");
SWRevealViewController *homeVC = (SWRevealViewController*) rootVC;
NSString *category = [[pushNot objectForKey:pushPayloadKeyaps] objectForKey:pushPayloadKeyCategory];
NSString *subCat = [[pushNot objectForKey:pushPayloadKeyaps] objectForKey:pushPayloadKeySubCategory];
NSLog(#"category : %# , subcat : %#",category,subCat);
//The code for the page to which i'm supposed to navigate to is contained in the push notification payload
if ([category isEqualToString:pushCategoryItemChat])
{
[homeVC.rearViewController performSegueWithIdentifier:#"chatPush" sender:nil];
UINavigationController *nc = (UINavigationController*)homeVC.frontViewController;
NSLog(#"FrontView Class : %#",[nc.viewControllers[0] class]);
UITableViewController *tvc = (UITableViewController*)nc.viewControllers[0];
NSDictionary *send = #{chatPushTargetUserId:subCat,chatPushTargetUserName:#"",chatPushTargetUserImage:#""};
[tvc performSegueWithIdentifier:#"seguePushDemoVC" sender:send];
return YES;
}
//communityPush historyPush
else if ([category isEqualToString:pushCategoryItemCommunity])
{
if ([subCat isEqualToString:pushSubCatItemNewRequest])
{
[homeVC.rearViewController performSegueWithIdentifier:#"communityPush" sender:nil];
return YES;
}
else if ([subCat isEqualToString:pushSubCatItemAccepted])
{
[homeVC.rearViewController performSegueWithIdentifier:#"communityPush" sender:nil];
return YES;
}
}
else if ([category isEqualToString:pushCategoryItemHistory])
{
[homeVC.rearViewController performSegueWithIdentifier:#"historyPush" sender:nil];
return YES;
}
}
else
{
UIAlertView *whoa = [[UIAlertView alloc] initWithTitle:#"WHOA!!" message:#" That wasn't supposed to happen. You are not even logged in. Call 911..." delegate:nil cancelButtonTitle:#"mmKay.." otherButtonTitles:nil, nil];
[whoa show];
}
return NO;
}
I hope the code is self explanatory. cheers
In my app I am using TTOpenInAppActivity to insert "Open in" action inside UIActivityController.
Inside it works like this:
Some view controller presents UIActivityController with TTOpenInActivity already built in.
-(void)openWithAction
{
NSURL *fileURL = SOME_URL;
CGRect rect = SOME_RECT;
TTOpenInAppActivity *openInAppActivity = [[TTOpenInAppActivity alloc] initWithView:self.view andRect:rect];
UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:#[fileURL] applicationActivities:#[openInAppActivity]];
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
// Store reference to superview (UIActionSheet) to allow dismissal
openInAppActivity.superViewController = activityViewController;
// Show UIActivityViewController
[self presentViewController:activityViewController animated:YES completion:NULL];
} else {
// code for iPad, irrelevant
}
}
When user taps "Open in" button, the following method is triggered:
- (void)performActivity
{
if(!self.superViewController){
[self activityDidFinish:YES];
return;
}
// Dismiss activity view
if(UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone){
// iPhone dismiss UIActivityViewController
[self.superViewController dismissViewControllerAnimated:YES completion:^(void){
if (self.fileURLs.count > 1) {
[self openSelectFileActionSheet];
}
else {
// Open UIDocumentInteractionController
[self openDocumentInteractionControllerWithFileURL:self.fileURLs.lastObject];
}
}];
} else {
// code for iPad, irrelevant
}
}
}
As the app is for iPhone only, this piece of code should be executed:
[self.superViewController dismissViewControllerAnimated:YES completion:^(void){
if (self.fileURLs.count > 1) {
[self openSelectFileActionSheet];
}
else {
// Open UIDocumentInteractionController
[self openDocumentInteractionControllerWithFileURL:self.fileURLs.lastObject];
}
}];
In iOS7 everything works fine. In iOS8 UIActivityController is dismissed and then nothing happens.
While debugging I did manage to detect that in iOS8 completion handler is never called.
Please, help me find out the reason for this behavior and make it work as it should.
Thank you in advance.
In iOS 8, when you tap on "Open in", UIActivityViewController is dismissed automatically. So, when you call self.superViewController dismissViewControllerAnimated:completion:, viewController was already dismissed and method do nothing (so completion not called).
For my iPhone app I want to implement the option to upload files to Soundcloud by making use of the CocoaSoundCloudAPI. In the instructions "How to use the SoundCloud API directly" it is explained how to modally present a loginViewController:
- (void)login {
[SCSoundCloud requestAccessWithPreparedAuthorizationURLHandler:
^(NSURL *preparedURL){
SCLoginViewController *loginViewController;
loginViewController =
[SCLoginViewController loginViewControllerWithPreparedURL:preparedURL
completionHandler:^(NSError *error){
if (SC_CANCELED(error)) {
NSLog(#"Canceled!");
} else if (error) {
NSLog(#"Ooops, something went wrong: %#", [error localizedDescription]);
} else {
NSLog(#"Done!");
}
}];
[self presentModalViewController:loginViewController
animated:YES];
}];
}
Now I replaced
[self presentModalViewController:loginViewController
animated:YES];
with
[self presentViewController:loginViewController
animated:YES
completion:nil];
because the first method is deprecated in iOS 7.
But the problem is that the Soundcloud loginViewController overlaps the status bar when presented in this fashion. And since I don't want to change the Soundcloud API I do not have the option to customize the loginViewController accordingly e.g. in its - viewDidLoad method (as suggested in many other posts on Stackoverflow).
Unfortunately there is a toolbar with a button on top the loginViewController. How can I configure my loginViewController from inside my own (presenting) view controller so that it won't overlap with the status bar when presented?
As mentioned in my comment to the original question I did not find a neat solution for this problem. However I managed to implement a workaround that does the job:
The basic idea is to add the SCLoginViewController as a child view controller of another custom view controller that is not part of the Soundcloud framework and that you can customize to your needs. This is my new login method that presents the login view controller:
- (BOOL)loginToSoundcloud {
BOOL __block success = NO;
[SCSoundCloud requestAccessWithPreparedAuthorizationURLHandler:^(NSURL *preparedURL){
SCLoginViewController *loginViewController;
loginViewController =
[SCLoginViewController loginViewControllerWithPreparedURL:preparedURL
completionHandler:^(NSError *error){
if (SC_CANCELED(error)) {
NSLog(#"Canceled!");
} else if (error) {
NSLog(#"Ooops, something went wrong: %#", [error localizedDescription]);
} else {
NSLog(#"Done!");
success = YES;
}
}];
/* BEGIN workaround for iOS7 bug:
when modally presenting a view controller it overlaps the status bar */
CBContainerVCToFixStatusBarOverlap *containerVC = [[CBContainerVCToFixStatusBarOverlap alloc] init];
[containerVC addChildViewController:loginViewController];
containerVC.view.backgroundColor = [UIColor clearColor];
if ([CBAppDelegate iOSVersionIs7OrHigher]) {
loginViewController.view.frame =
CGRectMake(loginViewController.view.frame.origin.x,
loginViewController.view.frame.origin.y + 20,
containerVC.view.frame.size.width,
containerVC.view.frame.size.height - 20);
} else {
loginViewController.view.frame =
CGRectMake(loginViewController.view.frame.origin.x,
loginViewController.view.frame.origin.y,
containerVC.view.frame.size.width,
containerVC.view.frame.size.height);
}
[containerVC.view addSubview:loginViewController.view];
/* END workaround for iOS7 bug */
[self presentViewController:containerVC
animated:YES
completion:nil];
}];
return success;
}
To check for the iOS version I implemented the following method in my CBAppDelegate:
+ (BOOL)iOSVersionIs7OrHigher {
return floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1;
}
CBContainerVCToFixStatusBarOverlap is a simple view controller class with no additional methods and only one declared property. This is the content of CBContainerVCToFixStatusBarOverlap.h:
#interface CBContainerVCToFixStatusBarOverlap : UIViewController
#property (strong, nonatomic) IBOutlet UIView *containerView;
#end
I am using UIActivityViewController to present sharing options and I want to display another view controller when the UIActivityViewController is dismissed by the user or when the animation that follows "activityDidFinish:(bool)completed" gets over. When I try to present the other controller in the completion handler of the UIActivityViewController, I get the following warning and the second VC does not get displayed at all!
Attempt to present <_UIViewController: 0x1e16f020> on <###> while a presentation is in progress!
UIActivityViewController activityVC = [[UIActivityViewController alloc]initWithActivityItems:selectedAssetsURL applicationActivities:nil];
[activityVC setCompletionHandler:^(NSString *activityType, BOOL completed) {
NSLog(#"completed");
//Present another VC
}];
The question is, how to know when the UIActivityViewController disappears from the screen? Even the -ViewDidAppear method of the view controller which presents the UIActivityViewController does not get fired!
In this link there's good information about how the UIActivityViewController works:
http://www.apeth.com/iOSBook/ch26.html#_activity_view
Basically you can subclass the UIActivityViewController into another class and implement a method to know when it has been dissmissed.
UIActivityViewController* avc =
[[UIActivityViewController alloc]
initWithActivityItems:#[myCoolString]
applicationActivities:#[[MyCoolActivity new]]];
Here’s the preparatory part of the implementation of MyCoolActivity:
-(NSString *)activityType {
return #"com.neuburg.matt.coolActivity"; // make up your own unique string
}
-(NSString *)activityTitle {
return #"Be Cool";
}
-(UIImage *)activityImage {
return self.image; // prepared beforehand
}
-(BOOL)canPerformWithActivityItems:(NSArray *)activityItems {
for (id obj in activityItems) {
if ([obj isKindOfClass: [NSString class]])
return YES;
}
return NO;
}
-(void)prepareWithActivityItems:(NSArray *)activityItems {
self.items = activityItems;
}
To perform the activity, we implement one of two methods:
-(void)performActivity {
// ... do something with self.items here ...
[self activityDidFinish:YES];
}
-(UIViewController *)activityViewController {
MustacheViewController* mvc = [MustacheViewController new];
mvc.activity = self;
mvc.items = self.items;
return mvc;
}
And then MustacheViewController would have code like this:
- (IBAction)doCancel:(id)sender {
[self.activity activityDidFinish:NO];
}
- (IBAction)doDone:(id)sender {
[self.activity activityDidFinish:YES];
}
I am Using Outh to add Twitter to my app.
Below are two UIViewControllers for login and posting tweets respectively.
1.SettingViewcontroller
2.DetailViewcontroller
This code for login to twitter with SettingViewcontroller.
- (void)switchAction1:(UISwitch*)sender
{
if (sender.on){
if(_engine)
return;
_engine = [[SA_OAuthTwitterEngine alloc] initOAuthWithDelegate:self]
_engine.consumerKey = #"###";
_engine.consumerSecret = #"###";
UIViewController *controller =[SA_OAuthTwitterController controllerToEnterCredentialsWithTwitterEngine: _engine delegate: self];
DetailViewcontroller *detobj=[[DetailViewcontroller alloc]init];
detobj.detail_enginne=_engine;
[detobj release];
[self presentModalViewController: controller animated: YES];
}
if(!sender.on)
{
NSLog(#"Logout section");
}
}
And In DetailViewcontroller Iam doing like this for posting.
if(buttonIndex == 1)
{
if(detail_enginne!=nil)
{
NSLog(#"engine availble");
NSString *str=#"hai twitterrrrrrrrrrr";
[detail_enginne sendUpdate:str];
}
else{
NSLog(#"Engine not availabele");
}
}
Here Iam unable to send tweets from DetailViewcontroller.
How to achive this?
in DetailViewcontroller.m
#import "SettingViewcontroller.h"
replace
[_enginnne sendUpdate:str];
to
[[[self parentViewController] _enginnne] sendUpdate:str];