I am new to iOS development. I am developing photo sharing app. In this , First i need to use Web service for Login page. Web service is in PHP and return response in JSON. I want to save login session throughout the app . When user launches the app then it always check whether the user is logged in or not. Please give me suitable solution for this very soon as there is deadline of my job if i don`t do this in early time. Here is my Code.
**<HomeKiddoAppDelegate.h file>**
#import <UIKit/UIKit.h>
#class HomeKiddoViewController;
#interface HomeKiddoAppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) UIWindow *window;
#property (strong, nonatomic) HomeKiddoViewController *viewController;
#end
**<HomeKiddoAppDelegate.m file>**
#import "HomeKiddoAppDelegate.h"
#import "HomeKiddoViewController.h"
#implementation HomeKiddoAppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions: (NSDictionary *)launchOptions
{
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// Override point for customization after application launch.
self.viewController = [[HomeKiddoViewController alloc] initWithNibName:#"HomeKiddoViewController" bundle:nil];
self.window.rootViewController = self.viewController;
[self.window makeKeyAndVisible];
//Register defaults
NSMutableDictionary *defaultsDictionary = [[NSMutableDictionary alloc] init];
[[NSUserDefaults standardUserDefaults] registerDefaults: defaultsDictionary];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
}
- (void)applicationWillTerminate:(UIApplication *)application
{
}
#end
> #import <UIKit/UIKit.h>
> #import "SignInViewController.h"
>
> #interface HomeKiddoViewController : UIViewController{
> SignInViewController *signInViewController;
> }
>
> -(IBAction)signInClicked:(id)sender;
>
> #end
**<HomekiddoViewController.m>**
> #import "HomeKiddoViewController.h"
>
> #interface HomeKiddoViewController ()
>
> #end
>
> #implementation HomeKiddoViewController
>
> - (void)viewDidLoad
> {
> [super viewDidLoad];
> }
>
> - (void)viewDidUnload {
> [super viewDidUnload]; }
>
> - (BOOL)shouldAutorotateToInterfaceOrientation: (UIInterfaceOrientation)interfaceOrientation {
> return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown); }
>
> -(IBAction)signInClicked:(id)sender{
> if(signInViewController==nil){
> signInViewController=[[SignInViewController alloc]initWithNibName:#"SignInViewController" bundle:nil];
> }
> [self.view addSubview:signInViewController.view];
> } #end
>
>
**<SignInFormViewController.h>**
> #import <UIKit/UIKit.h>
> #import "SBJson.h"
>
> #interface SignInFormViewController : UIViewController
> <NSURLConnectionDelegate>
{
> IBOutlet UITextField *email1;
> IBOutlet UITextField *password1;
> NSURLConnection *conn;
> NSMutableData *webData;
> IBOutlet UITextView *textView;
> }
#
property (nonatomic, retain) IBOutlet UITextField *email1; #property
> (nonatomic, retain) IBOutlet UITextField *password1;
>
>
-(IBAction)btnSignInClicked:(id)sender;
> -(IBAction)backClicked:(id)sender;
>
> #end
>
import "SignInFormViewController.h"
#interface SignInFormViewController ()
#end
#implementation SignInFormViewController
#synthesize email1;
#synthesize password1;
- (void)viewDidLoad
{
[super viewDidLoad];
}
- (void)viewDidUnload
{
[super viewDidUnload];
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
}
-(IBAction)btnSignInClicked:(id)sender{
NSString *queryUrl=[NSString stringWithFormat:#"Url of the web service with parameters",email1.text,password1.text];
NSURL *url=[NSURL URLWithString:queryUrl];
NSMutableURLRequest *request=[NSMutableURLRequest requestWithURL:url];
conn=[[NSURLConnection alloc] initWithRequest:request delegate:self];
if(conn)
{
webData=[NSMutableData data];
NSLog(#"in Connection if statement");
}
}
-(void) connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *) response{
[webData setLength: 0];
NSLog(#" inside didReceiveZResponse");
}
-(void) connection:(NSURLConnection *)connection didReceiveData:(NSData *) data {
[webData appendData:data];
NSLog(#"inside did receive data");
}
-(void) connection:(NSURLConnection *)connection didFailWithError:(NSError *) error {
NSLog(#"in fail with error");
}
-(void) connectionDidFinishLoading:(NSURLConnection *)connection{
[email1 resignFirstResponder];
[password1 resignFirstResponder];
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
[defaults setObject:email1.text forKey:#"email"];
[defaults setObject:password1.text forKey:#"password"];
[defaults synchronize];
}
-(IBAction)backClicked:(id)sender{
[self.view removeFromSuperview];
}
#end
I'm gonna give you a comprehensive answer.
Don't use NSUserDefaults and don't store password it's a bad solution
Let's create a structured user class instead
When the user logged in, you will need to make sure you have access to user data throughout the app so you can get the data on any screen when you need it.
To achieve this, we need to make a great structure to organize this properly. Remember that current user and another users are both "users" so we will use the same class.
Create a class and name it "EDUser" (you can choose other name if you want).
This class will contain a user information (either current user or other user).
More than that, this class will have capability to log the user in.
Here's a picture of what the class might look like:
class EDUser {
var firstName: String
var lastName: String?
var birthDate: NSDate?
init(firstName: String, lastName: String?, birthDate: NSDate?) {
self.firstName = firstName
self.lastName = lastName
self.birthDate = birthDate
}
}
// MARK: - Accessor
extension EDUser {
class var currentUser: EDUser? {
get {
return loadCurrentUserFromDisk()
}
set {
saveCurrentUserToDiskWithUser(newValue)
}
}
}
// MARK: - Log in and out
extension EDUser {
class func loginWithUsername(username: String,
andPassword password: String,
callback: (EDUser?, NSError) -> Void) {
// Access the web API
var parameters = [
"username": username,
"password": password
]
YourNetworkingLibrary.request(.POST,
"https://api.yourwebsite.com/login",
parameters: parameters).responseJSON {
response in
if response.statusCode == .Success {
let user = EDUser(firstName: response["firstName"],
lastName: response["lastName"],
birthDate: NSDate.dateFromString(response["birthDate"]))
currentUser = user
callback(currentUser, nil)
} else {
callback(nil, yourError)
}
}
}
class func logout() {
deleteCurrentUserFromDisk()
}
}
// MARK: - Data
extension EDUser {
class private func saveCurrentUserToDiskWithUser(user: EDUser) {
// In this process, you encode the user to file and store it
}
class private func loadCurrentUserFromDisk() -> EDUser? {
// In this process, you get the file and decode that to EDUser object
// This function will return nil if the file is not exist
}
class private func deleteCurrentUserFromDisk() {
// This will delete the current user file from disk
}
}
// MARK: - Helper
extension NSDate {
class func dateFromString(string: String) -> NSDate {
// convert string into NSDate
}
}
Use Case
Now with everything in place, we can use it like this
Non-blocking logging in process
EDUser.loginWithUsername(username: "edward#domain.com",
password: "1234") {
user, error in
if error == nil {
// Login succeeded
} else {
// Login failed
}
}
Logging out
EDUser.logout()
Check whether the user is logged in
if EDUser.currentUser != nil {
// The user is logged in
} else {
// No user logged in
// Show the login screen here
}
Get current user data on any screen
if let currentUser = EDUser.currentUser {
// do something with current user data
}
Store other user as object
let user = EDUser(firstName: "Edward",
lastName: "Anthony",
birthDate: NSDate())
You can save the login data in the NSUserDefaults like this.
NSUserDefaults *userDefaults = [NSUserDefaults standardUserDefaults];
[userDefaults setObject:cookieString forKey:#"Cookie"];
[userDefaults setObject:pwString forKey:#"Password"];
[userDefaults synchronize];
Then you can load the user default from anywhere you like in the app with
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSString *myString = [defaults objectForKey:#"Cookie"];
the simplest solution is to use keychain.
Another simple method is to save the login credentials in a locale file (txt, xml or even an sqldb).
Related
I am writing an application in Objective C and I keep getting a Use of Undeclared Identifier 'startClient' error. I have attached a link to my project file and the tutorial link is here: https://www.sinch.com/tutorials/building-one-button-app-conference-calling/
https://drive.google.com/file/d/0B5loU41SFmzDZ2RNbWJsR0xoSk0/view?usp=sharing
The relevant portion of my code is here...
#import <QuartzCore/QuartzCore.h>
#import "ConferenceViewController.h"
#import "LoginViewController.h"
#import <SinchCallingUIKit/SinchCallingUIKit.h>
#class ConferenceViewController;
#interface UIView ()
#end
#implementation ConferenceViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
}
- (void)viewDidAppear:(BOOL)animated
{
- (void)startClient {}{
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[[CallingManager sharedManager] startClientWithKey:8b6893bf-41c6-4527-bc68-9d3703c13be3 secret:Ox18uwq7gkiAdeQYzntN6A== userName:[defaults stringForKey:#"userName"] sandbox:NO launchOptions:nil];
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
if ([defaults stringForKey:#"userName"] == nil)
{
[self performSegueWithIdentifier:#"login" sender:nil];
}
else
{
[self startClient];
}
}
You can't stick a function inside another function. You have the implementation of startClient inside of viewDidAppear.
I don't know what your viewDidAppear is supposed to do, but this will compile:
- (void)viewDidAppear:(BOOL)animated
{
if ([defaults stringForKey:#"userName"] == nil)
{
[self performSegueWithIdentifier:#"login" sender:nil];
}
else
{
[self startClient];
}
}
- (void)startClient
{
NSUserDefaults* defaults = [NSUserDefaults standardUserDefaults];
[[CallingManager sharedManager] startClientWithKey:8b6893bf-41c6-4527-bc68-9d3703c13be3 secret:Ox18uwq7gkiAdeQYzntN6A== userName:[defaults stringForKey:#"userName"] sandbox:NO launchOptions:nil];
}
I am trying to bypass the login page to welcome page if the person already have a token. I am using basic auth and afnetworking for the api call. Once the user logs the username&password, I base 64 the info and get a token. I save the token in a nsobject class where I create a token singleton and a simple is logged in method where it checks if the user has the token or not. But for some reason I always see the login page(meaning it skips my condition method). If any one can point out where I am making the mistake, it would be great.
This is class where I create the login singleton
CredentialStore.h
#import <Foundation/Foundation.h>
#import "LoginInfo.h"
#interface CredentialStore : NSObject
-(BOOL)isLoggedIn;
#property (nonatomic) LoginInfo *loginInfo;
+(id)sharedStore;
#end
CredentialStore.m
#import "CredentialStore.h"
static CredentialStore *sharedInsance;
#implementation CredentialStore
+(id)sharedStore
{
if (!sharedInsance) {
sharedInsance = [[CredentialStore alloc] init];
}
return sharedInsance;
}
- (BOOL)isLoggedIn {
return (self.loginInfo.authToken != nil);
}
#end
this is my authenticationapimanager class
AuthAPIManager.h
#import "AFHTTPSessionManager.h"
#interface AuthAPIManager : AFHTTPSessionManager
+ (id)sharedManager;
#end
AuthAPIManager.m
#import "AuthAPIManager.h"
#import "CredentialStore.h"
#define BASE_URL #"http://Url"
#define Base_Proxy #"http://Url"
static AuthAPIManager *sharedManager;
#implementation AuthAPIManager
//Setup the singleton to use throught the life of the application
+(id)sharedManager
{
if (!sharedManager) {
sharedManager = [[AuthAPIManager alloc] initWithBaseURL:[NSURL URLWithString:Base_Proxy]];
}
return sharedManager;
}
-(id)initWithBaseURL:(NSURL *)url
{
self = [super initWithBaseURL:url];
if (self) {
}
return self;
}
#end
this is the class where I save the login information
LoginInfo.h
#import <Foundation/Foundation.h>
#interface LoginInfo : NSObject
#property(nonatomic,copy)NSNumber *AccountId;
#property(nonatomic,copy)NSString *DeviceType;
#property(nonatomic,copy)NSString *HardwareId;
#property(nonatomic,copy)NSString *NickName;
#property(nonatomic,copy)NSString *authToken;
-(id)initWithDictionary:(NSDictionary *)dictionary;
#end
LoginInfo.m
#import "LoginInfo.h"
#implementation LoginInfo
-(id)initWithDictionary:(NSDictionary *)dictionary
{
self =[super init];
if (self) {
self.AccountId = [dictionary objectForKey:#"AccountId"];
self.DeviceType = [dictionary objectForKey:#"DeviceType"];
self.HardwareId = [dictionary objectForKey:#"HardwareId"];
self.NickName = [dictionary objectForKey:#"NickName"];
}
return self;
}
and in my view controller, in viewwillappearmethod, I check if the user has a token or not but this is the part I am having problems with
LoginViewController.m
#interface LoginViewController ()
#property (nonatomic,strong) CredentialStore *credentialStore;
#end
implementation LoginViewController
#pragma mark - UIViewController
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self checkIfThePersonLoggedIn];
}
-(void)checkIfThePersonLoggedIn
{
CredentialStore *credStore = [CredentialStore sharedStore];
// //check to see if the use has the token already
if (credStore.loginInfo.authToken != nil) {
[self.loginButton setHidden:YES];
[self performSegueWithIdentifier:#"welcomeViewSegue" sender:self];
}
else [self.loginButton setHidden:NO];
NSLog(#"checkForToken - loginviewcontroller");
}
and in my getTokenRequest this is how I save the token in the event of success
NSString *authToken = [responseObject objectForKey:#"Token"];
CredentialStore *credStore = [CredentialStore sharedStore];
LoginInfo * loginInfo = credStore.loginInfo;
loginInfo.authToken = authToken;
NSLog(#"this is the token here %#",authToken);
[self performSegueWithIdentifier:#"welcomeViewSegue" sender:self];
I appreciate the help.
this is where I instantiate login info
- (IBAction)login:(id)sender
{
[_usernameTextField resignFirstResponder];
[SVProgressHUD show];
id LoginParams =#{
#"NickName" : self.usernameTextField.text,
#"password" :_StoreIdentifierForVendor,
#"DeviceType" :_DeviceModel
};
[[AuthAPIManager sharedManager]POST:#"/url" parameters:LoginParams success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(#"response: %#", responseObject);
LoginInfo *loginInfo = [[LoginInfo alloc] initWithDictionary:responseObject];
CredentialStore *credStore = [CredentialStore sharedStore];
credStore.loginInfo = loginInfo;
[self getToken];
}failure....
I made an AR app that recognize image and show the object recognized in an AlertView. In the AlertView I have 2 buttons: Add and Cancel, I'm using the UIAlertViewDelegate to understand which button the user pressed. If the user press the Add button, the object recognized will be stored in an array. I pass this array to another ViewController, in which I set up a TableView. On the bottom of this TableView there's a button "Pay" to go to another ViewController in which I display the total price of the object recognized. From the last ViewController I can press a button to pay the objects I selected by using the AR. Now when I press this button the app close this ViewController and go back to the first ViewController, but the array in which I stored the object that the AR recognized it's full. To delete the content of this array I thought that the best way is to use the delegation methods, so I made this:
PaymentViewController.h
#import <UIKit/UIKit.h>
#protocol PaymentViewControllerDelegate;
#interface PaymentViewController : UIViewController
#property (strong, nonatomic) IBOutlet UILabel *labelTotal;
- (IBAction)buttonClosePaymentVC:(id)sender;
- (IBAction)buttonPay:(id)sender;
#property(nonatomic,strong)NSString *total;
#property(assign) id<PaymentViewControllerDelegate> delegate;
#end
#protocol PaymentViewControllerDelegate <NSObject>
- (void)cleanReportArray;
#end
PaymentViewController.m
#import "PaymentViewController.h"
#interface PaymentViewController () <UIAlertViewDelegate>
#end
#implementation PaymentViewController
#synthesize delegate = _delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.labelTotal.text = self.total;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)buttonClosePaymentVC:(id)sender {
[self dismissViewControllerAnimated:YES completion:nil];
}
- (IBAction)buttonPay:(id)sender {
NSString *pay = [NSString stringWithFormat:#"Stai per pagare %#, procedi?", self.total];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"HelloMS" message:pay delegate:self cancelButtonTitle:#"Si" otherButtonTitles:#"No", nil];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
// Procedura per il pagamento e cancellazione del file plist
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:#"objects.plist"];
NSError *error;
if (![[NSFileManager defaultManager]removeItemAtPath:path error:&error]) {
NSLog(#"Errore: %#", error);
}
__weak UIViewController *vcThatPresentedCurrent = self.presentingViewController;
[self dismissViewControllerAnimated:YES completion:^{
[vcThatPresentedCurrent dismissViewControllerAnimated:YES completion:nil];
}];
[self.delegate cleanReportArray];
}
if (buttonIndex == 1) {
// Non deve far nulla: fa scomparire l'UIAlertView
}
}
Here I post to you the method of the class that will use the delegate:
Interface of the ScannerViewController.m
#interface ScannerViewController () <MSScannerSessionDelegate, PaymentViewControllerDelegate, UIActionSheetDelegate, UIAlertViewDelegate>
#property (weak) IBOutlet UIView *videoPreview;
- (IBAction)stopScanner:(id)sender;
#end
In ViewDidLoad I inserted this rows:
PaymentViewController *pay = [[PaymentViewController alloc]init];
[pay setDelegate:self];
And in the ScannerViewController.m I implemented the method I declared in PaymentViewController.h:
- (void)cleanReportArray {
[arrayObjectAdded removeAllObjects];
}
I tested my app on my iPhone, the app works fine until I try to pay the objects I scanned by camera, indeed, I tried to pay the object, but it doesn't clean the array in which I stored the objects scanned.
What's wrong in my code? I used an tutorial on the web to understand better how the delegation method works. I hope you can help me to fix this issue, thank you
UPDATE:
here i will post my ScannerViewController code:
ScannerViewController.h
#import <UIKit/UIKit.h>
#interface ScannerViewController : UIViewController
#end
ScannerViewController.m
#import "ScannerViewController.h"
#import "PaymentViewController.h"
#import "ReportViewController.h"
#import "MSScannerSession.h"
#import "MSResult.h"
#import "XmlReader.h"
static int kMSScanOptions = MS_RESULT_TYPE_IMAGE |
MS_RESULT_TYPE_EAN8 |
MS_RESULT_TYPE_EAN13;
#interface ScannerViewController () <MSScannerSessionDelegate, PaymentViewControllerDelegate, UIActionSheetDelegate, UIAlertViewDelegate>
#property (weak) IBOutlet UIView *videoPreview;
- (IBAction)stopScanner:(id)sender;
#end
#implementation ScannerViewController {
MSScannerSession *_scannerSession;
NSString *nameOfObjectScanned;
XmlReader *reader;
NSMutableArray *arrayObjectAdded;
}
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
_scannerSession = [[MSScannerSession alloc] initWithScanner:[MSScanner sharedInstance]];
[_scannerSession setScanOptions:kMSScanOptions];
[_scannerSession setDelegate:self];
}
return self;
}
- (void)session:(MSScannerSession *)scanner didScan:(MSResult *)result {
if (!result) {
return;
}
[_scannerSession pause];
NSString *resultStr = nil;
if (result) {
switch ([result getType]) {
case MS_RESULT_TYPE_IMAGE:
resultStr = [NSString stringWithFormat:#"Immagine trovata: %#", [result getValue]];
break;
case MS_RESULT_TYPE_EAN8:
case MS_RESULT_TYPE_EAN13:
resultStr = [NSString stringWithFormat:#"EAN trovato: %#", [result getValue]];
break;
default:
break;
}
}
dispatch_async(dispatch_get_main_queue(), ^{
UIActionSheet *asView = [[UIActionSheet alloc]initWithTitle:resultStr delegate:self cancelButtonTitle:#"OK" destructiveButtonTitle:nil otherButtonTitles:nil, nil];
asView.actionSheetStyle = UIActionSheetStyleBlackTranslucent;
[asView showInView:self.view];
[self addObjectToList:resultStr];
});
}
- (void)addObjectToList:(NSString *)objectName {
// Ricerca dell'oggetto
NSString *object = [objectName substringFromIndex:18];
if ([object isEqualToString:#"Binario_con_coppia"]) {
[self showAlert:object];
}
if ([object isEqualToString:#"Dadi_colorati"]) {
[self showAlert:object];
}
if ([object isEqualToString:#"Dadi_rossi"]) {
[self showAlert:object];
}
if ([object isEqualToString:#"Bici_da_corsa"]) {
[self showAlert:object];
}
}
- (void)showAlert:(NSString*)name {
name = [name stringByReplacingOccurrencesOfString:#"_" withString:#" "];
nameOfObjectScanned = name;
NSString *message = [NSString stringWithFormat:#"Ho riconosciuto questo oggetto: %#, vuoi aggiungerlo al carrello?", name];
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:#"HelloMS" message:message delegate:self cancelButtonTitle:#"Aggiungi" otherButtonTitles:#"Annulla", nil];
[alert show];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex {
if (buttonIndex == 0) {
NSLog(#"Aggiungi");
for (int i = 0; i < [reader.objArray count]; i++) {
if ([[reader.objArray[i]objectForKey:#"name"] isEqualToString:nameOfObjectScanned]) {
// Salvo il nome dell'oggetto trovato, il prezzo e la descrizione
NSString *name = [reader.objArray[i]objectForKey:#"name"];
NSString *desc = [reader.objArray[i]objectForKey:#"desc"];
NSString *price = [reader.objArray[i]objectForKey:#"price"];
NSDictionary *newObjectAdded = [[NSDictionary alloc]init];
newObjectAdded = #{#"name": name,
#"desc": desc,
#"price": price};
[arrayObjectAdded addObject:newObjectAdded];
}
}
} else {
NSLog(#"Annulla");
}
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex {
[_scannerSession resume];
}
- (void)viewDidLoad
{
[super viewDidLoad];
arrayObjectAdded = [[NSMutableArray alloc]init];
CALayer *videoPreviewLayer = [self.videoPreview layer];
[videoPreviewLayer setMasksToBounds:YES];
CALayer *captureLayer = [_scannerSession previewLayer];
[captureLayer setFrame:[self.videoPreview bounds]];
[videoPreviewLayer insertSublayer:captureLayer below:[[videoPreviewLayer sublayers] objectAtIndex:0]];
reader = [[XmlReader alloc]init];
[reader parseXml];
[_scannerSession startCapture];
PaymentViewController *pay = [[PaymentViewController alloc]init];
[pay setDelegate:self];
}
- (void)cleanReportArray {
[arrayObjectAdded removeAllObjects];
}
- (void)dealloc {
[_scannerSession stopCapture];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)stopScanner:(id)sender {
ReportViewController *reportVC = [[ReportViewController alloc]initWithNibName:#"ReportViewController" bundle:nil];
reportVC.reportArray = arrayObjectAdded;
[reportVC setModalTransitionStyle:UIModalTransitionStyleFlipHorizontal];
[self presentViewController:reportVC animated:YES completion:nil];
}
#end
To recognize picture I'm using this AR SDK. I hope you can help me to understand where's my issue
Your problem is that in viewDidLoad you have the code:
PaymentViewController *pay = [[PaymentViewController alloc]init];
[pay setDelegate:self];
this is the last thing you do in that method. So the instance of PaymentViewController that you create and set the delegate on is immediately destroyed (by ARC).
You need to modify your code so that you call setDelegate: on the actual instance of PaymentViewController that is presented on screen as this is the instance that needs to use the delegate (it receives the callback from the alert view).
I finally got my leaderboard to show up. Now I just need to implement that my score will pop up.
My score is saved as an NSString in NSUserDefaults under the name score.
Here is some code:
Game_CenterViewController.h
#import <UIKit/UIKit.h>
#import <GameKit/GameKit.h>
#import "GameCenterManager.h"
#class GameCenterManager;
#interface Game_CenterViewController : UIViewController <UIActionSheetDelegate, GKLeaderboardViewControllerDelegate, GKAchievementViewControllerDelegate, GameCenterManagerDelegate> {
GameCenterManager *gameCenterManager;
int64_t currentScore;
NSString *currentLeaderBoard;
}
#property (nonatomic, retain) GameCenterManager *gameCenterManager;
#property (nonatomic, assign) int64_t currentScore;
#property (nonatomic, retain) NSString* currentLeaderBoard;
#end
Game_CenterViewController.m
#import "Game_CenterViewController.h"
#import "AppSpecificValues.h"
#import "GameCenterManager.h"
#implementation Game_CenterViewController
#synthesize gameCenterManager;
#synthesize currentScore;
#synthesize currentLeaderBoard;
- (void)dealloc {
[gameCenterManager release];
[currentLeaderBoard release];
[currentScoreLabel release];
[super dealloc];
}
#pragma mark - View lifecycle
- (void)viewDidLoad {
[super viewDidLoad];
self.currentLeaderBoard = thescore101;
self.currentScore = score
if ([GameCenterManager isGameCenterAvailable]) {
self.gameCenterManager = [[[GameCenterManager alloc] init] autorelease];
[self.gameCenterManager setDelegate:self];
[self.gameCenterManager authenticateLocalUser];
} else {
// The current device does not support Game Center.
}
}
- (void)leaderboardViewControllerDidFinish:(GKLeaderboardViewController *)viewController {
[self dismissModalViewControllerAnimated: YES];
[viewController release];
}
- (void)viewDidUnload {
[super viewDidUnload];
// Release any retained subviews of the main view.
// e.g. self.myOutlet = nil;
self.gameCenterManager = nil;
self.currentLeaderBoard = nil;
}
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
// Return YES for supported orientations
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
#end
The current score is where I'm trying to put the NSString in.
EDITED: I think it would be better to use int for the currentScore.
Is this what you are looking for?
- (void)submitMyScore:(int64_t)score
{
GKScore *myScoreValue = [[[GKScore alloc] initWithCategory:#"yourCat"] autorelease];
myScoreValue.value = (int)score;
[myScoreValue reportScoreWithCompletionHandler:^(NSError *error){
if(error != nil){
NSLog(#"Score Submission Failed");
} else {
NSLog(#"Score Submitted: %d",(int)score);
}
}];
}
So you should add a IBAction
- (IBAction)buttonPressed
{
[self submitMyScore:currentScore];
}
With this and connecting the SEND MY SCORE button to this IBAction, you will have your score submitted.
I hope this to be useful for you.
I have started exploring the Dropbox API for an app that I have where I would like the user to be able to back up the database file. The problem I have run into is that after the user links the app with their account (similar to logging in via Facebook) the app doesn't return to the foreground. When I manually go back to the app it is still on the backups screen, but the account has not been linked (as best as I can tell) and the handleOpenUrl app delegate method is not called.
Any ideas? or maybe someone knows a good tutorial for this. The sample Dropbox app works fine, and I'm doing my best to use it as a guide but obviously i've messed something up.
App Delegate:
#import "AppDelegate_iPad.h"
#import <DropboxSDK/DropboxSDK.h>
#interface AppDelegate_iPad () <DBSessionDelegate>
#end
#implementation AppDelegate_iPad
#synthesize window,viewController;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.viewController = [[mainMenuViewController alloc]init];
[window addSubview:viewController.view]; //< this is a main menu viewcontroller for my app
[self.window makeKeyAndVisible];
// Set these variables before launching the app
NSString* appKey = #"XXXX";
NSString* appSecret = #"XXX";
NSString *root = kDBRootAppFolder;
NSString* errorMsg = nil;
if ([appKey rangeOfCharacterFromSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]].location != NSNotFound) {
errorMsg = #"Make sure you set the app key correctly in DBRouletteAppDelegate.m";
} else if ([appSecret rangeOfCharacterFromSet:[[NSCharacterSet alphanumericCharacterSet] invertedSet]].location != NSNotFound) {
errorMsg = #"Make sure you set the app secret correctly in DBRouletteAppDelegate.m";
} else if ([root length] == 0) {
errorMsg = #"Set your root to use either App Folder of full Dropbox";
} else {
NSString *plistPath = [[NSBundle mainBundle] pathForResource:#"Info" ofType:#"plist"];
NSData *plistData = [NSData dataWithContentsOfFile:plistPath];
NSDictionary *loadedPlist =
[NSPropertyListSerialization
propertyListFromData:plistData mutabilityOption:0 format:NULL errorDescription:NULL];
NSString *scheme = [[[[loadedPlist objectForKey:#"CFBundleURLTypes"] objectAtIndex:0] objectForKey:#"CFBundleURLSchemes"] objectAtIndex:0];
if ([scheme isEqual:#"db-APP_KEY"]) {
errorMsg = #"Set your URL scheme correctly in DBRoulette-Info.plist";
}
}
DBSession* session =
[[DBSession alloc] initWithAppKey:appKey appSecret:appSecret root:root];
session.delegate = self; // DBSessionDelegate methods allow you to handle re-authenticating
[DBSession setSharedSession:session];
[session release];
if (errorMsg != nil) {
[[[[UIAlertView alloc]
initWithTitle:#"Error Configuring Session" message:errorMsg
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil]
autorelease]
show];
}
NSURL *launchURL = [launchOptions objectForKey:UIApplicationLaunchOptionsURLKey];
NSInteger majorVersion =
[[[[[UIDevice currentDevice] systemVersion] componentsSeparatedByString:#"."] objectAtIndex:0] integerValue];
if (launchURL && majorVersion < 4) {
// Pre-iOS 4.0 won't call application:handleOpenURL; this code is only needed if you support
// iOS versions 3.2 or below
[self application:application handleOpenURL:launchURL];
return NO;
}
return YES;
}
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url { /// this is never called
if ([[DBSession sharedSession] handleOpenURL:url]) {
if ([[DBSession sharedSession] isLinked]) {
NSLog(#"App linked successfully!");
// At this point you can start making API calls
}
return YES;
}
return NO;
}
#end
From the main Menu, the user pressed a backup button and that opens the following view controller:
#import "BackupManagerViewController.h"
#import <DropboxSDK/DropboxSDK.h>
#import <stdlib.h>
#interface BackupManagerViewController () <DBRestClientDelegate>
//#property (nonatomic, readonly) DBRestClient* restClient;
#end
#implementation BackupManagerViewController
#synthesize itemsArray,delegate;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
}
return self;
}
#pragma mark - View lifecycle
- (void)viewDidLoad
{
//[super viewDidLoad];
// Do any additional setup after loading the view from its nib.
}
-(BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)orientation
{
return (orientation != UIDeviceOrientationLandscapeLeft) &&
(orientation != UIDeviceOrientationLandscapeRight);
}
- (IBAction)didPressLink {
if (![[DBSession sharedSession] isLinked]) {
[[DBSession sharedSession] link];
} else {
[[DBSession sharedSession] unlinkAll];
[[[[UIAlertView alloc]
initWithTitle:#"Account Unlinked!" message:#"Your dropbox account has been unlinked"
delegate:nil cancelButtonTitle:#"OK" otherButtonTitles:nil]
autorelease]
show];
}
}
-(DBRestClient *)restClient{
if (restClient == nil) {
restClient = [[DBRestClient alloc]initWithSession:[DBSession sharedSession]];
restClient.delegate = self;
}
return restClient;
}
-(IBAction) closeButtonPressed {
[delegate closeBackupManager];
}
#end
Things to check are
Make sure you don't have two applications with same db-APP_KEY
Make sure only one of these is implemented (not both) in your application delegate.
(a)
- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation
(b)
- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
Option (b) is deprecated so please go with the option (a) in your new applications
You have entered correct APP_KEY in the URL scheme .
I ran into the same problem, but got it working after deleting the sample app DBRoulette from the simulator. I also deleted my own app and restarted the simulator, but I am not sure if those steps were necessary.
Did you add the drop box URL schema to your app's info.plist?
I believe this problem had to do with running in the simulator. I ran it on a device and it worked fine.