Custom NSArray Class definition - objective-c

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])

Related

Question about class member declarations

I`m new to the Objective-C world, so I have a couple of questions about class member declarations. Please notice the comments in the code below:
In header file I have code such
#interface MyClass : NSObject {
//what we points here ? Object or something else ?
NSString *myString;
}
// In interface we declare NSTring *myString in #property declaration is (NSString *) myString.
// What is the difference here ? Why we don`t use the same declaration as above ?
#property(nonatomic, retain) (NSString *) myString;
#end
The thing you're missing is that instance variables (defined between curly braces) are not accessed from the outside (i.e. other objects). To do that - you have to define a property for the instance var (by using #property keyword) to know how outside objects can access a value of given instance var. Also in implementation file (.m) you have to #synthesize instance variable accessor methods for it's appropriate property. Please note that #property declaration not only defines what it holds (NSString *myString), but also how it's being accessed and set. You can define property as read only (#property (readonly)...) or accessible from few threads at a time (#property (nonatomic)).
Also - if your instance var is named differently from the property it represents to other objects - you must show that in implementation file (#synthesize propertyName=instanveVariableName)
update
MyClass *myInstance = [[MyClass alloc] init];
[myInstance myString]; // returns myString property
Try running above 2 lines of code without #property and you'll see the difference.
Actually you are defining a Property of yar class.#interface MyClass : NSObject {
//public object
#public
NSString *myString;
//private object
NSString *myString2;
}
class structure for obj-c
.h file
#interface MyClass : NSObject {
//Your member variable;
// you member objects;
}
//property declarations
//function declarations
#end
so it should look like
#interface MyClass : NSObject {
NSString *str;
}
#property(nanatomic,retain) NSString *str;
-(void)method;
#end

Objective-c setter/getter callback

I have an interface with properties.
I would like to know the way to declare callback to reach its instance's setter or getter.
Is there a way to do it?
Sorry for my english and thx for your answers and time.
If you declared a #property for your instance variable, and then synthesized it in your implementation file, your getter and setter are automatically created for you. Example for a NSMutableArray
#interface ...
{
NSMutableArray *array;
}
#property (nonatomic, retain) NSMutableArray *array;
Then on your implementation:
#implementation ...
#synthesize array;
Once that's done, you can get and set your instance variable values by using:
Getter: self.array OR [self array]
Setter: self.array = ... OR [self setArray:...]
I am not sure if I understand your question correctly but if you are trying to get some code executed every time the setter or getter is invoked there are basically two ways to do that:
1) you can overwrite the synthesized getter and/or setter like this
Header:
#interface ...
{
NSString *example;
}
#property (nonatomic, copy) NSString *example;
Implementation:
#implementation ...
#synthesize aString
-(void)setExample:(NSString *)newExample
{
if (example != newExample)
{
[example autorelease];
example = [newExample copy];
// YOUR CODE HERE
}
}
...and similarly for the getter.
2) you can observe the variable via KVO and get a 'callback' whenever the variable changes. This, of course, only runs you code when the setter is invoked, not the getter.

Accessing NSMutableDictionary Across Classes

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.

#Synthesize array of class objects?

Having some difficulty with what I thought would be straight forward. I am trying to make an array of class objects but running into different problems. The goal was to create one class that held an array of another class of objects.
Any help appreciated:
// Basic class unit
#interface MobRec : NSObject {
NSString *MName;
int Speed;
}
#end
// Master Class holding an array of units
#interface MobDefs : NSObject {
MobRec *MobInfo;
}
#property(retain) MobRec *MobInfo;
#end
#synthesize MobInfo;
1) From reading it seems I should create and NSMutableArray but how do you declare an NSMutableArray of custom class objects? All iterations I try cause errors. Previously I had predefined the size in the class as MobInfo[20]; but that didnt seem to be good for anything.
2) How do you properly #Synthesize an array of class objects?
I think you misunderstand what #synthesize does. It creates accessor methods to get and set the property (i.e., it would create a getter method to return that NSMutableArray and a setter method to allow you to replace it with another NSMutableArray). To create an NSMutableArray, you would just create one like any other object in that class's initializer.
NSMutableArray doesn't have any type checking as you add (or read) from it, so you can add any objects you want to it.
In this case I'd have something like:
// MobRec Class
#interface MobRec : NSObject {
NSString *mName;
int speed;
}
#property(retain)NSString *name;
#property(assign)int speed;
#end
#implementation MobRec
#synthesize mName, speed;
#end
// MobDefs Class
#import "MobRec.h"
#interface MobDefs : NSObject {
NSMutableArray *mobInfo;
}
#property(retain) NSMutableArray *mobInfo;
#end
#implementation MobDefs
#synthesize mobInfo;
- (id)init {
mobInfo = [[NSMutableArray alloc] init];
MobRec *aNewMobRec = [[MobRec alloc] init];
[mobInfo addObject:aNewMobRec];
[aNewMobRec release];
}
I've included the basics for adding to the array as well so you can see how its used. Oh and don't forget you have to release the MobInfo in the dealloc method.
But mostly look at NSMutableArray
Your MobDefs class is not necessary, you can use an NSMutableArray directly. NSArray can hold objects of any type, and is declared in just the same way as any other object (such as your MName property).

Proper way to modify an NSMutableDictionary instance variable?

I have an Objective-C NSMutableDictionary declared inside a class's #interface section, with getter/setter methods, like so:
#interface myClass : NSObject
{
NSMutableDictionary *dict;
}
- (void) setDict: (NSMutableDictionary *) newDict;
- (NSMutableDictionary *) dict;
Inside some of my #implementation methods I want to modify dict. I'd like to stick to standard Obj-C idiom and modify it "properly". Is it OK to modify it like this, using the getter but not the setter:
[[self dict] removeObjectForKey:#"myKey"];
...or is there a better way to do this?
That'll work, but why not do:
[dict removeObjectForKey:#"myKey"];
Inside a class's implementation, you have direct access to the instance variables, and using them directly is idiomatic Objective-C.