In App Purchases in iPhone Programming - iphone

I have developed an application with in App Purchases. I have the following code... In the ViewController.m file I the butoon1Clicked Method I am callInAppPurchases. Actually when click on the button first time i want to perform In App Purchases. If the Transaction is Successful, from the next Click I want to Perform Some Action (For Example I gave NSLog Statement) Where Should I have to write the NSLog stmt(or any code) in the program to perform the Action when i click on the button after A successful Transaction. Please Exaplain me where i have to write. Or Explain me in any process. I thought i want to handle with BOOL Values but i am not able to know where i have to set the BOOL Value as YES / NO. Please Explain me... MyStoreObserver.m file do the In App Purchase Transactions.
ViewController.m
-(IBAction)button1Clicked:(id)sender
{
[self callInAppPurchase];
NSLoG(#"Perform Some Action");
}
#pragma mark-In-AppPurchase code from here
-(void)callInAppPurchase
{
if ([SKPaymentQueue canMakePayments])
{
// Display a store to the user.
}
}
AppDelegate.h
#import <UIKit/UIKit.h>
#import "MyStoreAbserver.h"
#interface iTeach_MathsAppDelegate : NSObject <UIApplicationDelegate>
{
BOOL isPurchased,isFailed;
}
#property (nonatomic, readwrite) BOOL isPurchased,isFailed;
#property (nonatomic, retain) IBOutlet UIWindow *window;
AppDelegate.m
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
MyStoreAbserver *observer = [[MyStoreAbserver alloc] init];
[[SKPaymentQueue defaultQueue] addTransactionObserver:observer];
if([[[NSUserDefaults standardUserDefaults] objectForKey:#"isPurchased"] isEqualToString:#"true"])
self.isPurchased = YES;
else
isPurchased = NO;
isFailed = NO;
// Override point for customization after application launch.
[self.window makeKeyAndVisible];
return YES;
}

I think you refer this link, and implement code... This link is useful for me...
When product purchase you call this function:
(void)productPurchased:(NSNotification *)notification

Related

Correct way to have a one time login iPhone?

I'm trying to create an app that will require a login upon first time load. Once the user logged in successfully the credentials will be stored in a keychain so the user doesn't have to keep logging in.
Here is a quick mockup of the following code I've written; Is using the AppDelegate the correct way to go about handling which View to show first?
AppDelegate.h
#import <UIKit/UIKit.h>
#import "KeychainItemWrapper.h"
#import "ViewController.h"
#import "TestBViewController.h"
#import "User.h"
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) TestBViewController *mainVC; // User see's after loggin in
#property (strong, nonatomic) User *user;
#property (strong, nonatomic) KeychainItemWrapper *keychainItem;
- (void)saveKeychainUsername:(NSString *)username andPassword:(NSString *)password;
- (void)loadLoggedInViewControllers;
#end
AppDelegate.m
#import "AppDelegate.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.keychainItem = [[KeychainItemWrapper alloc] initWithIdentifier:#"AppUniqueID" accessGroup:nil];
// [self.keychainItem resetKeychainItem];
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
// Override point for customization after application launch.
NSString *password = [self.keychainItem objectForKey:(__bridge id)(kSecValueData)];
NSString *username = [self.keychainItem objectForKey:(__bridge id)(kSecAttrAccount)];
NSLog(#"username: %#, password: %#", username, password);
if ([username length] <= 0 || [password length] <= 0) {
// Login VC
ViewController *loginVC = (ViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"Login"];
self.window.rootViewController = loginVC;
} else {
[self loadLoggedInViewControllers];
}
return YES;
}
- (void)loadLoggedInViewControllers {
UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:#"MainStoryboard" bundle:nil];
// Attempt to login user
self.user = [[User alloc] init];
self.user.name = #"Bob";
self.user.hasAccess = YES;
// If user is no longer valid (for whatever reason) remove his keychain information so we can save the new ones.
// Valid user! Skip Login VC
self.mainVC = (TestBViewController *)[mainStoryboard instantiateViewControllerWithIdentifier:#"Main"];
self.mainVC.user = self.user;
self.window.rootViewController = self.mainVC;
}
ViewController.m - Think of this as my LoginViewController
- (IBAction)storePassButtonTap:(id)sender {
if ([[username text] length] > 0 && [[password text] length] > 0) {
AppDelegate *shareDelegate = [[UIApplication sharedApplication] delegate];
[shareDelegate saveKeychainUsername:[username text] andPassword:[password text]];
[shareDelegate loadLoggedInViewControllers];
} else {
if ([[username text] length] <= 0) {
// Error message
}
if ([[password text] length] <= 0) {
// Error message
}
}
}
I wont recommend doing this. I have done this in the past and I have faced problems such as the orientation delegates were not working once I change the rootviewcontroller property of appdelegate like this. Looks like it is fixed in iOS 6, but my understanding is that this is something unusual and not supposed to do.
Instead have a dummy viewcontroller as rootviewcontroller and add other viewcontrollers as its childViewController. You can remove and add any view controller this way.
Personally I wouldn't. I use storyboards and would set a view controller as the root. If I need to do this I would leave the view controller blank (maybe have an activity indicator if it takes a minute to login), run the login code here and then either move to the login segue or the main app segue.
Making sure that both the next screens hide the back button so the user can't go back to this screen.
I like the leave the appDeleage for things like reestablishing tcp connections and closing them when entering background.

How to properly create a root view controller?

After upgrading to xCode 4.2 I am getting the following warning...
Applications are expected to have a root view controller at the end of application launch
After reading as much as I could find on line about the RootViewController I am not sure whether I have created my root view controller properly. I created it a long time ago when I was first learning to program in xCode.
One question I have is it ok to name the root view controller something other than RootViewController. Every example I see now has it named RootViewController. I also see it synthesized in the app delegate like this...
#synthesize rootViewController = _rootViewController;
I do not understand what this is doing. Why not just...
#synthesize rootViewController;
In any event I changed the name of my root view controller to RootViewController and followed the example I found at cupsofcocoa.com. But even after the changes I am still getting the "...expected to have a root controller..." warning.
If someone has the time to take a look and let me know what I am missing, I have listed the the significant portions of my initialization code below.
Thanks,
John
//RootViewController.h
#import <UIKit/UIKit.h>
#interface RootViewController : UIViewController {
}
#end
.
//RootViewController.m
#import "RootViewController.h"
#import "JetLoggerAppDelegate.h"
#implementation RootViewController
#end
.
//JetLoggerAppDelegate.h my app delegate
#import <UIKit/UIKit.h>
#class RootViewController;
#interface JetLoggerAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
RootViewController *rootViewController;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet RootViewController *rootViewController;
#end
.
//.m app delegate
#import "JetLoggerAppDelegate.h"
#import "RootViewController.h" //I don't think I need this here
#implementation JetLoggerAppDelegate
#synthesize window;
#synthesize rootViewController = _rootViewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([launchOptions count] == 0) {
_rootViewController = [[RootViewController alloc] init];
self.window.rootViewController = self.rootViewController;
[window makeKeyAndVisible];
return YES;
}else{
[JLHelper showAlertWithTitle:#"" message:[NSString stringWithFormat:#"launchOptions: %#", launchOptions]];
}
return NO;
}
.
//main.m
#import <UIKit/UIKit.h>
int main(int argc, char *argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
int retVal = UIApplicationMain(argc, argv, nil, #"JetLoggerAppDelegate");
[pool release];
return retVal;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
if ([launchOptions count] == 0) {
_rootViewController = [[RootViewController alloc] init];
self.window.rootViewController = self.rootViewController;
**[window addSubview:_rootViewController.view];**
[window makeKeyAndVisible];
return YES;
}else{
[JLHelper showAlertWithTitle:#"" message:[NSString stringWithFormat:#"launchOptions: %#", launchOptions]];
return NO;
}
return nil;
}
Put return NO inside else statement and on the end put return nil; Hope this help.
Applications are expected to have a root view controller
Replace in AppDelegate
[window addSubview:[someController view]];
to
[self.window setRootViewController:someController];

Facebook API causes app to crash when switching back to main view

Heads Up: I'm not too comfortable with Objective C to know exactly what I'm talking about..
Here's my life story:
My app basically consists of 3 views: main, facebook, and twitter.. No problems with the twitter, no problems switching back and forth between views until... bum bum bum.. I started using the Facebook API in guidance from this site: http://www.mobisoftinfotech.com/blog/iphone/iphone-fbconnect-facebook-connect-tutorial/
Now I can connect to FB and use their API and post without any problem, but when I switch back from the Facebook View on my app to the main view, it switches and then immediately crashes..
FacebookViewController.m
#import "FacebookViewController.h"
#import "Crush_LoveAppDelegate.h"
#define _APP_KEY #"43e37a535cc09c2013bd76fde78dfcc7"
#define _SECRET_KEY #"cc14801521a0c4d1dc31b7cacb891072"
#implementation FacebookViewController
#synthesize facebookFeed;
#synthesize delegate;
#synthesize loginButton;
#synthesize facebookAlert;
#synthesize usersession;
#synthesize username;
#synthesize post;
- (void)viewDidLoad {
Crush_LoveAppDelegate *appDelegate =
(Crush_LoveAppDelegate *) [[UIApplication
sharedApplication]delegate];
if (appDelegate._session == nil){
appDelegate._session = [FBSession sessionForApplication:_APP_KEY secret:_SECRET_KEY delegate:self];
}
if(self.loginButton == NULL)
self.loginButton = [[[FBLoginButton alloc] init] autorelease];
loginButton.frame = CGRectMake(110, 200, 100, 50);
[self.view addSubview:loginButton];
[super viewDidLoad];
self.view.backgroundColor = [UIColor viewFlipsideBackgroundColor];
}
- (IBAction)done:(id)sender {
[self.delegate facebookViewControllerDidFinish:self];
}
FacebookViewController.h
#import <UIKit/UIKit.h>
#import "FBConnect/FBConnect.h"
#import "FBConnect/FBSession.h"
#import "FBConnect/FBRequest.h"
#import "FBConnect/FBStreamDialog.h"
#protocol FacebookViewControllerDelegate;
#interface FacebookViewController : UIViewController <UIApplicationDelegate, FBSessionDelegate, FBRequestDelegate>{
IBOutlet UIWebView *facebookFeed;
id <FacebookViewControllerDelegate> delegate;
FBLoginButton *loginButton;
UIAlertView *facebookAlert;
FBSession *usersession;
NSString *username;
BOOL post;
}
#property(nonatomic,retain) FBLoginButton *loginButton;
#property(nonatomic,retain) UIAlertView *facebookAlert;
#property(nonatomic,retain) FBSession *usersession;
#property(nonatomic,retain) NSString *username;
#property(nonatomic,assign) BOOL post;
#property (nonatomic, assign) id <FacebookViewControllerDelegate> delegate;
#property (nonatomic, retain) IBOutlet UIWebView *facebookFeed;
- (IBAction)done:(id)sender;
#end
#protocol FacebookViewControllerDelegate
- (void)facebookViewControllerDidFinish:(FacebookViewController *)controller;
- (BOOL)textFieldShouldReturn:(UITextField *)textField;
-(void)getFacebookName;
-(void)postToWall;
#end
I chopped some of the .m off of the post to save space, but you get the idea.. I've narrowed it down and it seems like the problem is caused during this line in .m
appDelegate._session = [FBSession sessionForApplication:_APP_KEY secret:_SECRET_KEY delegate:self];
I've been trying to debug it myself for a few hours and I don't know enough on my own to diagnose it myself..
Any thoughts?
Im not sure why your app is crashing, but thought I'd mention that there are a few really good Apple WWDC videos about bug checking and crashing in XCode. In particular, "Debugging with Xcode 4 and LLDB" and "Understanding Crash Reports on iPhone OS", both from the WWDC 2010 videos. I believe you need a developer login to access these videos however but certainly worth a look if you're interested in learning more about debugging.
Okay, for anyone else who had this issue, here's what I did..
FacebookViewController.m File
- (void)dealloc {
[username release];
[usersession release];
[loginButton release];
[super dealloc];
}
I commented out the [loginButton release]; line and it worked oddly enough.. I don't know if this will give me serious problems down the road, but it works for now..

iPhone UISwitch Problem

My switch will not reset when I call clearbtn, it just remains in the same state. Also when I call pushme and check to see if the switch is on or off it always detects its off, what would be causing this? How can I fix this? I created a Window-based application just to play around, I didnt create a UIViewController yet, is that what is causing this issue? Thank You.
My .h file
UIButton *_pushmebutton;
UITextField *_nametextfield;
UILabel *_pushmelabel;
UIImageView *_bgimage;
UISwitch *_bgswitch;
}
#property (nonatomic, retain) IBOutlet UIWindow *window;
#property (nonatomic, retain) IBOutlet UIButton *pushmebutton;
#property (nonatomic, retain) IBOutlet UITextField *nametextfield;
#property (nonatomic, retain) IBOutlet UILabel *pushmelabel;
#property (nonatomic, retain) IBOutlet UISwitch *bgswitch;
#property (nonatomic, retain) IBOutlet UIImageView *bgimage;
- (IBAction)textFieldReturn:(id)sender;
- (IBAction)backgroundTouched:(id)sender;
- (IBAction)pushme:(id)sender;
- (IBAction)clearbtn:(id)sender;
- (IBAction)changebg:(id)sender;
My .m File
#import "MyFirstAppAppDelegate.h"
#implementation MyFirstAppAppDelegate
#synthesize window=_window;
#synthesize pushmebutton = _pushmebutton;
#synthesize nametextfield = _nametextfield;
#synthesize pushmelabel = _pushmelabel;
#synthesize bgswitch = _bgswitch;
#synthesize bgimage = _bgimage;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
/*
Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
*/
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
/*
Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
*/
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
/*
Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
*/
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
/*
Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
*/
}
- (void)applicationWillTerminate:(UIApplication *)application
{
/*
Called when the application is about to terminate.
Save data if appropriate.
See also applicationDidEnterBackground:.
*/
}
- (void)dealloc
{
[_window release];
[_pushmebutton release];
[_pushmelabel release];
[_nametextfield release];
[super dealloc];
}
-(IBAction)pushme:(id)sender
{
if([_nametextfield.text length] == 0)
{
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"Error" message:#"Please Enter Your Name" delegate:nil cancelButtonTitle:#"OK" otherButtonTitles: nil]; [alert show]; [alert release];
}
else
{
[_nametextfield resignFirstResponder];
if(_bgimage.hidden == false)
{
self.pushmelabel.backgroundColor = [UIColor redColor];
}
if(_bgswitch.on)
{
NSString *msg = [[NSString alloc] initWithFormat:#"Hello, %# Thanks for using the App! Switch: On!", _nametextfield.text];
self.pushmelabel.text = msg;
}
else
{
NSString *msg = [[NSString alloc] initWithFormat:#"Hello, %# Thanks for using the App! Switch: Off!", _nametextfield.text];
self.pushmelabel.text = msg;
}
}
}
-(IBAction)clearbtn:(id)sender;
{
_nametextfield.text = #"";
_pushmelabel.text = #"";
_pushmelabel.backgroundColor = [UIColor clearColor];
[_bgswitch setOn:NO animated:YES];
}
-(IBAction)textFieldReturn:(id)sender
{
[sender resignFirstResponder];
}
-(IBAction)backgroundTouched:(id)sender
{
[_nametextfield resignFirstResponder];
}
-(IBAction)changebg:(id)sender
{
if(_bgimage.hidden == false)
{
_bgimage.hidden = true;
_pushmelabel.backgroundColor = [UIColor clearColor];
}
else if(_bgimage.hidden == true)
{
_bgimage.hidden = false;
if([_pushmelabel.text length] > 0)
{
_pushmelabel.backgroundColor = [UIColor redColor];
}
}
}
#end
My hunch is telling me that you haven't connected the outlet to the switch in IB. Check for that connection and make it if necessary. If the connection is already there, NSLog your switch in the pushme method and see if it comes out to nil.
You really shouldn't use ApplicationDelegate like this - it's intended to be the delegate for application events, and that is all it should be. Since it doesn't inherit from UIViewController, it wont participate in normal view lifecycle stuff, so it's very likely that is your problem. Put your view stuff in a UIViewController, and try your switch again.

Programmatically created ViewController and awakeFromNiB?

I am creating a viewController programmatically (hopefully the right way) My problem is that I previously created the controller in IB and have code I want to call in awakeFromNib. As I currently have things viewDidLoad works fine but awakeFromNib does not. Is there anyway to get awakeFromNib to call or an alternative method that I can use in its place?
#class MyViewController;
#interface TEST_ControllerAppDelegate : NSObject <UIApplicationDelegate> {
UIWindow *window;
MyViewController *viewController;
}
#property(nonatomic, retain) IBOutlet UIWindow *window;
#end
.
#implementation TEST_ControllerAppDelegate
#synthesize window;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
viewController = [[MyViewController alloc] init];
[window addSubview:[viewController view]];
[window makeKeyAndVisible];
return YES;
}
- (void)dealloc {
[viewController release];
[window release];
[super dealloc];
}
#end
EDIT_001:
I have pretty much come to the conclusion that using viewDidLoad is going to be my best option, particularly as I want to initialise IBOutlet instance variables.
In order to be called, the awakeFromNib method must be parameter-less (no sender):
- (void)awakeFromNib {
// Do whatever is needed...
}
Take care of the casing, as no error or warning will be logged if you mistype the method.