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....
Related
I have some Realm models in my app that all use a base class. In this class I wrote some generic functions like the one below:
- (void)save {
self.updatedAt = [NSDate date];
[self.realm beginWriteTransaction];
[self.realm addOrUpdateObject:self];
[self.realm commitWriteTransaction];
[[SyncEngine sharedInstance] store:self];
}
Now, I also wrote a class called SyncEngine, which checks if some available synchronization methods are enabled and then calls them:
- (void)store:(id)object {
if ([Preferences CloudKitEnabled]) {
[self.cloudKit store:object];
}
}
This is where my problem arises. I have written a base class called CloudKitManager which has some generic functions. I then create a specific CloudKitClass for every model in my app, so I'll end up with CloudKitRestaurant and CloudKitTable. All of these will contain a function (void)store:(id)sender. What would be the best way to call the store function of a specific CloudKit class, based on the class that is being stored in Realm?
Ideally, I'd like for RLMRestaurant to automatically use CloudKitRestaurant and not have to use and if else or switch statement.
For further clarity, this is how SyncEngine works.
#interface SyncEngine()
#property (nonatomic, strong) CloudKitManager *cloudKitManager;
#end
#implementation SyncEngine
static SyncEngine *sharedInstance = nil;
+ (SyncEngine *)sharedInstance {
if (sharedInstance == nil) {
sharedInstance = [[self alloc] init];
}
return sharedInstance;
}
- (instancetype)init {
self = [super init];
if (self) {
self.cloudKitManager = [[CloudKitManager alloc] init];
}
return self;
}
#end
In my opinion, you should keep type of CloudKitManager class inside RLMBase object. And when you need to call [[CloudKitManager sharedInstance] store:object], call [[object.cloudKitClass sharedInstance] store:object].
Try my code below.
#interface RLMBase : NSObject
- (Class)cloudKitClass;
#end
#implementation RLMBase
- (Class)cloudKitClass {
// Must be overridden in subclass.
return CloudKitManager.class;
}
#end
#interface RLMRestaurant : RLMBase
#end
#implementation RLMRestaurant
- (Class)cloudKitClass {
return CloudKitRestaurant.class;
}
#end
- (void)store:(RLMBase *)object {
if ([Preferences CloudKitEnabled]) {
[[object.cloudKitClass sharedInstance] store:object];
}
}
ANOTHER WAY
Put store: method from SyncEngine to RLMBase object.
#interface RLMBase : NSObject
- (Class)cloudKitClass;
- (void)store;
#end
#implementation RLMBase
- (Class)cloudKitClass {
// Must be overridden in subclass.
return CloudKitManager.class;
}
- (void)store {
if ([Preferences CloudKitEnabled]) {
[[self.cloudKitClass sharedInstance] store:self];
}
}
#end
And save method will become
- (void)save {
self.updatedAt = [NSDate date];
[self.realm beginWriteTransaction];
[self.realm addOrUpdateObject:self];
[self.realm commitWriteTransaction];
[self store];
}
I am in the middle of an app re-design and am refactoring and extending my model.
One aspect of my apps model is that the app retrieves data from a web service and populates the model.
My question is: Should my model objects have the capability to implement NSURLSession or should I rely on the VC to provide the connection?
I'm asking from a best practices standpoint. What's the best way to think about this? Should the model be totally on its own or should it have network access?
One consideration is that these model objects are essentially useless without data from the network, meaning data from the Internet is a fundamental aspect of their existence.
If we take SOLID — especially the S for Single Responsible Principle — in account, it becomes obvious, that neither the VC nor the model should do the networking:
a VC's single responsible would be to handle views
the model's purpose would be to hold data
networking should be done by a third class, a networking controller.
This three points will fulfill SOLID, but how do you get data from the network into model objects show on a view?
Well, this depends on your overall architectural design on the app, but a common approach would be to use callback — either a delegate protocol or a block — with your network controller.
You create a network controller in the app delegate and pass it from view controller to view controller via properties to any place in the app were newly fetched data is needed. I wouldn't use a singleton here, as that violates O, I & D of SOLID.
Add a class method to your model +(NSArray *)modelObjectsFromDictionaries:(NSArray *) or similar.
In the view controller you can now do
-(void)viewDidLoad
{
[super viewDidLoad];
__weak typeof(self) weakSelf = self;
[self.networkController fetchModels:^(NSArray *modelDictionaries, NSError *error){
typeof(weakSelf) self = weakSelf;
if(self) {
if(!error){
[self.dataSource addOrUpdateData:[Model modelObjectsFromDictionaries:modelDictionaries]];
} else {
// error handling
}
}
}];
}
This is just a starting point. For more complicated APIs it might be useful to use an api controller that itself uses the networking controller and maybe a persistence controller.
Although instead of a Model class method you might want to use some sort of mapping and abstract factory pattern… But all this things would require more information about your app and are out of the scope for this question.
Update:
I created a sample project to demonstrate this.
It is slightly different than what I say above:
As it uses a table view, I am using a data source class to populate it. Instead of the view controller the data source will tell the network controller to fetch new data.
I am using OFAPopulator for this, a library written by me to populate table views and collection views in a SOLID-conform fashion, or to «Keep view controllers clean and MVC smart».
#import "AppDelegate.h"
#import "VSNetworkController.h"
#implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
[self.window.rootViewController setValue:[[VSNetworkController alloc] initWithBaseURL:[NSURL URLWithString:#"http://api.goeuro.com/api/v2/"]]
forKey:#"networkController"];
return YES;
}
#end
// VSNetworkController.h
#import <Foundation/Foundation.h>
#interface VSNetworkController : NSObject
-(instancetype)initWithBaseURL:(NSURL *) baseURL;
-(void)suggestionsForString:(NSString *)suggestionString
responseHandler:(void(^)(id responseObj, NSError *error))responseHandler;
#end
// VSNetworkController.m
#import "VSNetworkController.h"
#interface VSNetworkController ()
#property (nonatomic, strong) NSURL *baseURL;
#end
#implementation VSNetworkController
-(instancetype)initWithBaseURL:(NSURL *)baseURL
{
self = [super init];
if (self) {
_baseURL = baseURL;
}
return self;
}
-(void)suggestionsForString:(NSString *)suggestionString
responseHandler:(void(^)(id responseObj, NSError *error))responseHandler
{
NSURL *url = [self.baseURL URLByAppendingPathComponent:[NSString stringWithFormat:#"position/suggest/en/%#", suggestionString]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request
queue:[NSOperationQueue mainQueue]
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *connectionError) {
responseHandler([NSJSONSerialization JSONObjectWithData:data options:0 error:nil], connectionError);
}];
}
#end
// VSLocationSuggestion.h
#import <Foundation/Foundation.h>
#import CoreLocation;
#interface VSLocationSuggestion : NSObject
#property (nonatomic, copy, readonly) NSString *name;
#property (nonatomic, copy, readonly) NSString *country;
#property (nonatomic, strong, readonly) CLLocation *position;
+(NSArray *)suggestionsFromDictionaries:(NSArray *)dictionaries;
#end
// VSLocationSuggestion.m
#import "VSLocationSuggestion.h"
#interface VSLocationSuggestion ()
#property (nonatomic, copy) NSString *name;
#property (nonatomic, copy) NSString *country;
#property (nonatomic, strong) CLLocation *position;
#end
#implementation VSLocationSuggestion
+(NSArray *)suggestionsFromDictionaries:(NSArray *)dictionaries
{
NSMutableArray *array = [#[] mutableCopy];
[dictionaries enumerateObjectsUsingBlock:^(NSDictionary *suggestionDict, NSUInteger idx, BOOL *stop) {
[array addObject:[[self alloc] initWithDictionary:suggestionDict]];
}];
return [array copy];
}
-(instancetype)initWithDictionary:(NSDictionary *)dict
{
self = [super init];
if (self) {
_name = dict[#"name"];
_country = dict[#"country"];
CLLocationDegrees latitude = [dict[#"geo_position"][#"latitude"] doubleValue];
CLLocationDegrees longitude =[dict[#"geo_position"][#"longitude"] doubleValue];
_position = [[CLLocation alloc] initWithLatitude:latitude longitude:longitude];
}
return self;
}
#end
// VSSuggestionDataSource.h
#import <Foundation/Foundation.h>
#import <OFADataProvider.h>
#class VSNetworkController;
#interface VSSuggestionDataSource : NSObject <OFADataProvider>
-(instancetype)initWithNetworkController:(VSNetworkController *)networkController;
-(void)setNewSuggestions:(NSArray *)suggetsions;
-(void)enteredStringForSuggestions:(NSString *)suggestionString;
#end
// VSSuggestionDataSource.m
#import "VSSuggestionDataSource.h"
#import "VSNetworkController.h"
#import "VSLocationSuggestion.h"
#interface VSSuggestionDataSource ()
#property (nonatomic, copy) void (^available)(void);
#property (nonatomic, strong) VSNetworkController *networkController;
#end
#implementation VSSuggestionDataSource
#synthesize sectionObjects;
-(instancetype)initWithNetworkController:(VSNetworkController *)networkController
{
self = [super init];
if (self) {
_networkController = networkController;
}
return self;
}
-(void)dataAvailable:(void (^)(void))available
{
_available = available;
}
-(void)setNewSuggestions:(NSArray *)suggetsions
{
self.sectionObjects = suggetsions;
self.available();
}
-(void)enteredStringForSuggestions:(NSString *)s
{
__weak typeof(self) weakSelf = self;
[self.networkController suggestionsForString:s responseHandler:^(NSArray *responseObj, NSError *error) {
typeof(weakSelf) self = weakSelf;
if (self) {
if (!error && responseObj) {
NSArray *suggestion = [VSLocationSuggestion suggestionsFromDictionaries:responseObj];
[self setNewSuggestions:suggestion];
}
}
}];
}
#end
// ViewController.h
#import <UIKit/UIKit.h>
#class VSNetworkController;
#interface ViewController : UIViewController
#property (nonatomic, strong) VSNetworkController *networkController;
#end
// ViewController.m
#import "ViewController.h"
#import "VSLocationSuggestion.h"
#import <OFAViewPopulator.h>
#import <OFASectionPopulator.h>
#import "VSSuggestionDataSource.h"
#interface ViewController ()
#property (weak, nonatomic) IBOutlet UITableView *tableView;
#property (strong, nonatomic) OFAViewPopulator *viewPopultor;
#property (strong, nonatomic) VSSuggestionDataSource *dataSource;
- (IBAction)textChanged:(UITextField *)sender;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.dataSource = [[VSSuggestionDataSource alloc] initWithNetworkController:self.networkController];
OFASectionPopulator *sectionPopulator = [[OFASectionPopulator alloc] initWithParentView:self.tableView
dataProvider:self.dataSource
cellIdentifier:^NSString *(id obj, NSIndexPath *indexPath) {
return #"Cell";
} cellConfigurator:^(VSLocationSuggestion *obj, UITableViewCell *cell, NSIndexPath *indexPath) {
cell.textLabel.text = obj.name;
}];
sectionPopulator.objectOnCellSelected = ^(VSLocationSuggestion *suggestion, UIView *cell, NSIndexPath *indexPath ){
NSString * string =[NSString stringWithFormat:#"%#, %# (%f %f)", suggestion.name, suggestion.country, suggestion.position.coordinate.latitude, suggestion.position.coordinate.longitude];
UIAlertController *avc = [UIAlertController alertControllerWithTitle:#"Selected" message:string preferredStyle:UIAlertControllerStyleAlert];
UIAlertAction *cancelAction = [UIAlertAction
actionWithTitle:NSLocalizedString(#"Cancel", #"Cancel action")
style:UIAlertActionStyleCancel
handler:^(UIAlertAction *action)
{
;
}];
[avc addAction:cancelAction];
[self presentViewController:avc animated:YES completion:NULL];
};
self.viewPopultor = [[OFAViewPopulator alloc] initWithSectionPopulators:#[sectionPopulator]];
}
- (IBAction)textChanged:(UITextField *)sender
{
NSString *s = sender.text;
if ([s length]) {
[self.dataSource enteredStringForSuggestions:s];
}
}
#end;
I made this code available on github: https://github.com/vikingosegundo/LocationSugesstion
I actually try to figure out how inheritance in Objective-C does work. My problem is, that my obj. allways returns "null".
Here is my Code:
Edit: Added rest of code.
// ReportViewController.h
#import <UIKit/UIKit.h>
#import <MessageUI/MessageUI.h>
#import "IAPHelper.h"
#class Report, Category, GADBannerView;
#interface ReportViewController : UIViewController <UIWebViewDelegate,
NSFetchedResultsControllerDelegate> {NSString* _werbung;}
#property (nonatomic, strong) GADBannerView *bannerView;
#property (nonatomic, retain) NSString* werbung;
- (id)initWithReport:(Report *)report category:(Category *)category ;
#end
// ReportViewController.m
#import "ReportViewController.h"
#import "IAPHelper.h"
#interface ReportViewController ()
- (void)loadReport;
- (void)setupFetchRequest;
- (void)resizeNavigationContentViewToHeight:(CGFloat)height;
- (NSString*) werbung;
- (void)setWerbung:(NSString *)newwerbung;
#end
#implementation ReportViewController
#synthesize werbung = _werbung;
-(NSString*) werbung {
return _werbung;
}
- (void)setWerbung:(NSString *)newwerbung {
_werbung= newwerbung;
}
//Werbung ausblenden
NSLog(#"Check for bought products");
if ([_werbung isEqual: #"gekauft"]) {
self.bannerView.hidden = TRUE;
}
- (void)viewDidLoad
{
[super viewDidLoad];
if ([[[UIDevice currentDevice] systemVersion] floatValue] >= 7.0)
{
self.edgesForExtendedLayout=UIRectEdgeNone;
self.navigationController.navigationBar.translucent = NO;
}
//ADMob
if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) {
if([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationPortrait) {
_bannerView = [[GADBannerView alloc] initWithFrame: CGRectMake(20.0,850.0,728,90 )];}
if([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeRight) {
_bannerView = [[GADBannerView alloc] initWithFrame: CGRectMake(-10,615.0,728,90 )];}
if([UIApplication sharedApplication].statusBarOrientation == UIInterfaceOrientationLandscapeLeft) {
_bannerView = [[GADBannerView alloc] initWithFrame: CGRectMake(-10,615.0,728,90 )];}
}
else
_bannerView = [[GADBannerView alloc] initWithFrame: CGRectMake(0,410,320,50 )];
//initWithAdSize:kGADAdSizeBanner];
//initwithframe:CGRectMake(0.0,0.0,320,50 )];
self.bannerView.adUnitID = #„xxxxxxxxxxxxxxxxx“;
self.bannerView.rootViewController = self;
GADRequest *request = [GADRequest request];
// Enable test ads on simulators.
[self.view addSubview:(_bannerView)];
request.testDevices = #[ GAD_SIMULATOR_ID, #„xxxxxxxxxxxxxxxxxxxxxxx“ ];
[self.bannerView loadRequest:request];
//Werbung ausblenden
NSLog(#"Check for bought products");
if ([_werbung isEqual: #"gekauft"]) {
self.bannerView.hidden = TRUE;
}
NSLog(#"%#",_werbung);
NSLog(#"%#",self.werbung);
}
// IAPHelper.m
#import "IAPHelper.h"
#import <StoreKit/StoreKit.h>
#import "ReportViewController.h"
#interface IAPHelper () <SKProductsRequestDelegate, SKPaymentTransactionObserver>
#end
#implementation IAPHelper
- (id)initWithProductIdentifiers:(NSSet *)productIdentifiers
{
//self = [super init];
if ((self = [super init])) {
// Store product identifiers
_productIdentifiers = productIdentifiers;
// Check for previously purchased products
_purchasedProductIdentifiers = [NSMutableSet set];
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
for (NSString * productIdentifier in _productIdentifiers) {
BOOL productPurchased = [[NSUserDefaults standardUserDefaults] boolForKey:productIdentifier];
if (productPurchased) {
[_purchasedProductIdentifiers addObject:productIdentifier];
NSLog(#"Previously purchased: %#", productIdentifier);
if ([productIdentifier isEqual:#"XXXXXXXXXXXXXXXXXXXXXXXXXX"]) {
ReportViewController *rvc = [[ReportViewController alloc] init];
rvc.werbung = #"gekauft";
NSLog(#"werbung gekauft!");
NSLog(#"%#", rvc.werbung); <- log's #"gekauft";
} else {
NSLog(#"Not purchased: %#", productIdentifier);
}
}
[[SKPaymentQueue defaultQueue] addTransactionObserver:self];
}}
return self;
}
My question is: What I did wrong? Maybe you got a good tutorial for me too?
EDIT: You were right, it was not about inheritance. My solution is working with UserDefaults.
This isn't a question of inheritance — inheritance governs what behaviour a subclass will acquire from its parent. The issue seems to be one of instances.
ReportViewController is a class. So it's not an actual actor. It's just the description of how any ReportViewControllers that are created will act. Like a constitution.
When you call alloc] init] you create one new instance of the view controller. You then set the advertisement as bought on that instance. You don't put the instance anywhere or otherwise keep hold of it. That instance therefore ceases to exist.
Elsewhere, in a completely different instance, you check the advertisement value. Nobody has told that instance anything. So you see the nil values.
Think of it exactly the same as NSString. In the code below, should stringB change value?
NSMutableString *stringA = [[NSMutableString alloc] init];
NSMutableString *stringB = [[NSMutableString alloc] init];
[stringA appendString:#"Mo' string for ya'"];
The ReportViewController that you're using to set the werbung value is not the same controller where you're checking the value. The one where you're doing the assignment is local to the method where it's being allocated.
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.
This question already has answers here:
How do I create delegates in Objective-C?
(20 answers)
Closed 9 years ago.
On iOS, how do I create a delegate (user defined)?
First define a declare a delegate like this -
#protocol IconDownloaderDelegate;
Then create a delegate object like this -
#interface IconDownloader : NSObject
{
NSIndexPath *indexPathInTableView;
id <IconDownloaderDelegate> delegate;
NSMutableData *activeDownload;
NSURLConnection *imageConnection;
}
Declare a property for it -
#property (nonatomic, assign) id <IconDownloaderDelegate> delegate;
Define it -
#protocol IconDownloaderDelegate
- (void)appImageDidLoad:(NSIndexPath *)indexPath;
#end
Then you can call methods on this delegate -
[delegate appImageDidLoad:self.indexPathInTableView];
Here is the complete source code of the image downloader class -
.h file -
#class AppRecord;
#class RootViewController;
#protocol IconDownloaderDelegate;
#interface IconDownloader : NSObject
{
AppRecord *appRecord;
NSIndexPath *indexPathInTableView;
id <IconDownloaderDelegate> delegate;
NSMutableData *activeDownload;
NSURLConnection *imageConnection;
}
#property (nonatomic, retain) AppRecord *appRecord;
#property (nonatomic, retain) NSIndexPath *indexPathInTableView;
#property (nonatomic, assign) id <IconDownloaderDelegate> delegate;
#property (nonatomic, retain) NSMutableData *activeDownload;
#property (nonatomic, retain) NSURLConnection *imageConnection;
- (void)startDownload;
- (void)cancelDownload;
#end
#protocol IconDownloaderDelegate
- (void)appImageDidLoad:(NSIndexPath *)indexPath;
#end
.m file -
#import "IconDownloader.h"
#import "MixtapeInfo.h"
#define kAppIconHeight 48
#define TMP NSTemporaryDirectory()
#implementation IconDownloader
#synthesize appRecord;
#synthesize indexPathInTableView;
#synthesize delegate;
#synthesize activeDownload;
#synthesize imageConnection;
#pragma mark
- (void)dealloc
{
[appRecord release];
[indexPathInTableView release];
[activeDownload release];
[imageConnection cancel];
[imageConnection release];
[super dealloc];
}
- (void)startDownload
{
self.activeDownload = [NSMutableData data];
// alloc+init and start an NSURLConnection; release on completion/failure
NSURLConnection *conn = [[NSURLConnection alloc] initWithRequest:
[NSURLRequest requestWithURL:
[NSURL URLWithString:appRecord.mixtape_image]] delegate:self];
self.imageConnection = conn;
[conn release];
}
- (void)cancelDownload
{
[self.imageConnection cancel];
self.imageConnection = nil;
self.activeDownload = nil;
}
#pragma mark -
#pragma mark Download support (NSURLConnectionDelegate)
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
[self.activeDownload appendData:data];
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
// Clear the activeDownload property to allow later attempts
self.activeDownload = nil;
// Release the connection now that it's finished
self.imageConnection = nil;
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
// Set appIcon and clear temporary data/image
UIImage *image = [[UIImage alloc] initWithData:self.activeDownload];
self.appRecord.mixtape_image_obj = image;
self.activeDownload = nil;
[image release];
// Release the connection now that it's finished
self.imageConnection = nil;
// call our delegate and tell it that our icon is ready for display
[delegate appImageDidLoad:self.indexPathInTableView];
}
#end
and here is how we use it -
#import "IconDownloader.h"
#interface RootViewController : UITableViewController <UIScrollViewDelegate, IconDownloaderDelegate>
{
NSArray *entries; // the main data model for our UITableView
NSMutableDictionary *imageDownloadsInProgress; // the set of IconDownloader objects for each app
}
in .m file -
- (void)startIconDownload:(AppRecord *)appRecord forIndexPath:(NSIndexPath *)indexPath
{
IconDownloader *iconDownloader = [imageDownloadsInProgress objectForKey:indexPath];
if (iconDownloader == nil)
{
iconDownloader = [[IconDownloader alloc] init];
iconDownloader.appRecord = appRecord;
iconDownloader.indexPathInTableView = indexPath;
iconDownloader.delegate = self;
[imageDownloadsInProgress setObject:iconDownloader forKey:indexPath];
[iconDownloader startDownload];
[iconDownloader release];
}
}
here is delegate gets called automatically -
// called by our ImageDownloader when an icon is ready to be displayed
- (void)appImageDidLoad:(NSIndexPath *)indexPath
{
IconDownloader *iconDownloader = [imageDownloadsInProgress objectForKey:indexPath];
if (iconDownloader != nil)
{
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:iconDownloader.indexPathInTableView];
// Display the newly loaded image
cell.imageView.image = iconDownloader.appRecord.appIcon;
}
}
This is basic concepts to create a own delegate
Delegates are very useful to control transfer within the array of view controllers in app manually. Using delegates you can manage the control flow very well.
here is small example of own delegates....
Create a protocol class.... (.h only)
SampleDelegate.h
#import
#protocol SampleDelegate
#optional
#pragma Home Delegate
-(NSString *)getViewName;
#end
Import above protocol class in the class whom you want to make delegate of another class. Here in my ex. I m using AppDelegate to make delegate of The HomeViewController's Object.
also add above DelegateName in Delegate Reference < >
ownDelegateAppDelegate.h
#import "SampleDelegate.h"
#interface ownDelegateAppDelegate : NSObject <UIApplicationDelegate, SampleDelegate> {
}
ownDelegateAppDelegate.m
//setDelegate of the HomeViewController's object as
[homeViewControllerObject setDelegate:self];
//add this delegate method definition
-(NSString *)getViewName
{
return #"Delegate Called";
}
HomeViewController.h
#import
#import "SampleDelegate.h"
#interface HomeViewController : UIViewController {
id<SampleDelegate>delegate;
}
#property(readwrite , assign) id<SampleDelegate>delegate;
#end
HomeViewController.h
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
UILabel *lblTitle = [[UILabel alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
lblTitle.text = [delegate getViewName];
lblTitle.textAlignment = UITextAlignmentCenter;
[self.view addSubview:lblTitle];
}