I created this Class to store Rss feeds about Cd-rooms:
CdObject.h
#interface CdObject : NSObject{
NSString *title,*artist,*country,*company,*price,*year;
}
#property(nonatomic,retain)NSString *title,*artist,*country,*company,*price,*year;
CdObject.m
#import "CdObject.h"
#implementation CdObject
#synthesize title,artist,country,company,price,year;
#end
Then while parsing the xml i'm creating new instances of this class filling their properties (title,artist ect..)and pushing them into a NSMutableArray (cdListArray)
How could I read the property of one of these objects from inside cdListArray?
Ex:NSLog(#"%#",[cdListArray objectAtIndex:0].title) ???
IMHO, the simples way in all such cases is valueForKey: and it's brother valueForKeyPath:
Try NSLog(#"%#",((CdObject*)[cdListArray objectAtIndex:0]).title)
You simply cast it to the object you want. If you're paranoid about type casting that way, you can also check the object's class before the cast.
Ex:
NSObject *firstObject = [cdListArray objectAtIndex:0];
if ( [firstObject isKindOfClass:[CdObject class]] )
{
CdObject* cdFirstObject = (CdObject*)firstObject;
NSLog(#"%#", cdFirstObject.title;
}
I think you need to cast:
NSLog(#"%#",[(CdObject *)[cdListArray objectAtIndex:0]] title);
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 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 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]]];
Is it possible to store multiple objects for a single index in an NSArray?
Sure there are many ways to do this with the most common being to assign a dictionary to each array element
Yes, you probably just want to have an NSArray of NSMutableArrays. You can then call something like this:
[[array objectAtIndex:2] addObject:obj];
or
[[array objectAtIndex:2] objectAtIndex:1];
I'm not sure how dynamic you want the multiple objects to be. How about creating a very simple class with properties of the multiple objects?
I was thinking about a struct but I don't think NSArrays like pointer objects.
#import <Foundation/Foundation.h>
#import <AppKit/AppKit.h>
#interface myCompound : NSObject
{
}
#property (nonatomic,strong) NSColor* colour;
#property (nonatomic,strong) NSRegularExpression* expression;
#end
#implementation myCompound
#synthesize colour;
#synthesize expression;
#end
And use this as the element type for NSArray
NSArray<myCompound*>* myArray;
I have declared an NSMutableDictionary object in AppController.h and initialized in the corresponding AppController.m file.
AppController.h
#import <Cocoa/Cocoa.h>
#interface AppController : NSObject {
NSMutableDictionary *uberDict;
}
AppController.m
#import "AppController.h"
#implementation AppController
- (id)init
{
uberDict = [NSMutableDictionary new];
return self;
}
Now I want to use the NSMutableDictionary object in another view, flashcardView. I add/remove items in the dictionary using methods in the AppController class and want to use the same dictionary (with the current items still present in it) in the flashcardView view. The problem is that I don't know how to access the dictionary object from outside AppController. How would I do that?
from flashcardView.m
- (void)setAndCheckString
{
NSArray *keys = [uberDict allKeys];
NSString *i;
for (i in keys) {
string = i;
NSLog(#"%#", string);
}
}
Here's where the problem lies. What do I do with uberDict to make this work? Thanks!
While I encourage you to look at alternative design patterns, to do what you're looking for you simply need to add a method (or property) to access uberDict to AppController. As a property, the code would be:
#interface AppController : NSObject {
NSMutableDictionary *uberDict;
}
#property (readonly) NSMutableArray *uberDict;
#end
in the AppController.h file, and just add a one line #synthesize uberDict; inside the AppContoller implementation (before the #end). Don't worry about the (readonly) -- this means that the object getting the uberDict cannot set it to a new dictionary, but still can modify the contents of the dict and read from it.