So, i want to get NSDictionary from class method, i think it will be like this:
NSDictionary *dictionary = [SomeClass parseJSONAndGetDictionary];
Can someone explain me how i can make it?
in you .h file of your SomeClass declare method like,
+ (NSDictionary*)aClassMethod;
and in your .m file of your SomeClass implement it like it will return NSDictionary something like,
+ (NSDictionary*)population{
// get desired dictionary here and return it
return dictionary ;
}
the you can got dictionary from any class like,
NSDictionary *dictionary = [SomeClass parseJSONAndGetDictionary];
by implementing SomeClass.h file in that class.
Related
I try to write my own class in objective-c. I declared a class variable NSArray *_people in it. I set all setters and getters and everything works fine for me but.. A silly easy question. When I want to query my array with a 'for' loop It must go like this:
for (NSString *s in [myClass people])
How do I achieve the same behavior as with a usual NSArray class instance like this?:
for (NSString *s in people)
If you want to keep people array property private, then you should implement NSFastEnumeration protocol in your new class. Custom implementation is quite dificult (buffering, change mutation flag, pointers and size), but your case it is pretty simple.
In your .m file you should implement:
- (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state objects:(id __unsafe_unretained [])buffer count:(NSUInteger)len {
return [self.people countByEnumeratingWithState:state objects:buffer count:len];
}
And in your header file:
#interface YourClass : NSObject<NSFastEnumeration>
MyClass.h
#interface MyClass
#property (nonatomic, strong) NSArray *people;
#end
Now, you can access the array like...
for(NSString *s in [myclass people])
I have a class to perform little conversions like NSDate to NSString with a specific format, etc.
Every methods are class methods, eg +[Tools humanReadableStringForDate:(NSDate*)date];
I sometime need my method +[Tools A] to call a method +[Tools B] of my class, but inside a block.
Should I create a __block safeSelf = self; or is it unnecessary because I use class level methods ?
EDIT :
here is an example, not my actual code :
#implementation FileManager
+(void) uploadEveryFile:(void (^)(NSObject*))thingToDo :(NSArray*) fileArray {
for(NSString *s in fileArray) {
[[SomeWebAPI uploadFile:s withSuccess:^(NSNumber *responseCode) {
[self logUploadOk:s];
}];
}
}
+(void) logUploadOk:(NSString*)s {
NSLog(#"File upload ok : %#", s)
}
#end
I think this make things clearer. I like to use self keyword even for class methods when I can - in this example I can because I am in the same class and refer to a class level method - because it seems to make more sense, and can be helpful if I have to modify my class name.
So is it correct to write it like this ? Is it working but not really correct ? Do I really need to call logUploadOk using [FileManager logUploadOk:s] ?
Thank you !
It is unnecessary to use __block or __weak or anything like that. You are talking about self in a class method, which is the class object itself. The class object lives for the whole program, so memory management like retain and release on it have no effect. So you don't need to worry about retain cycles.
+ (NSString *)A
{
NSString *something = [Tools B];
NSString *something = [self B]; // both are same inside class method
}
+ (NSString *)B
{
//..
}
That's unnecessary because you're using class method, not instance method. To call Class methods, you use the class name: [Tools doThisForMe].
However, it sounds like you could use Objective-C Categories in this case. It would allow you to extend the different classes and make your code more readable such as [myNSDate humanReadableString].
In your case, it would go along the lines of:
NSDate+Human.h
#interface NSDate (Human)
- (NSString *)humanReadableString;
#end
NSDate+Human.m
#implementation NSDate (Human)
- (NSString *)humanReadableString {
// do whatever you want.
// now 'self' refers to the NSDate instance
}
#end
What is the difference of using:
+ (id) myMethod;
// Rather than
- (id) myMethod;
Using a + declares the method as a class method, or a method that can be called directly on the class, where the class is the object. So when you have this:
#implementation Foo
+(NSString*)method1 {
return #"Foo";
}
-(NSString*)method2 {
return #"Foo";
}
#end
The methods are called in different ways:
[Foo method1]; //=> #"Foo"
Foo* f=[[Foo alloc] init];
[f method2]; //=> #"Foo"
One other thing to note is that class methods don't have access to an instance, which means they can't access any kind of instance variables.
#Linuxios pretty much summed up the concept of class and instance method. However, since you mentioned getters and setters in your title, I want to point out that in Objective-C you can use properties instead of writing your own accessor methods. For example,
In the header file, you will have something like this:
#interface MyObject : NSObject
#property (nonatomic,retain) NSSet* mySet;
#end
In the m file, you wil have something like this:
#implement MyObject
#synthesize mySet;
#end
To access the set in another class you can do it like this:
myObject.mySet; // assuming myObject is an instance of the MyObject class
The top one is a class method (no instance required)
The second one is a instance variable (attached to a specific instance).
This answer explains the methods quite well:
Method Syntax in Objective C
[MyObject myMethod]; // did not have to create an instance
MyObject* myNewObject = [[MyObject alloc] init] autorelease];
[myNewObject myMethod]; // had to create an instance
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
I have a dictionary that I read from a plist. I want to create a subclass of NSDictionary to implement something like the following, so that I can avoid using #"key name" everywhere in my source code:
#interface MyDict{
}
-(NSString*) textString;
#end
#implementation MyDict
-(NSString*) textString {
return [self objectForKey:#"textString"];
}
#end
In my other method:
MyDict *d = ... // something i read from plist
NSString *str = [d textString];
When I call the method, the app crashes because of "unrecognized selector textString". What is wrong here?
Just assigning an NSDictionary to a MyDict pointer doesn't make it a MyDict instance.
One way you can do this would be to create a category to add your method to NSDictionary. See http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocCategories.html#//apple_ref/doc/uid/TP30001163-CH20-SW1 for info.
Your class has no superclass. Also, the conventional wisdom is that it's very difficult to subclass NSDictionary because it is an class cluster. You don't actually get an NSDictionary back when you:
NSDictionary * myDict = [NSDictionary dictionary];
You get a private subclass (NSCFDictionary in this case).
You might want to try defining your own dictionary keys, the way Apple does:
NSString * const MyWonderfulUnicornKey = #"MyWonderfulUnicornKey";