Override a method in Objective-C - objective-c

I'm trying to override a getter in Objective-C. I have two classes, First and Second, like:
First.h:
#interface First : MashapeResponse {
NSString* message;
}
#property(readwrite, retain) NSString* message;
#end
First.m:
#import "First.h"
#implementation First
#synthesize message;
#end
Second.h:
#import "First.h"
#interface Second : First
-(NSString*) message;
#end
Second.m:
#import "Second.h"
#implementation Second
-(NSString*) message {
return [NSString stringWithFormat:#"%#%#", #"Message is ", message];
}
#end
I'm trying to execute the following code, but it seems like the overridden method in Second is never executed.
First* first = [[First alloc] init];
[first setMessage:#"hello"];
NSLog(#"%#", [first message]); // "hello" expected
Second* second = (Second*) first;
NSLog(#"%#", [second message]); // "Message is hello" expected, but it's still "hello"

You're actually casting a First as a Second (which is bad form); but the underlying type is still First, that's why you see the original message (from First). Alloc a Second, and it should work as expected.

The problem is not with how you override, but with how you allocate:
Second* second = [[Second alloc] init];
second.message = #"Hello";
NSLog(#"%#", [second message]);
When you cast First* to Second*, the object remains what it was - an instance of First. You need to allocate an instance of Second in order to see your override work.

In Objective-C, casts only make a statement to the compiler that an object is of a certain type. They do nothing to alter the actual object in any way. In down-casting first to a pointer to a Second instance, you have made an assertion to the compiler that is actually incorrect - because the object now pointed to by both first and second is still an instance of First. Hope this helps!

Related

Objective C - Category No Visible selector #removeWhiteSpaceStringWithString

so im trying to add new method for testing using Category from NSString, but some how i must declared like this with following step:
Create Category from NSString with name StringExtension so it will be NSString+StringExtension, after that i declared my own methos that return type is String
so after i define in NSString+StringExtension #interface and #implementation, i tried in my viewController to called it, but first i import the class NSString+StringExtension
after that i do like this
NSString *testString = #"as d a s d";
NSLog(#"===== %#", [testString removeWhiteSpaceStringWithString:testString]);
and it says
No visible #interface for 'NSString' declares the selector 'removeWhiteSpaceStringWithString:'
the question is, why it cannot use like that? i already search and see tutorial doing like that and its possible, but why i'm not able to do that?
so i found this way, but i don't know is this the correct code to use?
NSLog(#"===== %#", [[testString class] removeWhiteSpaceStringWithString:testString]);
anyone have the same case like i am?
Based upon what you have shared with us, it would appear that you defined a class method (with +). It should be an instance method (with -) and then you don’t need the parameter, either. You can simply reference self.
For example:
// NSString+Whitespace.h
#import Foundation;
NS_ASSUME_NONNULL_BEGIN
#interface NSString (Whitespace)
- (NSString *)stringByRemovingWhitespace;
#end
NS_ASSUME_NONNULL_END
And
// NSString+Whitespace.m
#import "NSString+Whitespace.h"
#implementation NSString (Whitespace)
- (NSString *)stringByRemovingWhitespace {
return [self stringByReplacingOccurrencesOfString:#"\\s+"
withString:#""
options:NSRegularExpressionSearch
range:NSMakeRange(0, self.length)];
}
#end
Then you can do:
NSString *testString = #"as d a s d";
NSLog(#"===== %#", [testString stringByRemovingWhitespace]); // ===== asdasd
Obviously, do whatever you want in your implementation, but it illustrates the idea, that you want an instance method and you do not need to pass the string again as a parameter.

NSLog returning null instead of string

NSLog is returning the output 'Null" instead of a string that I would have expected. I suspect that this is a problem with private instance variables and such, but since I am not familiar with Object-oriented programming I cannot determine the cause.
//The viewDidLoad method in MainGameDisplay.m:
- (void)viewDidLoad
{
[super viewDidLoad];
Engine *engine = [[Engine alloc] init];
[engine setPlayerName: viewController];
}
The string is entered by a UITextField, the property being
//ViewController.h
#property (strong, nonatomic) IBOutlet UITextField *PlayerNameTextView;
The method works fine and returns the correct string if [engine setPlayerName: self] is placed into ViewController, but anywhere outside the location that *PlayerNameTextView is causes this problem.
//Engine.m
#implementation Engine
{
ViewController *firstPage;
}
NSString *Player;
-(void) setPlayerName: (ViewController *) name
{
Player = [[name PlayerNameTextView] text];
NSLog(#"%#", Player);
}
NSLog return type is void as you can see in it's documentation. There is no reason to expect any return value for a call to it, since it does not return anything.
Make sure that 'name' is properly initialized. Try putting an assert(name != nil) right before the NSLog. Or better yet, set a breakpoint at the NSLog and inspect the variables.
Another suggestion: Why not make the method -(void) setPlayerName:(NSString*)name? This is more straightforward than passing around pointers to view controllers, and would be easier to debug.

iOS create object

I want to create an object called Note . Then I want to assign some values to it's fields and display them in the console to verify that all of this works properly.
Note.h
#import <Foundation/Foundation.h>
#interface Note : NSObject
{
NSNumber *position;
NSString *syllable;
}
#property(nonatomic, retain)NSNumber *position;
#property(nonatomic, retain)NSString *syllable;
#end
Note.m
#import "Note.h"
#implementation Note
#dynamic position;
#dynamic syllable;
#end
After this , in another class I want to assign some values to the fields .
-(void) configNote:(Note*)not
{
not = [Note alloc];
[not setPosition:[NSNumber numberWithInt:2]];
[not setSyllable:#"Twin-"];
}
.....
Note *note;
[self configNote:note];
NSLog(#" pos : %d syl : %# ",[[note position] integerValue],[note syllable]);
I tried to use #synthesize instead of #dynamic but still nothing changes . The reason of the error is : -[Note setPosition:]: unrecognized selector sent to instance 0x733d060
init your note and use custom init method to initialize ivars and change dynamic to synthesize
and for better use this init to initialize your varibales
- (id)initWithPosition:(NSNumber*)pos andSyllable:(NSString*)syl {
self = [super init];
if (self) {
self.position = pos;
self.syllable= syl;
}
return self;
}
Since your question is quite basic and fundamental you might want to check out this Tutorial on cocoadevcentral. It's very well done and teaches you some of the basics when dealing with objects.
Your problem is that you are passing the Note object pointer to configNote: by value rather than by reference. Inside of configNote: when you set not to a newly allocated Note object, you are actually setting the local variable not to that value. What your NSLog call outside of your configNote: object actually receives is original note value prior to the call to configObject:.
To get what I believe you desire, either more the Note object allocation outside of the configObject: method, or pass the Note object pointer to configObject: by reference.
If you are using ARC, try "strong" instead of "retain".

addObject in NSMutableArray doesn't work

I'm a beginner to XCode.
Below is my code. I want to add an object to a mutablearray. From the debugger window I can see there is one object added to the array "words". I can also see the property "flag" of that object is "NO". The problem is another property "str" is shown as "out of scope".
Can anyone help me with this issue? Thanks a loooooot! Stucked on this one for the whole afternoon.
NSMutableArray * words=[[NSMutableArray alloc] initWithCapacity:numberOfWords];
Word *w=[[Word alloc] init];
[w setStr:#"abc" flag:NO];
[words addObject: w];
[w release];
--
#interface Word : NSObject{
NSString *str;
BOOL flag;
}
-(void) setStr: (NSString *) s flag:(BOOL) b
{
self.str=s;
flag=b;
}
Do you have a property declaration for your string? Are you retaining the string you are setting?
Still AFAIK 'out of scope' does not necessarily mean it was not set or that nothing has been set. Try an NSLog of the value or something. You might find that there is nothing wrong.
Have a look at this question that talks about scope in GDB:
Objective-C: instance variables out of scope in debugger
Your problem is that the string #"abc" is a temporary object who's scope only exists during the [w setStr:#"abc" flag:NO] method call. You should be able to resolve this problem by making str a #property of Word:
#interface Word : NSObject{
NSString *str;
BOOL flag;
}
#property (retain) NSString* str;
#end
And in your implementation file
#implementation Word
#synthesize str;
-(void) setStr: (NSString *) s flag:(BOOL) b
{
self.str=s;
flag=b;
}
#end

iOS: issues with a always null NSString

I have a doubt about initializing string with synthesize keyword.
In my Event.h class I have
#interface Event : NSObject {
NSString *title;
}
#property (nonatomic, retain) NSString *title;
and in Event.h I have
#synthesize title;
However when I want to set the title from my main class and I display the content in the console, I get null:
[self.currentEvent.title stringByAppendingString:#"hello"];
NSLog(#"%#", self.currentEvent.title); //this is null
Is because I don't properly initialize the title variable in Event? Isn't synthesize initializing it for me?
[self.currentEvent.title stringByAppendingString:#"hello"];
You call stringByAppendingString: on a null object (since it was never initialized), so it doesn't do anything. Plus, even if it were to return something, you're not storing the return value anywhere.
if(self.currentEvent.title==nil){
self.currentEvent.title = #"hello";
}
else{
self.currentEvent.title = [self.currentEvent.title stringByAppendingString:#"hello"];
}
#synthesize creates the setter and getter methods for you, but does not initialize
Fastest way to get up to speed with this stuff is to watch "Developing Apps for iOS" by Paul Hegarty / Stanford University, available free on iTunes.
You are not storing the result of your call into a variable. I also suggest using this method since it's a little bit cleaner because you do not need to have an if statement.
[self setTitle:[NSString stringWithFormat:#"hello %#", [self title]]];