How to add a simple function at top of FirstViewController.h - iphone

I'm writing a simple app with 10 buttons on it. One button looks like this:
- (IBAction)num1pressed:(UIButton *)sender
{
// checkSomethingFirst
self.myLabel.text=[NSString stringWithFormat:#"1"];
}
Every button needs to "check something first" so rather than copy and paste the lines of code into every (IBAction)num#pressed code segment, I want to call a function called checkSomethingFirst. Maybe function is the wrong word here? Nevertheless my function looks like this:
-(void)checkSomethingFirst
{
// check first thing
// check other thing
// check last thing
}
When I compile my code - which looks like this:
- (IBAction)num1pressed:(UIButton *)sender
{
checkSomethingFirst;
self.myLabel.text=[NSString stringWithFormat:#"1"];
}
I get an error at checkSomethingFirst; <--- Use of undeclared identifier 'checkSomethingFirst'.
How do I create a simple function or procedure that all of my buttons can use? Note I don't need to return any values as my checkSomethingFirst function simply sets a label to either a 0 or a 1 (probably better off using a bool, except I'm doing the setting on a global label - hence no need to return a bool, I can simply interrogate the value in the label).

You need to say what object the method should be called on
[self checkSomethingFirst];

You are calling your method in the wrong way
- (IBAction)num1pressed:(UIButton *)sender
{
[self checkSomethingFirst];
self.myLabel.text=[NSString stringWithFormat:#"1"];
}

You need to call that method using
[self checkSomethingFirst];
hope it helps.

- (IBAction)num1pressed:(UIButton *)sender
{
// checkSomethingFirst
[self checkSomethingFirst];
self.myLabel.text=[NSString stringWithFormat:#"1"];
}

Related

What is the role of selector in UILocalizedIndexedCollation's sectionForObject:(id)object collationStringSelector:(SEL)selector method

I am a beginner of iOS development and while going through this document (iOS Developer Guide about configuring a TableView with Indexed List) I came across this:
// Listing 4.7
for (State *theState in statesTemp) {
NSInteger sect = [theCollation sectionForObject:theState collationStringSelector:#selector(name)];
theState.sectionNumber = sect;
}
I could not figure out the selector (#selector(name)) and its purpose, nor could I find the method with the name passed in the selector i.e. name. I googled for examples to find a better explanation, and came across this example.
In the code listing, there is a statement which is a method call:
    
self.tableData = [self partitionObjects:objects collationStringSelector:#selector(title)];
now the selector is called title. I have not been able to find a better explanation, and my question is what is the purpose of this selector and the method referred by this selector, and what should it do and return.
In general
With the #selector(title:) you define which method will be called.
in my example it will call
- (void) title:(id)someObject {}
Be carefull with the semicolon at the end! If you have a semicolon at the end you method will have parameters like mine above.
Your code states just #selector(title) and will call a method title without a parameter like this:
- (void)title {}
Specific to UILocalizedIndexCollation
The docs state:
selector
A selector that identifies a method returning an identifying
string for object that is used in collation. The method should take no
arguments and return an NSString object. For example, this could be a
name property on the object.
So i would suggest you implement it like this
self.tableData = [self partitionObjects:objects collationStringSelector:#selector(title)];
...
- (NSString *)title {
NSString *title;
// some code to fill title with an identifier for your object
return title;
}
Try replace the title with self:
self.tableData = [self partitionObjects:objects collationStringSelector:#selector(self)];
worked for me

Calling a method in Objective-C that references another class file

I am trying to call a method that checks whether the player is bigger or smaller than the enemy. (this is a fish game)
In EnemyFish.m I am using this method
-(void) compareSize:(Player*)player{
if (self.fSize > player.pSize){
isBigger = true;
}
else{
isBigger = false;
}
}
Then I want to call this method during the update so I am doing this:
-(void) update {
[self compareSize];
//Check to see if bigger than player fish
if( isBigger == true){
//code for if bigger
}else{ //etc. }
I am getting an exception: sharedlibrary apply-load-rules all
not sure what the best way to set up this method would be, and the best way to call it, since [self compareSize] is definately not working.
Any help would be greatly appreciated, Thanks!
------UPDATE----------
What about if I use this
update:(Player *)player{
The problem I was running into here, is how to call this correctly, I wasn't sure how to change this to correctly call the new update method:
[self schedule:#selector(update) interval:1.0f/60.0f];
It is unclear what you are asking, but let's look at your code and see if it helps.
Your first method can be written more concisely as:
- (void) compareSize:(Player *)player
{
isBigger = self.fSize > player.pSize;
}
There is no point in using an if/else to assign a true/false (or YES/NO) value.
Looking at this method raises the obvious question of whether it would be better returning a value rather than assigning to an instance variable. This would look like:
- (BOOL) compareSize:(Player *)player
{
return self.fSize > player.pSize;
}
and now you can use a call to compareSize in an if.
Assuming the second version of compareSize your second method is:
-(void) update
{
//Check to see if bigger than player fish
if ([self compareSize]) // OOPS, no Player
{
//code for if bigger
}
else
{
//etc.
}
}
But this doesn't work as you need an instance of Player to pass to compareSize:, e.g. [self compareSize:somePlayerInstance]. So you now have to ask yourself where you expect the Player to be found; it could be an argument to update (e.g. - (void) update:(Player *)somePlayerInstance), or you might have a method to call which returns a whole collection of players and you need to test against each one, etc., etc. I can't give an answer as I've no idea of your game and algorithm!
Following comment
You must store a reference to your Player object somewhere in your application. If there is only a single player is Player designed as a singleton with a sharedInstance, or similarly named, class method that returns the single instance? If so then your update will contain:
if ([self compareSize:[Player sharedInstance]])
etc.
Another design pattern is to have your application delegate store the reference and to provide a method (or property) for accessing it. Following this pattern (and making up a class MyDelegateApp and property player names) your code might look like:
if ([self compareSize:((MyAppDelegate *)[NSApp delegate]).player])
Yet another model is to create the single player in the application's main XIB/NIB file - etc., etc., there are many application models!
You "simply" (its not simple of course) need to design your application model so that your single player is accessible, one way or another, where you need it...
Your compareSize: method (note the colon) requires a player parameter.
So you need to call it like this:
[someEnemyFish compareSize:somePlayer]
If self is the instance of EnemyFish you want, you can do [self compareSize:somePlayer], but your title seems to indicate self isn't an EnemyFish?

how to initialize a method parameter with null

I have a custom method that accepts two parameters. I am using this method with several different data sets, of which some only need to have one array passed and other two.. I am wondering if its possible to pass one null if needed?
//method
- (IBAction)startSortingTheArray:(NSArray *)arrayData:(NSArray *)arrayDataB
{
//..
}
Yes, you should be able to pass one null if needed, as long as your implementation is coded to expect it that way. For example:
- (void)startSortingTheArray:(NSArray *)arrayData arrayB:(NSArray *)arrayDataB
{
if (arrayData != nil) {
// process arrayData
}
if (arrayDataB != nil) {
// process arrayDataB
}
}
To make your interface more clean, you could also provide an alternate signature of the method and do something like:
- (void)startSortingTheArray:(NSArray *)arrayData
{
[self startSortingTheArray:arrayData arrayB:nil];
}
Note that I changed the return type from what you initially posted. You had it declared as an IBAction which should take sender as its argument, not an array as you were passing it. I assume you meant for this to be applied to another function and not really to an interface builder action.
Yes you could do that. Then in your startSortingTheArray handle such cases... (i.e. code such a way that you dont assume both arrayData & arrayDataB are present).
Another suggestion I would like to make is if the parameters are getting too many & you have this scenario of some params being present & some not. Then use 1 object as parameter. This object is encapsulated & all the data points are properties of this object. That way your code is much clear & cleaner, easy to maintain blah, blah...
if you are using this method in interface builder e.g attaching it to UIButton then its not possible.
but in if your are calling this method in other methods then yes
[self startSortingTheArray:nil arrayB:nil];
- (IBAction)startSortingTheArray:(NSArray *)arrayData:(NSArray *)arrayDataB
{
if(arrayData == nil){
// do something
}
if(arrayDataB == nil){
// do something
}
if(arryaData == nil && arrayData == nil){
// do something
}
//..
}

How to verify number of method calls using OCMock

Is there a way to verify that a method has been called 'x' amount of times?
Looking at the test file for OCMock, it seems that you need to have the same number of expects as you have calls. So if you call someMethod three times, you need to do...
[[mock expect] someMethod];
[[mock expect] someMethod];
[[mock expect] someMethod];
...test code...
[mock verify];
This seems ugly though, maybe you can put them in a loop?
I've had success by leveraging the ability to delegate to a block:
OCMStub([mock someMethod]).andDo(^(NSInvocation *invocation)
{ /* block that handles the method invocation */ });
Inside the block, I just increment a callCount variable, and then assert that it matches the expected number of calls. For example:
- (void)testDoingSomething_shouldCallSomeMethodTwice {
id mock = OCMClassMock([MyClass class]);
__block int callCount = 0;
OCMStub([mock someMethod]).andDo(^(NSInvocation *invocation) {
++callCount;
});
// ...exercise code...
int expectedNumberOfCalls = 2;
XCTAssertEqual(callCount, expectedNumberOfCalls);
}
The block should be invoked each time someMethod is called, so callCount should always be the same as the number of times the method was actually called.
If you need to check if a method is only called once, you can do it like this
[self.subject doSomething];
OCMVerify([self.mock method]);
OCMReject([self.mock method]);
[self.subject doSomething];

iPhone Int with NSObject &/causes class can't reference itself

I've got a function called updateTheValue() that I have called using [self updateTheValue] for a while now. Two things happened recently; I added the method calling in the viewDidLoad() method and it spit out a warning saying my class may not respond to this. Second, I want to pass objects to updateTheValue() like strings, but mostly ints, so I declared an NSObject to pass into the method. Can an int fit into an NSObject slot, or what should I use instead?
I would have posted these seperately but they seem to be related since after updating updateTheValue() to accept an NSObject every reference to this function turns out the error that my class "May not respond to -updateTheValue"
You could make your method like this:
-(void)updateTheValue:(NSObject *)anObject
// or use -(void)updateTheValue:(id)anObject
{
if ([anObject isKindOfClass:[NSString class]]) {
// Do your string handling here
}
else if ([anObject isKindOfClass:[NSNumber class]]) {
// Do your number handling here
}
}
Use it like this:
[self updateTheValue:[NSNumber numberWithInt:42]];
I'd suggest doing two different methods though, i.e. updateTheValueWithInt: and updateTheValueWithString: making it easier to read and understand.
Make sure you make the method signature visible before using them, so that the compiler knows what this does.
If you use separate methods you can use int directly without wrapping them into NSNumber objects.
First problem:
updateTheValue() must be declared before you try to call it.
You can either move the definition of function before the calls to it, or add a prototype at the top - eg, add:
(void) updateTheValue;
near the top.
Second problem:
Use an NSNumber, eg [NSNumber numberWithInt:45];