How/should I use nested for loops inside of if statements? - objective-c

I was hoping to get some help from someone who is better than me with using Objective C and Xcode.
I am using an example project and trying to figure out exactly what it's asking me to do and how to do it. It is specifically asking me:
STEP 1: Use the if statement below to determine if defaults contains a bool value of "TRUE" for a key called "registered"
This snippet is what I have so far for this problem:
if (self.defaults == YES)
{
[self performSelector:#selector(goToLogin)];
}
The "for" and "if" are both bold in the directions, leading me to believe I need to use both.
Edit: This is more of the surrounding code because of the comments suggesting I didn't upload all of the necessary code.
#import "RegistrationViewController.h"
#interface RegistrationViewController ()
#end
#implementation RegistrationViewController
-(void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[self.navigationController setNavigationBarHidden:TRUE];
}
- (void)viewDidLoad
{
[super viewDidLoad];
self.textFields = [NSArray arrayWithObjects:_emailTextField,_userNameTextField,_passwordTextField,_confirmPasswordText Field, nil];
defaults = [NSUserDefaults standardUserDefaults];
//STEP 1: Use the if statement below to determine if defaults contains a bool value of "TRUE" for a key called "registered"
if (self.defaults == YES)
{
[self performSelector:#selector(goToLogin)];
}
}
I am really new to this and just don't know where to go from here! any help would be very appreciated!
Thanks in advance,
FMM92

It is difficult to tell the precise situation here, but this is how it sounds to me:
defaults is almost certainly meant to be an instance of NSUserDefaults. The bolded "for" in your instructions is not suggesting a for-loop; it's giving you a hint at the method you need to use. Take a look at the NSUserDefaults reference there and see if you can find a method that might be useful for looking up a BOOL value for a named key.

Related

Correct way to reset class values in unit testing with setup

I'm new to Objective-C so please bear with me.
I have a unit test class that looks something like this:
static NSString * const kTestingUserID = #"userID";
#interface UserPreferencesTest
#property(nonatomic) UserPreferences *userPreferences;
#end
#implementation UserPreferencesTest
- (void)setUp {
[super setUp];
self.userPreferences = [[UserPreferences alloc] init];
}
- (void)testEmptyDictionary {
STAssertFalse([self.userPreferences getLockoutStatus:kTestingUserID],
#"An unset username should always return false");
}
- (void)testBlockManualEntry {
//lock the username
[self.userPreferences lockout:kTestingUserID];
STAssertTrue([self.userPreferences getLockoutStatus:kTestingUserID],
#"The account has been locked out");
}
#end
They call the following methods in the userPreferences Class:
- (void)lockout:(NSString *) userID {
NSMutableDictionary *dictionary =
[[self.defaults objectForKey:dict] mutableCopy];
dictionary[userID] = [NSNumber numberWithBool:YES];
[self.defaults setObject:[NSDictionary dictionaryWithDictionary:dictionary]
forKey:dict];
[self synchronize];
}
- (BOOL) getLockoutStatus:(NSString *) userID {
NSDictionary *dictionary = [self.defaults objectForKey:dict];
if ([dictionary objectForKey:userID])
return true;
return false;
}
If I comment out the testBlockManualEntry the test passes. If I run the two tests together the first one, testEmptyDictionary fails. The issue to my understanding is that the username is set in the 2nd test and then is found in the 1st test.
If I were to write a similar unit test in java I would use #Before in my setup and thus setup would run before each test method is called. That would ensure that the userPreferences is created each time and thus the values in that object are reset.
What am I missing here? My understanding of setup in Objective-C is that it should behave similarly (clearly it's not unless theres another bug that I'm not seeing).
Also please ignore the fact that a set would be better used in this scenario than a dict, I'm just looking (and how to fix the issue) for why the tests fail when run together.
I would suggest changing over to Xcode's XCT test framework. SN* is an old framework.
Your problem is probably coming from
#interface UserPreferencesTest
It should be
#interface UserPreferencesTest: XCTestCase
So that it inherits all the functionality of the test framework. Then it should work.
I also noticed this code:
if ([dictionary objectForKey:userID])
return true;
return false;
There is nothing wrong with this code and it will work. But from a style point of view I would change it. Firstly I always recommend ensuring that if ... statements always have {...} brackets. The reason is that it's easy to miss read a single line if and subtle bugs can appears, especially if other developers are updating your code.
The second thing is that whenever I see a return YES or return NO, I tend to look to see if they are a verbose version of what the code is trying to achieve.
In that light, I would probably code something like this:
return [dictionary objectForKey:userID] != nil;
Having said that, sometimes code is clearer when you do return YES or return NO. So it's how you feel about it.

Bad Access Parent is Null - Wht is this Happening?

I understand what the error is, but in this case not what is causing it. In general use it occurs maybe 1% of the time (probably less) but I have found an extreme way to cause it which I will describe below. First, I am using an in-app purchase process I found on Ray Wenderlich's site. Below are the specific pieces of concern here:
.h:
typedef void (^RequestProductsCompletionHandler)(BOOL success, NSArray * products);
#interface IAPHelper : NSObject
- (void)requestProductsWithCompletionHandler:RequestProductsCompletionHandler)completionHandler;
#end
.m
#implementation IAPHelper
{
SKProductsRequest * _productsRequest;
RequestProductsCompletionHandler _completionHandler;
}
- (void)productsRequest:(SKProductsRequest *)request didReceiveResponse:(SKProductsResponse *)response {
NSLog(#"Loaded list of products...");
_productsRequest = nil;
NSArray * skProducts = response.products;
for (SKProduct * skProduct in skProducts) {
NSLog(#"Found product: %# %# %0.2f",
skProduct.productIdentifier,
skProduct.localizedTitle,
skProduct.price.floatValue);
}
_completionHandler(YES, skProducts); // here is where bad access occurs
_completionHandler = nil;
}
Again, 99%+ of the time this works just fine. Given how infrequent the bad access happens in regular use and it has been difficult to diagnose. However, I found an extreme way to cause the issue. The setup is "Tab 1" is a table view controller and "Tab 2" is a table view controller that uses the code from above. If I quickly switch back and forth between the two tabs I can usually cause the problem to occur anywhere from a few seconds into it to 20-30 seconds. Doesn't happen every time in this scenario but it does the vast majority. As marked above the following line gets a bad access error with Parent is Null.
_completionHandler(YES, skProducts);
To solve the issue I simple do the following:
if (_completionHandler)
{
_completionHandler(YES, skProducts);
_completionHandler = nil;
}
While that fix does work and does solve the problem I am still bothered by why this is occurring. Any thoughts as to the cause of this?
Update:
Apologies to all as I did forget to include the following in what I pasted above.
- (void)requestProductsWithCompletionHandler:(RequestProductsCompletionHandler)completionHandler {
// 1
_completionHandler = [completionHandler copy];
// 2
_productsRequest = [[SKProductsRequest alloc] initWithProductIdentifiers:_productIdentifiers];
_productsRequest.delegate = self;
[_productsRequest start];
}
You need to treat your completion block as any other object when you are storing it. So if you are storing your block as a variable and then using it within a different scope from where you assign it, you need to increment the reference count by either copying it or retaining it. The simple solution is to create a strong property to store your block.
Depending on unseen bits of code, your completion handler block might not be being assigned correctly. You need to copy a block if you intend to use it outside of the scope in which it was created.
In your interface, declare your completion handler's storage attribute as "copy".
#property (nonatomic, readwrite, copy) void (^completionHandler)(BOOL, NSArray *);
If you want to control the local variable, you can synthesize the property manually in your implementation:
#synthesize completionHandler = _completionHandler;

Unit Testing Example with OCUnit

I'm really struggling to understand unit testing. I do understand the importance of TDD, but all the examples of unit testing I read about seem to be extremely simple and trivial. For example, testing to make sure a property is set or if memory is allocated to an array. Why? If I code out ..alloc] init], do I really need to make sure it works?
I'm new to development so I'm sure I'm missing something here, especially with all the craze surrounding TDD.
I think my main issue is I can't find any practical examples. Here is a method setReminderId that seems to be a good candidate for testing. What would a useful unit test look like to make sure this is working? (using OCUnit)
- (NSNumber *)setReminderId: (NSDictionary *)reminderData
{
NSNumber *currentReminderId = [[NSUserDefaults standardUserDefaults] objectForKey:#"currentReminderId"];
if (currentReminderId) {
// Increment the last reminderId
currentReminderId = #(currentReminderId.intValue + 1);
}
else {
// Set to 0 if it doesn't already exist
currentReminderId = #0;
}
// Update currentReminderId to model
[[NSUserDefaults standardUserDefaults] setObject:currentReminderId forKey:#"currentReminderId"];
return currentReminderId;
}
Update: I've improved on this answer in two ways: it's now a screencast, and I switched from property injection to constructor injection. See How to Get Started with Objective-C TDD
The tricky part is that the method has a dependency on an external object, NSUserDefaults. We don't want to use NSUserDefaults directly. Instead, we need to inject this dependency somehow, so that we can substitute a fake user defaults for testing.
There are a few different ways of doing this. One is by passing it in as an extra argument to the method. Another is to make it an instance variable of the class. And there are different ways of setting up this ivar. There's "constructor injection" where it's specified in the initializer arguments. Or there's "property injection." For standard objects from the iOS SDK, my preference is to make it a property, with a default value.
So let's start with a test that the property is, by default, NSUserDefaults. My toolset, by the way, is Xcode's built-in OCUnit, plus OCHamcrest for assertions and OCMockito for mock objects. There are other choices, but that's what I use.
First Test: User Defaults
For lack of a better name, the class will be named Example. The instance will be named sut for "system under test." The property will be named userDefaults. Here's a first test to establish what its default value should be, in ExampleTests.m:
#import <SenTestingKit/SenTestingKit.h>
#define HC_SHORTHAND
#import <OCHamcrestIOS/OCHamcrestIOS.h>
#interface ExampleTests : SenTestCase
#end
#implementation ExampleTests
- (void)testDefaultUserDefaultsShouldBeSet
{
Example *sut = [[Example alloc] init];
assertThat([sut userDefaults], is(instanceOf([NSUserDefaults class])));
}
#end
At this stage, this doesn't compile — which counts as the test failing. Look it over. If you can get your eyes to skip over the brackets and parentheses, the test should be pretty clear.
Let's write the simplest code we can to get that test to compile and run — and fail. Here's Example.h:
#import <Foundation/Foundation.h>
#interface Example : NSObject
#property (strong, nonatomic) NSUserDefaults *userDefaults;
#end
And the awe-inspiring Example.m:
#import "Example.h"
#implementation Example
#end
We need to add a line to the very beginning of ExampleTests.m:
#import "Example.h"
The test runs, and fails with the message, "Expected an instance of NSUserDefaults, but was nil". Exactly what we wanted. We have reached step 1 of our first test.
Step 2 is to write the simplest code we can to pass that test. How about this:
- (id)init
{
self = [super init];
if (self)
_userDefaults = [NSUserDefaults standardUserDefaults];
return self;
}
It passes! Step 2 is complete.
Step 3 is to refactor code to incorporate all changes, in both production code and test code. But there's really nothing to clean up yet. We are done with our first test. What do we have so far? The beginnings of a class that can access NSUserDefaults, but also have it overridden for testing.
Second Test: With no matching key, return 0
Now let's write a test for the method. What do we want it to do? If the user defaults has no matching key, we want it to return 0.
When first starting with mock objects, I recommend making them by hand at first, so that you get an idea of what they're for. Then start using a mock object framework. But I'm going to jump ahead and use OCMockito to make things faster. We add these lines to the ExampleTest.m:
#define MOCKITO_SHORTHAND
#import <OCMockitoIOS/OCMockitoIOS.h>
By default, an OCMockito-based mock object will return nil for any method. But I'll write extra code to make the expectation explicit by saying, "given that it's asked for objectForKey:#"currentReminderId", it will return nil." And given all that, we want the method to return the NSNumber 0. (I'm not going to pass an argument, because I don't know what it's for. And I'm going to name the method nextReminderId.)
- (void)testNextReminderIdWithNoCurrentReminderIdInUserDefaultsShouldReturnZero
{
Example *sut = [[Example alloc] init];
NSUserDefaults *mockUserDefaults = mock([NSUserDefaults class]);
[sut setUserDefaults:mockUserDefaults];
[given([mockUserDefaults objectForKey:#"currentReminderId"]) willReturn:nil];
assertThat([sut nextReminderId], is(equalTo(#0)));
}
This doesn't compile yet. Let's define the nextReminderId method in Example.h:
- (NSNumber *)nextReminderId;
And here's the first implementation in Example.m. I want the test to fail, so I'm going to return a bogus number:
- (NSNumber *)nextReminderId
{
return #-1;
}
The test fails with the message, "Expected <0>, but was <-1>". It's important that the test fail, because it's our way of testing the test, and ensuring that the code we write flips it from a failing state to a passing state. Step 1 is complete.
Step 2: Let's get the test test to pass. But remember, we want the simplest code that passes the test. It's going to look awfully silly.
- (NSNumber *)nextReminderId
{
return #0;
}
Amazing, it passes! But we're not done with this test yet. Now we come to Step 3: refactor. There's duplicate code in the tests. Let's pull sut, the system under test, into an ivar. We'll use the -setUp method to set it up, and -tearDown to clean it up (destroying it).
#interface ExampleTests : SenTestCase
{
Example *sut;
}
#end
#implementation ExampleTests
- (void)setUp
{
[super setUp];
sut = [[Example alloc] init];
}
- (void)tearDown
{
sut = nil;
[super tearDown];
}
- (void)testDefaultUserDefaultsShouldBeSet
{
assertThat([sut userDefaults], is(instanceOf([NSUserDefaults class])));
}
- (void)testNextReminderIdWithNoCurrentReminderIdInUserDefaultsShouldReturnZero
{
NSUserDefaults *mockUserDefaults = mock([NSUserDefaults class]);
[sut setUserDefaults:mockUserDefaults];
[given([mockUserDefaults objectForKey:#"currentReminderId"]) willReturn:nil];
assertThat([sut nextReminderId], is(equalTo(#0)));
}
#end
We run the tests again, to make sure they still pass, and they do. Refactoring should only be done in "green" or passing state. All tests should continue to pass, whether refactoring is done in the test code or the production code.
Third Test: With no matching key, store 0 in user defaults
Now let's test another requirement: the user defaults should be saved. We'll use the same conditions as the previous test. But we create a new test, instead of adding more assertions to the existing test. Ideally, each test should verify one thing, and have a good name to match.
- (void)testNextReminderIdWithNoCurrentReminderIdInUserDefaultsShouldSaveZeroInUserDefaults
{
// given
NSUserDefaults *mockUserDefaults = mock([NSUserDefaults class]);
[sut setUserDefaults:mockUserDefaults];
[given([mockUserDefaults objectForKey:#"currentReminderId"]) willReturn:nil];
// when
[sut nextReminderId];
// then
[verify(mockUserDefaults) setObject:#0 forKey:#"currentReminderId"];
}
The verify statement is the OCMockito way of saying, "This mock object should have been called this way one time." We run the tests and get a failure, "Expected 1 matching invocation, but received 0". Step 1 is complete.
Step 2: the simplest code that passes. Ready? Here goes:
- (NSNumber *)nextReminderId
{
[_userDefaults setObject:#0 forKey:#"currentReminderId"];
return #0;
}
"But why are you saving #0 in user defaults, instead of a variable with that value?" you ask. Because that's as far as we've tested. Hang on, we'll get there.
Step 3: refactor. Again, we have duplicate code in the tests. Let's pull out mockUserDefaults as an ivar.
#interface ExampleTests : SenTestCase
{
Example *sut;
NSUserDefaults *mockUserDefaults;
}
#end
The test code shows warnings, "Local declaration of 'mockUserDefaults' hides instance variable". Fix them to use the ivar. Then let's extract a helper method to establish the condition of the user defaults at the start of each test. Let's pull that nil out to a separate variable to help us with the refactoring:
NSNumber *current = nil;
mockUserDefaults = mock([NSUserDefaults class]);
[sut setUserDefaults:mockUserDefaults];
[given([mockUserDefaults objectForKey:#"currentReminderId"]) willReturn:current];
Now select the last 3 lines, context click, and select Refactor ▶ Extract. We'll make a new method called setUpUserDefaultsWithCurrentReminderId:
- (void)setUpUserDefaultsWithCurrentReminderId:(NSNumber *)current
{
mockUserDefaults = mock([NSUserDefaults class]);
[sut setUserDefaults:mockUserDefaults];
[given([mockUserDefaults objectForKey:#"currentReminderId"]) willReturn:current];
}
The test code that invokes this now looks like:
NSNumber *current = nil;
[self setUpUserDefaultsWithCurrentReminderId:current];
The only reason for that variable was to help us with the automated refactoring. Let's inline it away:
[self setUpUserDefaultsWithCurrentReminderId:nil];
Tests still pass. Since Xcode's automated refactoring didn't replace all instances of that code with a call to the new helper method, we need to do that ourselves. So now the tests look like this:
- (void)testNextReminderIdWithNoCurrentReminderIdInUserDefaultsShouldReturnZero
{
[self setUpUserDefaultsWithCurrentReminderId:nil];
assertThat([sut nextReminderId], is(equalTo(#0)));
}
- (void)testNextReminderIdWithNoCurrentReminderIdInUserDefaultsShouldSaveZeroInUserDefaults
{
// given
[self setUpUserDefaultsWithCurrentReminderId:nil];
// when
[sut nextReminderId];
// then
[verify(mockUserDefaults) setObject:#0 forKey:#"currentReminderId"];
}
See how we continually clean as we go? The tests have actually become easier to read!
Fourth Test: With matching key, return incremented value
Now we want to test that if the user defaults has some value, we return one greater. I'm going to copy and alter the "should return zero" test, using an arbitrary value of 3.
- (void)testNextReminderIdWithCurrentReminderIdInUserDefaultsShouldReturnOneGreater
{
[self setUpUserDefaultsWithCurrentReminderId:#3];
assertThat([sut nextReminderId], is(equalTo(#4)));
}
That fails, as desired: "Expected <4>, but was <0>".
Here's simple code to pass the test:
- (NSNumber *)nextReminderId
{
NSNumber *reminderId = [_userDefaults objectForKey:#"currentReminderId"];
if (reminderId)
reminderId = #([reminderId integerValue] + 1);
else
reminderId = #0;
[_userDefaults setObject:#0 forKey:#"currentReminderId"];
return reminderId;
}
Except for that setObject:#0, this is starting to look like your example. I don't see anything to refactor, yet. (There actually is, but I didn't notice until later. Let's keep going.)
Fifth Test: With matching key, store incremented value
Now we can establish one more test: given those same conditions, it should save the new reminder ID in user defaults. This is quickly done by copying the earlier test, altering it, and giving it a good name:
- (void)testNextReminderIdWithCurrentReminderIdInUserDefaultsShouldSaveOneGreaterInUserDefaults
{
// given
[self setUpUserDefaultsWithCurrentReminderId:#3];
// when
[sut nextReminderId];
// then
[verify(mockUserDefaults) setObject:#4 forKey:#"currentReminderId"];
}
That test fails, with "Expected 1 matching invocation, but received 0". To get it passing, of course, we simply change the setObject:#0 to setObject:reminderId. Everything passes. We're done!
Wait, we're not done. Step 3: Is there anything to refactor? When I first wrote this, I said, "Not really." But looking it over after watching Clean Code episode 3, I can hear Uncle Bob telling me, "How big should a function be? 4 lines is OK, maybe 5. 6 is… OK. 10 is way too big." That's at 7 lines. What did I miss? It must be violating the rule of functions by doing more than one thing.
Again, Uncle Bob: "The only way to be really be sure that a function does one thing is to extract 'til you drop." Those first 4 lines work together; they calculate the actual value. Let's select them, and Refactor ▶ Extract. Following Uncle Bob's scoping rule from episode 2, we'll give it a nice, long descriptive name since its scope of use is very limited. Here's what the automated refactoring gives us:
- (NSNumber *)determineNextReminderIdFromUserDefaults
{
NSNumber *reminderId = [_userDefaults objectForKey:#"currentReminderId"];
if (reminderId)
reminderId = #([reminderId integerValue] + 1);
else
reminderId = #0;
return reminderId;
}
- (NSNumber *)nextReminderId
{
NSNumber *reminderId;
reminderId = [self determineNextReminderIdFromUserDefaults];
[_userDefaults setObject:reminderId forKey:#"currentReminderId"];
return reminderId;
}
Let's clean that up to make it tighter:
- (NSNumber *)determineNextReminderIdFromUserDefaults
{
NSNumber *reminderId = [_userDefaults objectForKey:#"currentReminderId"];
if (reminderId)
return #([reminderId integerValue] + 1);
else
return #0;
}
- (NSNumber *)nextReminderId
{
NSNumber *reminderId = [self determineNextReminderIdFromUserDefaults];
[_userDefaults setObject:reminderId forKey:#"currentReminderId"];
return reminderId;
}
Now each method is really tight, and it's easy for anyone to read the 3 lines of the main method to see what it does. But I'm uncomfortable having that user defaults key spread across two methods. Let's extract that into a constant at the head of Example.m:
static NSString *const currentReminderIdKey = #"currentReminderId";
I'll use that constant wherever that key appears in the production code. But the test code continues to use the literals. This guards us from someone accidentally changing that constant key.
Conclusion
So there you have it. In five tests, I have TDD'd my way to the code you asked for. Hopefully it gives you a clearer idea of how to TDD, and why it's worth it. By following the 3-step waltz
Add one failing test
Write the simplest code that passes, even if it looks dumb
Refactor (both production code and test code)
you don't just end up at the same place. You end up with:
well-isolated code that supports dependency injection,
minimalist code that only implements what has been tested,
tests for each case (with the tests themselves verified),
squeaky-clean code with small, easy-to-read methods.
All these benefits will save more time than the time invested in TDD — and not just in the long term, but immediately.
For an example involving a full app, get the book Test-Driven iOS Development. Here's my review of the book.

Using stuff from other files in Cocos2d?

I am making a game (obviously) and I noticed that my HelloWorldLayer.m file is getting EXTREMELY cramped. I KNOW that there is a way to run methods from other .m files, I just don't know how. For example, I want to have a Character.h and Character.m file. Can I make it so in the HelloWorldLayer init layer, it just uses everything from the Character files instead of having to declare everything in the HelloWorldLayer? I hope my question makes sense, and any help is appreciated. Thanks!
Here is Character.m:
#implementation Character
#synthesize health,velocity;
-(void)dealloc {
[super dealloc];
}
-(id)initWithTexture:(CCTexture2D *)texture rect:(CGRect)rect
{
if((self = [super initWithTexture:texture rect:rect]))
{
[self scheduleUpdate];
}
return self;
}
-(void)update:(ccTime)dt {
[self setPosition:ccp(self.position.x,self.position.y)];
self = [CCSprite spriteWithFile:#"nukeboyGreen.gif"];
}
#end
And here's HelloWorldLayer.m (I skimped it down and took out the parts that aren't necessary):
self = [super init];
if( (self=[super initWithColor:ccc4(255,255,255,255)] )) {
CGSize winSize = [[CCDirector sharedDirector] winSize];
character = [Character spriteWithFile:#"nukeboyGreeen.gif"];
character.position = ccp(winSize.width/2,winSize.height/2);
character.scale = 0.15;
[self addChild:character];
Note that I have a Character declared in HelloWorldLayer.h
This is where object oriented programming comes to the rescue. OOP encourages you to encapsulate variables and functions that is pertinent to an object in that object itself. In your case, you should put the methods that are specific to Character in the Character class, and only get your HelloWorld to trigger those methods.
Examples:
#interface Character : CCSprite {
...
}
- (void)didCollideWith:(Object *)object;
- (void)moveTo:(CGPoint)nextPoint;
- (void)shootArrow:(ckDirection)direction;
- (BOOL)isAlive;
- (int)numberOfLivesRemaining;
...
#end
Then in HelloWorldLayer:
[character moveTo:ccp(100, 200)];
[character shootArrow:kDirectionUp];
if (![character isAlive]) {
[self showGameOver];
}
Not only that your HelloWorldLayer is less cluttered, you can easily understand what your code does by simply looking at the reasonably named methods.
EDIT:
To answer your question as in the comment about how to designate the sprite image in Character class:
#implementation Character
- (id)init {
self = [super initWithFile:#"sprite_character.png"];
if (self) {
// further customization
}
return self;
}
#end
EDIT (after code was added to the question):
First let me point out a few mistake (sorry for the lack of softer word):
You rarely need your sprite to call the [self scheduleUpdate] or [self schedule:SEL]. Normally people implement the update (or tick) method at the CCLayer or CCScene level, where the purpose is to check all the actors (sprites, menus, nested layers etc) for collision/interaction and update their attributes. If you just want to animate movement of a sprite to a specific position, just call runAction method from CCLayer (in the init, update, ccTouchBegan or somewhere). You can read cocos2d-iphone tutorial on Actions by clicking here. So, move the update method and the scheduleUpdate call into your HelloWorldLayer, and then you no longer need to override initWithTexture.
I'm seeing you instantiating a CCSprite in the update method. My above point on the inappropriateness of update method in CCSprite notwithstanding, there is something more important you need to understand when you implement a method: that is you need to decide how and how often your method is going to be used/called. Since the update method is going to be called once per frame (that is 60 times per second), it is simply wrong to unconditionally instantiate an object in that method. You are making the iPhone to allocate (and deallocate) the object with no apparent reason, wasting the processor time/power the device has. You might want to ask where should you instantiate the CCSprite. The answer is in the init method because that method is only called once per object instance. Again, all you need to know is whether a method is going to be called once or multiple times, and decide whether a piece of code should be in there or somewhere else.
In your code for HelloWorldLayer, did you realize that you are calling the super init* methods twice. You don't need to call [super init] since [super initWithColor:ccc4( ... )] is going to call specific init method internally. Although it is not entirely wrong to do so, you are going to break the 'assumption' that init is going to be called once per instance, so you might end up breaking some object integrity unintentionally (and believe me it's going to be hard to debug later)
And finally, care to enlighten me what's the real purpose of the line [self setPosition:ccp(self.position.x,self.position.y)];. You basically set the position of the self object to its current position, so that's like saying "hey you, move your position to your current position" and he'll be like "huh?" :P

How to call a method in init method?

My program looks like this:
-(id)init
{
if ( (self = [super init]) )
{
//TargetWithActions *targetActions= [[TargetWithActions alloc] init];
[self countDownSpeed123];
}
return self;
}
-(void)countDownSpeed123
{
countDownSpeed = 5.0f;
}
#end
warning: 'TargetWithActions' may not respond to '-countDownSpeed123'
I am getting the warning in this way. Where I am wrong in my program. Please explain ?
Thank You.
If I need to use the countDownSpeed value in another class, how can I retain the value ? How can I use in the other class? I think retain works for pointer types.
EDIT:
Sorry for my bad coding and negligence. I have did mistakes in my program which are very blunt.
Thanks for answering.
First: I did not declare the
function (
-(void)countDownSpeed123; )in
interface.
Second: I did not include the
following in my class where I needed
the (countDownSpeed) value.
TargetWithActions *targetActions= [[TargetWithActions alloc] init];
[targetActions countDownSpeed123];
Now, I got what I need.
Thank You.
In the class where you trying to use
TargetWithActions, and in TargetWithActions.m make sure you
have #import
"TargetWithActions.h".
In TargetWithActions.h make sure
in your class declaration
you declared the method -(void)countDownSpeed123;
Sorry I don't understand what are you trying to do with countDownSpeed123, it does not return anything (void) so I'm not quite sure what you want to retain. If the method returns simple value like float or int you don't have to retain it, it is passed by value - it will be copied.
Sorry for my bad coding and negligence. I have did mistakes in my program which are very blunt. Thanks for answering.
First: I did not declare the function ( -(void)countDownSpeed123; )in interface.
Second: I did not include the following in my class where I needed the (countDownSpeed) value.
TargetWithActions *targetActions= [[TargetWithActions alloc] init];
[targetActions countDownSpeed123];
Now, I got what I need.
Thank You.