Trouble in Simple app for iOS - iphone

I have a problem. I have 2 classes "Rating" (with .h and .m), "RatingViewController" (with .h and .m).
Rating.h
#import
#interface Rating : NSObject {
int usrLyrics;
int usrMusic;
int usrTotal;
}
- (void) setUsrTotal;
#end
Rating.m
#import "Rating.h"
#implementation Rating
-(void) incUsrLyrics
{
usrLyrics = 5;
}
- (void) incUsrMusic {
usrMusic = 6;
}
- (void) setUsrTotal {
usrTotal = usrMusic + usrLyrics;
}
}
#end
RatingViewController.h
#interface RatingItudeViewController : UIViewController {
Rating *rating;
}
- (IBAction) submitRating;
RatingViewController.m
#import "RatingItudeViewController.h"
#implementation RatingItudeViewController
- (IBAction) submitRating {
[rating setUsrTotal];
NSLog(#"usrTotal is %i", [rating usrTotal]);
}
#end
It's looks simple, but doesn't work, in Console always "usrTotal is 0".
Help me please.
UPDATED
Just now, I add couple lines in RatingViewController.m
- (IBAction) submitRating {
[rating incUsrMusic];
[rating incUsrLyrics];
[rating setUsrTotal];
NSLog(#"usrTotal is %d", [rating usrTotal]);
}
and in Rating.h
-(void) incUsrLyrics;
- (void) incUsrMusic;
- (void) setUsrTotal;
- (int) usrTotal;
And when a press a button, in console again "usrTotal is 0".

That is correct, you need to put initialization of usrMusic and usrLyrics variables into init constructor message. By default they are assigned values of 0. 0+0 is 0, hence the result.

The methods incUsrLyrics and incUsrMusic don't ever get called anywhere, thus never setting their initial values. If these values are essential to the operation of the class then they should be established in that class's initializer.
In Rating.m
- (id)init
{
if (self = [super init])
{
usrLyrics = 5;
usrMusic = 6;
}
return self;
}
or better yet, a more specific initializer...
- (id)initWithUserLyrics:(NSInteger)lyricsValue music:(NSInteger)musicValue
{
if (self = [super init])
{
usrLyrics = lyricsValue;
usrMusic = musicValue;
}
return self;
}

Related

iPhone SDK - Converting my delegate based function to blocks

I have a very simple class (currently used as a testing class), which uses delegate/protocol methods to interface with it's parent class. However, I would really like to convert this to use blocks. Yet I can't find a good resource or tutorial out there to help me figure out how to do this. All the blocks tutorials are just way to complicated, and I would really just like a small, concise example of how to do this.
I currently have the class:
#import <Foundation/Foundation.h>
#protocol TestObjectDelegate <NSObject>
#optional
-(void)testObjectSucceeded:(BOOL)passedTest;
-(void)testObjectedFailed:(NSError *)error;
#end
#interface TestObject : NSObject {
id<TestObjectDelegate> _delegate;
}
-(void)compare:(NSString *)stringA with:(NSString *)stringB;
#end
#import "TestObject.h"
#implementation TestObject
- (id)initWithDelegateController:(id<TestObjectDelegate>)delegate {
self = [super init];
if (self) {
_delegate = delegate;
}
return self;
}
-(void)compare:(NSString *)stringA with:(NSString *)stringB {
if ([stringA isEqualToString:stringB]) {
if(_delegate && [_delegate respondsToSelector:#selector(testObjectSucceeded:)]) {
[_delegate testObjectSucceeded:YES];
}
else {
[_delegate testObjectSucceeded:NO];
}
}
else {
if(_delegate && [_delegate respondsToSelector:#selector(testObjectedFailed:)]) {
[_delegate testObjectedFailed:nil];
}
}
}
#end
How could I begin to convert this to a blocks based function? Also, I know 'retain cycles' are something to watch out for when implementing a blocks function. What would I need to watch out for when converting this class to use blocks instead of delegate/protocols? Googling 'retain cycles' also gives some overly complicated answers.
Any starting pointers would be much appreciated?
Maybe this example gives you an idea:
typedef void (^MyCallbackBlock)(BOOL);
#interface TestObject : NSObject {
}
#property (nonatomic, copy) MyCallbackBlock myBlock;
#end
#import "TestObject.h"
#implementation TestObject
-(void) yourMethod
{
...
self.myBlock(YES); // call block with argument
...
}
- (void)dealloc
{
[myBlock release];
myBlock = nil;
[super dealloc];
}
#end
When using the object you can then define the block like this:
TestObject* theTestObject = [[TestObject alloc] init];
theTestObject.myBlock = ^(BOOL theParameter){
NSLog(#"foo");
};

Why wont my singleton property autocomplete?

Anyidea why autocomplete does not work on the spaceScene property?
#import <Foundation/Foundation.h>
#import "cocos2d.h"
#class SpaceScene;
#interface SpaceSceneSingleton : NSObject
{
SpaceScene *spaceScene;
}
#property (assign) SpaceScene *spaceScene;
+(SpaceSceneSingleton*)sharedSpaceSceneSingleton;
-(void) addChildToSceneWith:(CCNode *) node andWithZindex: (int) zIndex;
-(void) runAction:(CCAction*) action;
-(void) setTouchIsEnabled:(BOOL) isEnabled;
-(void) removeChild: (CCNode *) child;
#end
#import "SpaceSceneSingleton.h"
#implementation SpaceSceneSingleton
#synthesize spaceScene;
static SpaceSceneSingleton* _sharedSpaceSceneSingleton = nil;
+(SpaceSceneSingleton*)sharedSpaceSceneSingleton;
{
#synchronized([SpaceSceneSingleton class])
{
if (!_sharedSpaceSceneSingleton)
[[self alloc] init];
return _sharedSpaceSceneSingleton;
}
return nil;
}
+(id)alloc
{
#synchronized([SpaceSceneSingleton class])
{
NSAssert(_sharedSpaceSceneSingleton == nil, #"Attempted to allocate a second instance of a singleton.");
_sharedSpaceSceneSingleton = [super alloc];
return _sharedSpaceSceneSingleton;
}
return nil;
}
-(id)init {
self = [super init];
if (self != nil) {
// initialize stuff here
}
return self;
}
-(void) addChildToSceneWith:(CCNode *) node andWithZindex: (int) zIndex
{
[self.spaceScene addChild:node z:zIndex];
}
-(void) runAction:(CCAction*) action
{
//[self.spaceScene add
}
-(void) setTouchIsEnabled:(BOOL) isEnabled
{
}
-(void) removeChild: (CCNode *) child
{
}
#end
You only declared #class SpaceScene; so within this scope nothing more is known than that a class called SpaceScene might exist. Maybe importing SpaceScene.h helps.
I would even say this should compile with warnings. Does it?

How to add up a value when a button pressed

Last time I have asked how to add up a value when a button is pressed within the method of
-(IBAction)addTap:(id)sender;
now I was taught to use tapCount++; (tapCount is a int type variable) to add 1 everytime the button was pressed.
However, I find that the value stayed the same no matter how many times I pressed it.
I want to make tapCount to be 1 if I press the button once, and make it 2 if I pressed the button twice, and so on.
Can someone tell me how to do this?
Detail:
Lets say I have a class called Player, a member called int tapCount and int result
when each time the button was pressed, a value will be added to tapCount, and the value will be displayed at the end (when the game end lets say)
For now, the value stay the same when I use NSLog to check it.
Player.h
#class TappingViewController;
#interface Player : NSObject {
NSString *name;
int tapCount;
int result;
}
#property (nonatomic, assign) NSString *name;
#property (nonatomic, assign) int tapCount;
#property (nonatomic, assign) int result;
#end
TappingViewController.h
#interface TappingViewController : UIViewController {
}
-(IBAction)addTap:(id)sender;
#end
TappIngViewController.m
#import "TappingViewController.h"
#import "Player.h"
#class Player;
int tapCount;
#implementation TappingViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
/*
- (void)loadView {
}
*/
- (void)viewDidLoad
{
Player *aPlayer = [[Player alloc]init];
NSLog(#"tapCount:%d", aPlayer.tapCount);
[super viewDidLoad];
}
-(IBAction)addTap:(id)sender;
{
NSLog(#"BeforeL %d", tapCount);
tapCount++;
NSLog(#"After: %d", tapCount);
}
/*
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
}
- (void)dealloc {
[super dealloc];
}
#end
In the addTap: method you are referencing the TappingViewController's tapCount which is different to the Player's tapCount, even though they have the same name, they are different. So you need to reference the aPlayer's tapCount property:
aPlayer.tapCount++;
However aPlayer isn't in the addTap: method's scope. The only place you can currently reference aPlayer is in the viewDidLoad method.
This is what you need to change: (you don't need the comments I've added to point out the changes)
TappingViewController.h
#class Player; //**You have imported the Player class in the .m file so if you use the Player class in the header you need to add it as a forward class.
#interface TappingViewController : UIViewController {
Player *aPlayer; //**This is an instance variable (ivar) so you can access it in any method in the implementation (.m file), however you still need to put something in this ivar (see viewDidLoad)**
}
//**You can add a property for aPlayer if you want, but remember to do the memory management properly**
-(IBAction)addTap:(id)sender;
#end
TappIngViewController.m
#import "TappingViewController.h"
#import "Player.h"
//**Get rid of the forward class, as you have imported it above**
//**Get rid of the tapCount that was were**
#implementation TappingViewController
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil {
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
}
return self;
}
/*
- (void)loadView {
}
*/
- (void)viewDidLoad
{
aPlayer = [[Player alloc] init]; //**remove the declaration of a new var**
NSLog(#"tapCount:%d", aPlayer.tapCount);
[super viewDidLoad];
}
-(IBAction)addTap:(id)sender;
{
NSLog(#"BeforeL %d", tapCount);
aPlayer.tapCount++; //**reference the player's tapCount**
NSLog(#"After: %d", tapCount);
}
/*
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation {
return (interfaceOrientation == UIInterfaceOrientationPortrait);
}
*/
- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
}
- (void)viewDidUnload {
}
- (void)dealloc {
[super dealloc];
}
#end
I really don't feel like you're providing enough information to make it possible for us to tell you what's going wrong. That being said, I might be able to point you in the right direction.
First of all I would suggest that you try the following code:
-(IBAction)addTap:(id)sender {
NSLog(#"Before: %d", tapCount);
tapCount++;
NSLog(#"After: %d", tapCount);
}
I added both of them just to show you that incrementing the variable does indeed work.
If you get output that looks like this:
Before: 0
After: 1
Before: 0
After: 1
Before: 0
After: 1
It means that you set tapCount = 0; over and over again.
If you don't get any output it means that your IBAction isn't connected properly.
If you get the expected output, but it's the same when you "NSLog to check it". It means that you've accidentally run tapCount = 0; again.
Another possibility is that there is something wrong with your NSLog.
If you have any questions feel free to ask.
I assuming the IBAction is in your controller. You will need to add the variable to your header. In the controller for example:
Given that you have the tap counter in another class, your controller needs a pointer to that class.
// controller header file
Player *myPlayer;
// controller implementation file
-(void)awakeFromNib {
myPlayer = [Player alloc] init]; // initialized the player
// do whatever else you need to do
// load previous data from NSUserDefaults, maybe
}
-(IBAction)addTap:(id)sender {
myPlayer.tapCount++;
}

How to hide variables for distributed code

So I've built a few apps and am now trying my hand at building a piece of iPhone code that others can drop into their applications. Question is how do I hide the data elements in an object class header file (.h) from the user?
For example, not sure if people have used the medialets iPhone analytics but their .h does not have any data elements defined. It looks like:
#import <UIKit/UIKit.h>
#class CLLocationManager;
#class CLLocation;
#interface FlurryAPI : NSObject {
}
//miscellaneous function calls
#end
With that header file, they also supply an assembly file (.a) that has some data elements in it. How do they maintain those data elements across the life span of the object without declaring them in the .h file?
I am not sure if it matters but the .h file is only used to create a singleton object, not multiple objects of the same class (FlurryAPI).
Any help would be much appreciated. Thanks
Take a look at this:
Hide instance variable from header file in Objective C
In my header file I'd have:
#interface PublicClass : NSObject
{
}
- (void)theInt;
#end
In my source file I'd have:
#interface PrivateClass : PublicClass
{
int theInt;
}
- (id)initPrivate;
#end;
#implementation PublicClass
- (int)theInt
{
return 0; // this won't get called
}
- (id)init
{
[self release];
self = [[PrivateClass alloc] initPrivate];
return self;
}
- (id)initPrivate
{
if ((self = [super init]))
{
}
return self;
}
#end
#implementation PrivateClass
- (int)theInt
{
return theInt; // this will get called
}
- (id)initPrivate
{
if ((self = [super initPrivate]))
{
theInt = 666;
}
return self;
}
#end
I'm using theInt as an example. Add other variables to suit your taste.
I recommend you to use categories to hide methods.
.h
#import <Foundation/Foundation.h>
#interface EncapsulationObject : NSObject {
#private
int value;
NSNumber *num;
}
- (void)display;
#end
.m
#import "EncapsulationObject.h"
#interface EncapsulationObject()
#property (nonatomic) int value;
#property (nonatomic, retain) NSNumber *num;
#end
#implementation EncapsulationObject
#synthesize value;
#synthesize num;
- (id)init {
if ((self == [super init])) {
value = 0;
num = [[NSNumber alloc] initWithInt:10];
}
return self;
}
- (void)display {
NSLog(#"%d, %#", value, num);
}
- (void)dealloc {
[num release];
[super dealloc];
}
#end
You can't access to the private instance variables via dot notation, but you can still get the value by using [anObject num], though the compiler will generate a warning. This is why our apps can get rejected by Apple by calling PRIVATE APIs.

How do I make a custom delegate protocol for a UIView subclass?

I'm making some tabs and I want to have my own delegate for them but when I try to send an action to the delegate nothing happens.
I also tried following this tutorial:
link text
But it doesn't work for me :(
Here is my code:
TiMTabBar.h
#protocol TiMTabBarDelegate;
#interface TiMTabBar : UIView {
id<TiMTabBarDelegate> __delegate;
...
int selectedItem;
...
}
//- (id)init;
- (id)initWithDelegate:(id)aDelegate;
- (void)setSelectedIndex:(int)item;
..
#property (nonatomic) int selectedItem;
#property(assign) id <TiMTabBarDelegate> __delegate;
..
...
#end
#protocol TiMTabBarDelegate<NSObject>
//#optional
- (void)tabBar:(TiMTabBar *)_tabBar didSelectIndex:(int)index;
#end
TiMTabBar.m:
#import "TiMTabBar.h"
...
#interface NSObject (TiMTabBarDelegate)
- (void)tabBar:(TiMTabBar *)_tabBar didSelectIndex:(int)index;
#end
#implementation TiMTabBar
#synthesize selectedItem;
#synthesize __delegate;
...
/*
- (id)init
{
...
return self;
}
*/
- (id)initWithDelegate:(id)aDelegate;
{
//[super init];
__delegate = aDelegate;
return self;
}
- (void)awakeFromNib
{
//[self init];
//[self initWithDelegate:self];
...
}
- (void)setSelectedIndex:(int)item {
selectedItem = item;
if (self.__delegate != NULL && [self.__delegate respondsToSelector:#selector(tabBar:didSelectIndex:)]) {
[__delegate tabBar:self didSelectIndex:selectedItem];
}
...
if (item == 0) {
...
} else if (item == 1) {
...
} else if (item == 2) {
...
} else if (item == 3) {
...
} else if (item == 4) {
...
} else {
...
}
}
/*
- (void)tabBar:(TiMTabBar *)_tabBar didSelectIndex:(int)index;
{
//[delegate tabBar:self didSelectIndex:index];
//if (self.delegate != NULL && [self.delegate respondsToSelector:#selector(tabBar:didSelectIndex:)]) {
//[delegate tabBar:self didSelectIndex:selectedItem];
//}
NSLog(#"tabBarDelegate: %d",index);
}
*/
#end
The delegate only works works inside itself and not in any other files like:
#interface XXXController : UIViewController <TiMTabBarDelegate> {
...
...
IBOutlet TiMTabBar *tabBar;
...
}
...
#end
XXXController.m:
#import "XXXController.h"
#import <QuartzCore/QuartzCore.h>
#implementation XXXController
- (void)viewDidLoad {
[super viewDidLoad];
[self becomeFirstResponder];
...
tabBar = [[TiMTabBar alloc] initWithDelegate:self];
//tabBar.__delegate = self;
...
}
#pragma mark TiMTabBar Stuff
- (void)tabBar:(TiMTabBar *)_tabBar didSelectIndex:(int)index;
{
NSLog(#"Controller/tabBarDelegate: %d",index);
}
#end
None of this seems to work in XXXController. Anyone know how to make this work?
In your XXXController viewDidLoad after you alloc and init a new TiMTabBar are you adding it to the controller's view? If not, perhaps the tab bar in your view that you are clicking on is one loaded from the nib that does not have the delegate set.
It looks like - In awakeFromNib, you are setting the delegate to itself. So whenever you try to send the delegate messages, you are actually sending them to your instance of TiMTabBar, not XXXController.