SKStoreProductViewController cancel button crash or not working - ios

I have implemented a delegate for the SKStoreProductViewController.
I add that view controller into the key window's view controller.
I have also implemented a dismiss view controller code in the delegate function.
The question seems to be answer in this question.
Modal App Store won't dismiss
Yet, this problem still persist in my situation.
Display function
if (floor(NSFoundationVersionNumber) > NSFoundationVersionNumber_iOS_6_1) {
NSString *appURL = [NSString stringWithFormat:#"itms-apps://itunes.apple.com/%#/app/id%#",
[[NSLocale preferredLanguages] objectAtIndex:0], applicationID];
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:appURL]];
} else {
NSDictionary* dict = [NSDictionary dictionaryWithObject:applicationID forKey:SKStoreProductParameterITunesItemIdentifier];
SKStoreProductViewController *viewCont = [[SKStoreProductViewController alloc] init];
viewCont.delegate = self;
[viewCont loadProductWithParameters:dict completionBlock:^(BOOL result, NSError *error)
{
UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
if (viewController)
{ [viewController presentViewController:viewCont animated:YES completion:nil]; }
}];
}
Delegate Function
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController
{
if (viewController)
{ [viewController dismissViewControllerAnimated:YES completion:nil]; }
}

The problem is that you must implement
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController
{
if (viewController)
{ [self dismissViewControllerAnimated:YES completion:nil]; }
}
inside the delegate class. If you implement it inside the class whose delegate is presenting the SKStoreProductViewController, it will not work because SKStoreProductViewController will try to call productViewControllerDidFinish: within it's delegate, which isn't implementing that method.
Let me show an example:
#implementation MainViewController
- (void)presentSecondViewController
{
SecondViewController *secondViewController = [[SecondViewController alloc] initWithNibName:#"SecondViewController" bundle:nil];
[secondViewController setDelegate:self];
[self presentViewController:secondViewController animated:YES completion:nil];
}
- (void)productViewControllerDidFinish:(SKStoreProductViewController *)viewController
{
if (viewController)
{ [self dismissViewControllerAnimated:YES completion:nil]; }
}
#end
#implementation SecondViewController {
id delegate <SKStoreProductViewControllerDelegate>;
}
- (void)setDelegate:(id)delegate
{
_delegate = delegate;
}
- (void)callStoreProductViewController
{
SKStoreProductViewController *viewCont = [[SKStoreProductViewController alloc] init];
viewCont.delegate = _delegate;
[viewCont loadProductWithParameters:dict completionBlock:^(BOOL result, NSError *error)
{
UIViewController* viewController = [UIApplication sharedApplication].keyWindow.rootViewController;
if (viewController)
{ [_delegate presentViewController:viewCont animated:YES completion:nil]; }
}];
}
#end
So, if I did understand your problem well, you must implement productViewControllerDidFinish: inside your viewController class, as it is the one who is presentig the SKStoreProductViewController.
Hope this helps!

Please try in Delegate function, replace all lines with:
[self dismissViewControllerAnimated:YES completion:nil];

Where does this code reside? You set the delegate to the instance where this code is written, but you are adding the SKStoreProductViewController to the root view.
Have you tried adding the store to self?
[self presentViewController:storeController animated:YES completion:nil];
Thanks for the delegate function. It isn't obvious in the documentation.

Related

how to validate from UIButton addtarget to a different view controller

I'm adding a UIButton to a view on a different UIViewController. I need the target selector to point to that view controller from json value
- (IBAction)timeline:(id)sender {
if ([_NoTimeline isEqualToString:#"timeline not available :)"]) {
NearmeNOViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"NONearmeViewController"];
[self presentViewController:vc animated:YES completion:nil];
} else {
NearmeFrendViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"NearmeFrendViewController"];
[self presentViewController:vc animated:YES completion:nil];
}
}
Here you are assigning NSString "timeline not available :)" to variable self.NoTimeline if timeline isnt available. And assigning an NSArray to variable self.NoTimeline. If you can edit your api add status key properly. If not try this
- (IBAction)timeline:(id)sender{
if ([self.NoTimeline isKindOfClass:[NSString class]]) {
NearmeNOViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"NONearmeViewController"];
[self presentViewController:vc animated:YES completion:nil];
}
else {
NearmeFrendViewController *vc = [self.storyboard instantiateViewControllerWithIdentifier:#"NearmeFrendViewController"];
[self presentViewController:vc animated:YES completion:nil];
}
}
The problem here seems to be that _NoTimeline is not always of type NSString. Therefore the isEqualToString: operation fails.
You can check for NSString by using:
if ([_NoTimeline isKindOfClass:[NSString class]] {
// Your code
}

I am unable to dismiss a GameCenter leaderboard/view

GameCenter is able to open. However, when the "done" button is pressed on the top right corner to dismiss GameCenter, GameCenter still remains open. How do I close GameCenter?
Below is my code:
- (void) presentLeaderboards
{
GKGameCenterViewController *leaderboardController = [[GKGameCenterViewController alloc] init];
if (leaderboardController != nil)
{
leaderboardController.viewState = GKGameCenterViewControllerStateLeaderboards;
UIViewController *vc = self.view.window.rootViewController;
[vc presentViewController: leaderboardController animated: YES completion:nil];
}
}
- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)viewController
{
NSLog(#"Close");
UIViewController *vc = self.view.window.rootViewController;
[vc dismissViewControllerAnimated:YES completion:nil];
}
You never set a delegate for your GKGameCenterViewController so your gameCenterViewControllerDidFinish: method is never called. You should have found this yourself through a little debugging.
Call dismissViewControllerAnimated on viewController.
Your code should be more like:
- (void) presentLeaderboards
{
GKGameCenterViewController *leaderboardController = [[GKGameCenterViewController alloc] init];
if (leaderboardController != nil)
{
leaderboardController.gameCenterDelegate = self;
leaderboardController.viewState = GKGameCenterViewControllerStateLeaderboards;
UIViewController *vc = self.view.window.rootViewController;
[vc presentViewController: leaderboardController animated: YES completion:nil];
}
}
- (void)gameCenterViewControllerDidFinish:(GKGameCenterViewController *)viewController
{
NSLog(#"Close");
[viewController dismissViewControllerAnimated:YES completion:nil];
}
Adding the line:
leaderboardController.gameCenterDelegate = self;
may lead to a new error. If so, you need to add the following to the .m before the #implementation line.
#interface MyViewControllerNameHere () <GKGameCenterControllerDelegate>
#end
If you already have the class extension, just add the GKGameCenterControllerDelegate part.

UITabBarController setSelectedIndex slow performance

When a user presses the center UITabBarItem I present a modal UIView. Think of it like Instagram.
-(BOOL)tabBarController:(UITabBarController *)tabBarController shouldSelectViewController:(UIViewController *)viewController{
if(viewController == [self.viewControllers objectAtIndex:2])
{
CameraViewController *cameraVC = [[UIStoryboard storyboardWithName:#"Main" bundle:nil] instantiateViewControllerWithIdentifier:#"cameraVC"];
UINavigationController* navController = [[UINavigationController alloc] initWithRootViewController:cameraVC];
navController.navigationBar.barStyle = UIStatusBarStyleLightContent;
[self presentViewController:navController animated:YES completion:nil];
return NO;
}
else
{
return YES;
}
}
This works perfectly.
When I'm done taking a picture in CameraViewController I want the view to be dismissed and the 4th UITabBarItem to be selected for the results of the picture (HistoryViewController).
This is how I do that in CameraViewController (who is modally pushed):
[self dismissViewControllerAnimated:YES completion:nil];
[(UITabBarController *)self.presentingViewController setSelectedIndex:3];
And this is where it gets buggy.
As you can see the text in the 4th tab is selected, but the first tab icon is still selected. Also the presented view is the one from the first tab.
After 10 seconds or so it eventually changes the view to the, correct, 4th tab.
I'm trying to find out what process creates this slowdown so I've set up a lot of NSLog's.
The approximate 10 second slowdown is between [(UITabBarController *)self.presentingViewController setSelectedIndex:3]; in the CameraViewController and viewDidLoad in HistoryViewController.
What is happening in between these calls/methods that could cause the slowdown?
Edit:
In CameraViewController:
- (void)scan {
dispatch_queue_t scanTesseract = dispatch_queue_create("scanTesseract", NULL);
dispatch_async(scanTesseract, ^(void) {
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD setForegroundColor:[UIColor ht_mintDarkColor]];
[SVProgressHUD showProgress:0 status:#"Scanning"];
});
//background processing goes here
[self.tesseract setImage:self.imgToScan.blackAndWhite];
[self.tesseract recognize];
[self filterResults:[self.tesseract recognizedText]];
dispatch_async(dispatch_get_main_queue(), ^{
[SVProgressHUD dismiss];
});
[self scanningDone];
});
}
- (void)scanningDone {
[LastScan getInstance].hasBeenViewed = FALSE;
[self dismissViewControllerAnimated:YES completion:nil];
[(UITabBarController *)self.presentingViewController setSelectedIndex:3];
}
In HistoryViewController:
- (void)viewDidLoad {
[super viewDidLoad];
NSLog(#"ViewDidLoad");
self.navigationController.navigationBar.barStyle = UIStatusBarStyleLightContent;
self.collectionView.backgroundColor = [UIColor whiteColor];
}
You are calling your scanningDone from within a background queue. Execute that method on the main Queue.
dispatch_async(dispatch_get_main_queue(), ^{
[self scanningDone];
});
What about this?
[self dismissViewControllerAnimated:YES completion:^{
[(UITabBarController *)self.presentingViewController setSelectedIndex:3];
}];

GKGameCenterViewController wont dismiss?

I dont get it please help i DONT get a log when i hit done
- (IBAction)loadScores:(id)sender {
GKGameCenterViewController* gameCenterController = [[GKGameCenterViewController alloc] init];
gameCenterController.viewState = GKGameCenterViewControllerStateLeaderboards;
// gameCenterController.gameCenterDelegate = self;
[self presentViewController:gameCenterController animated:YES completion:nil];
}
-(void)gameCenterViewControllerDidFinish:(GKGameCenterViewController*)gameCenterViewController {
NSLog(#"rfffff");
[self dismissViewControllerAnimated:YES completion:nil];
UIViewController *vc = self.view.window.rootViewController;
[vc dismissViewControllerAnimated:YES completion:nil];
}
You have commented the delegates of the GKGameCenterViewController. This means all the delegate methods will not be called like the one that dismisses the view controller. So I suggest you uncomment this line and then run the code and see.

In Modal View, DismissViewControllerAnimated After PresentViewController Not Working

I come across this issue while doing some testing. I have presented a Modal view, called ModalView1. In ModalView1, when a button is pressed, another Modal view, called ModalView2 would be presented using presentViewController. Then I tried dismissing ModalView2 using dismissViewControllerAnimated but it is not working.
Here is the code fragment in button action
- (void) buttonAction: (UIButton*) sender
{
ModalView *ModalView2 = [[ModalView alloc] init];
[self presentViewController:ModalView2 animated:YES completion:nil];
[self dismissViewControllerAnimated:YES completion:nil];
}
Any help would be much appreciated. Thank you.
It's not clear what you are trying to do. I give you two options:
Presenting ModalView2 and then dismissing ModalView2 (makes no sense to me, but that's what I can read in your question)
- (void) buttonAction: (UIButton*) sender {
ModalView* modalView2 = [[ModalView alloc] init];
[self presentViewController:modalView2 animated:YES completion:^{
[modalView2 dismissViewControllerAnimated:YES completion:nil];
}];
}
Presenting ModalView2 and dismissing ModalView1:
- (void) buttonAction: (UIButton*) sender {
ModalView* modalView2 = [[ModalView alloc] init];
UIViewController* presentingViewController = self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^{
[presentingViewController presentViewController:modalView2 animated:YES completion:nil];
}];
}
at time present and dismiss not call so give some time
try this it working me
- (void) buttonAction: (UIButton*) sender
{
[self performSelector:#selector(call) withObject:nil afterDelay:.4];
[self dismissViewControllerAnimated:YES completion:nil];
}
-(void)call
{
ModalView *ModalView2 = [[ModalView alloc] init];
[self presentViewController:ModalView2 animated:YES completion:nil];
}

Resources