Objective C - Category No Visible selector #removeWhiteSpaceStringWithString - objective-c

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.

Related

Static NSLocalizedString

After checking a number of topics, I still can't figure something out : what is the (best?) way to use static NSLocalizedString, i.e. to statically allocate a NSLocalizedString and access it easily.
Ideally, I would want to do something like that (which won't compile, with an Initializer element is not a compile-time constant error):
//Somewhere in my header
static NSString* mystring = NSLocalizedString(#"min", nil); //Error : "Initializer element is not a compile-time constant"
#implementation myClass
(NSString*)aMethod
{
return myString;
}
#end
I know NSLocalizedString is a macro defined by #define NSLocalizedString(key, comment) \
[[NSBundle mainBundle] localizedStringForKey:(key) value:#"" table:nil], but that is not helping much :S.
Why ?
Long story short, to prevent the multiple definition of the same string in multiple parts of a document (which would prevent a one-stroke edit in my whole app).
Consider the example, where the redundancy of the definition is quiet explicit :
//MyDelegate.h
#property IBoutlet NSTextField* myTextField;
//MyDelegate.m
#implementation MyDelegate.m
#synthetize myTextField;
-(void)setTextFieldToDefaultValue
{
[myTextField setStringValue:NSLocalizedString(#"Name",#"This field is used to write one's name");
}
-(BOOL)isTextFieldStringDefault:(NSString*)myString
{
return [[myTextField stringValue] isEqual:NSLocalizedString(#"Name",#"This field is used to write one's name")];
}
#end
Of course, it makes more sense in a project which is quiet dense and big, where the string would be used in difference methods, and in a context where you have use of a lot of similar localized strings.
Generally this should all be in your implementation file:
static NSString* myString = nil;
#implementation myClass
+ (void)initialize
{
myString = NSLocalizedString(#"min", nil);
}
- (NSString *)aMethod
{
return myString;
}
#end
Well one more way you can write the same without using initialize method above:-
static NSString* mystring=nil;
-(NSString*)aMethod
{
mystring = NSLocalizedString(#"min", nil);
return mystring;
}

Override a method in 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!

What is an import statement where filename contains "+"?

I have seen in some source code (by other developers) something like this:
#import "SomeClass+SomeOtherClass.h"
What is the + for? What does this mean?
Let's say you want to add functionality to an existing class (exp: NSString). You can do that by creating a subclass or you can use a category. And it is common to name the file where the category is defined using the pattern : MyClass+MyCategory.h.
For example, we can add a method reverseString to the class NSString in a category:
// File NSString+reversable.h
- (NSString *)reverseString;
// File NSString+reversable.m
- (NSString *)reverseString
{
// Implementation
}
Have a look at this documentation for more information about categories.
Then you can use that category in another class:
#import "NSString+reversable.h"
// ...
NSString *aString = #"Hello!";
NSString *reversedString = [aString reverseString];
The "+" in header/source filenames is - by convention - used to describe Category implementations.
Example :
Let's say you want to add some functionality to an existing class (e.g.the NSString class). (NSString+Utilities.h)
// NSString+Utilities.h
#interface NSString (Utilities)
-(NSString *) doSthWithThisString;
#end
// NSString+Utilities.m
#implementation NSString (Utilities)
-(NSString *) doSthWithThisString
{
NSMutableString *transformedStr = [self copy];
// Do sth
return transformedStr;
}
#end
Using it :
// in another file
#import "NSString+Utilities.h"
- (void)awakeFromNib
{
NSString* myString = #"This is a string";
// you may use our new NSString method as much as any already-existing one
NSString* newString = [myString doSthWithThisString];
}
Reference :
Mac OS Developer Library - Categories & Extensions
Objective-C Categories - Wiki

Objective C - respondsToSelector for dynamic properties

I am currently facing the problem to check whether a property of an Object (NSManagedObject) exists or not.
Unfortunately the method
[[MyObject class] respondsToSelector:#selector(myProperty)];
always returns NO.
I think it's because the property generated by CoreData is a new style property ala
#property (nonatomic, strong) NSString *myProperty
So any ideas how to solve this issue?
I would really appreciate all of your suggestions ;)
Thanks in advance!
Alex
[[MyObject class] respondsToSelector:...] asks whether the metaobject responds to that selector. So, in effect, it asks whether there is a class method with that selector. Your code would return YES if you had:
+ (NSString *)myProperty;
It returns NO because you have the equivalent of the instance method:
- (NSString *)myProperty;
You need to call respondsToSelector: on an instance of your class.
You could normally use instancesRespondToSelector: directly on the metaclass (so, [MyObject instancesRespondToSelector:...]) but Core Data synthesises the relevant method implementations only when you create an object, so that's a non-starter. You could however create an instance via the normal NSEntityDescription route and test respondsToSelector: on that.
Since it's all Core Data, an alternative would be to ask the NSManagedObjectModel for the relevant NSEntityDescription via its entitiesByName dictionary and inspect the entity description's propertiesByName dictionary.
The only cases I've required this has been to set things dynamically so I am only looking for the setter. I am just composing the signature for the setter and then testing that it exists and then using it.
NSArray * keys = [myObject allKeys];
for(NSString * key in keys)
{
NSString * string = [NSString stringWithFormat:#"set%#:", [key capitalizedString]];
SEL selector = NSSelectorFromString(string);
if([myObject respondsToSelector:selector] == YES)
{
id object = [dict objectForKey:key];
// To massage the compiler's warnings avoid performSelector
IMP imp = [card methodForSelector:selector];
void (*method)(id, SEL, id) = (void *)imp;
method(myObject, selector, object);
}
}
This code satisfies a need where you may not be digesting all the data you receive in the dictionary.
In this case it was sparse json, so some data may not always exist in the json so stepping thru myObjects attributes looking for their corresponding key would just be a lot of wasted effort.
Are you synthesizing the property in the class file?
#interface SomeClass : NSObject
{
#property (nonatomic, strong) NSString *myProperty
}
#end
#implementation SomeClass
#synthesize myProperty;
#end

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