Set a variable in a different class - iphone

I am trying to create an application were 2 classes share a variable. Just to keep the code looking a little bit cleaner I created a 3rd class. This "third class" sole job is to house this variable.
In class 3 I put a "get" and "set" method.
SharedURL.H (Class 3)
#interface SharedURL : NSObject {
NSString *theURL;
}
-(NSString *)getTheURL;
-(void)setTheURL:(NSString *)blah;
#property (readwrite, copy) NSString *theURL;
#end
Implementation:
#import "SharedURL.h"
#implementation SharedURL
#synthesize theURL;
-(NSString *)getTheURL;
{
return theURL;
}
-(void)setTheURL:(NSString *)blah;
{
theURL=blah;
}
#end
In classes 1 and 2:
I Import the class header
I set up the instance variable like so
SharedURL *XMLURL;
I define the property like so
#property (readwrite, assign) SharedURL *XMLURL;
Then in the implementation I set the set method like this
[XMLURL setTheURL:#"http://localhost:8888/xml/MyXMLFile.xml"];
However whenever I implement the fallowing code the getter method returns nil.
NSLog(#" the url is %#", [XMLURL getTheURL]);
How can I get this to actually save the variable that I imput and then return it. I'm looking at some sample code and i cannot find my error it looks to me like I am doing it perfectly fine I think I am overlooking something stupid.

If I understand this right you are calling class 3 from either class 1 or 2 (lets say 1) and set the URL then your go to class 2 and and only ask for the URL, right?
I think your problem is that you are calling something that is independent for each object. I think you can fix this by instead of saying -(NSString *)getTheURL and -(void)setTheURL you need to change it to +(NSString *)getTheURL and +(void)setTheURL (in both the .h and .m files) making it not variable dependent.

Related

Declaration/definition of variables locations in ObjectiveC?

Ever since starting to work on iOS apps and objective C I've been really puzzled by the different locations where one could be declaring and defining variables. On one hand we have the traditional C approach, on the other we have the new ObjectiveC directives that add OO on top of that. Could you folks helps me understand the best practice and situations where I'd want to use these locations for my variables and perhaps correct my present understanding?
Here's a sample class (.h and .m):
#import <Foundation/Foundation.h>
// 1) What do I declare here?
#interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
// 3) class-specific method / property declarations
#end
and
#import "SampleClass.h"
// 4) what goes here?
#interface SampleClass()
// 5) private interface, can define private methods and properties here
#end
#implementation SampleClass
{
// 6) define ivars
}
// 7) define methods and synthesize properties from both public and private
// interfaces
#end
My understanding of 1 and 4 is that those are C-style file-based declarations and definitions that have no understanding whatsoever of the concept of class, and thus have to be used exactly how they would be used in C. I've seen them used for implementing static variable-based singletons before. Are there other convenient uses I'm missing?
My take from working with iOS is that ivars have been alost completely phased out outside of the #synthesize directive and thus can be mostly ignored. Is that the case?
Regarding 5: why would I ever want to declare methods in private interfaces? My private class methods seem to compile just fine without a declaration in the interface. Is it mostly for readability?
Thanks a bunch, folks!
I can understand your confusion. Especially since recent updates to Xcode and the new LLVM compiler changed the way ivars and properties can be declared.
Before "modern" Objective-C (in "old" Obj-C 2.0) you didn't have a lot of choices. Instance variables used to be declared in the header between the curly brackets { }:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
#end
You were able to access these variables only in your implementation, but not from other classes. To do that, you had to declare accessor methods, that look something like this:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
- (int)myVar;
- (void)setMyVar:(int)newVar;
#end
// MyClass.m
#implementation MyClass
- (int)myVar {
return myVar;
}
- (void)setMyVar:(int)newVar {
if (newVar != myVar) {
myVar = newVar;
}
}
#end
This way you were able to get and set this instance variable from other classes too, using the usual square bracket syntax to send messages (call methods):
// OtherClass.m
int v = [myClass myVar]; // assuming myClass is an object of type MyClass.
[myClass setMyVar:v+1];
Because manually declaring and implementing every accessor method was quite annoying, #property and #synthesize were introduced to automatically generate the accessor methods:
// MyClass.h
#interface MyClass : NSObject {
int myVar;
}
#property (nonatomic) int myVar;
#end
// MyClass.m
#implementation MyClass
#synthesize myVar;
#end
The result is much clearer and shorter code. The accessor methods will be implemented for you and you can still use the bracket syntax as before. But in addition, you can also use the dot syntax to access properties:
// OtherClass.m
int v = myClass.myVar; // assuming myClass is an object of type MyClass.
myClass.myVar = v+1;
Since Xcode 4.4 you don't have to declare an instance variable yourself anymore and you can skip #synthesize too. If you don't declare an ivar, the compiler will add it for you and it will also generate the accessor methods without you having to use #synthesize.
The default name for the automatically generated ivar is the name or your property starting with an underscore. You can change the generated ivar's name by using #synthesize myVar = iVarName;
// MyClass.h
#interface MyClass : NSObject
#property (nonatomic) int myVar;
#end
// MyClass.m
#implementation MyClass
#end
This will work exactly as the code above. For compatibility reasons you can still declare ivars in the header. But because the only reason why you would want to do that (and not declare a property) is to create a private variable, you can now do that in the implementation file as well and this is the preferred way.
An #interface block in the implementation file is actually an Extension and can be used to forward declare methods (not needed anymore) and to (re)declare properties. You could for instance declare a readonly property in your header.
#property (nonatomic, readonly) myReadOnlyVar;
and redeclare it in your implementation file as readwrite to be able to set it using the property syntax and not only via direct access to the ivar.
As for declaring variables completely outside of any #interface or #implementation block, yes those are plain C variables and work exactly the same.
First, read #DrummerB's answer. It a good overview of the whys and what you should generally do. With that in mind, to your specific questions:
#import <Foundation/Foundation.h>
// 1) What do I declare here?
No actual variable definitions go here (it's technically legal to do so if you know exactly what you're doing, but never do this). You may define several other kinds of things:
typdefs
enums
externs
Externs look like variable declarations, but they're just a promise to actually declare it somewhere else. In ObjC, they should only be used to declare constants, and generally only string constants. For instance:
extern NSString * const MYSomethingHappenedNotification;
You would then in your .m file declare the actual constant:
NSString * const MYSomethingHappenedNotification = #"MYSomethingHappenedNotification";
#interface SampleClass : NSObject
{
// 2) ivar declarations
// Pretty much never used?
}
As noted by DrummerB, this is legacy. Don't put anything here.
// 3) class-specific method / property declarations
#end
Yep.
#import "SampleClass.h"
// 4) what goes here?
External constants, as described above. Also file static variables can go here. These are the equivalent of class variables in other languages.
#interface SampleClass()
// 5) private interface, can define private methods and properties here
#end
Yep
#implementation SampleClass
{
// 6) define ivars
}
But very rarely. Almost always you should allow clang (Xcode) to create the variables for you. The exceptions are usually around non-ObjC ivars (like Core Foundation objects, and especially C++ objects if this is an ObjC++ class), or ivars that have weird storage semantics (like ivars that don't match with a property for some reason).
// 7) define methods and synthesize properties from both public and private
// interfaces
Generally you shouldn't #synthesize anymore. Clang (Xcode) will do it for you, and you should let it.
Over the last few years, things have gotten dramatically simpler. The side-effect is that there are now three different eras (Fragile ABI, Non-fragile ABI, Non-fragile ABI + auto-syntheisze). So when you see the older code, it can be a little confusing. Thus confusion arising from simplicity :D
I'm also pretty new, so hopefully I don't screw anything up.
1 & 4: C-style global variables: they have file wide scope. The difference between the two is that, since they're file wide, the first will be available to anyone importing the header while the second is not.
2: instance variables. Most instance variables are synthesized and retrieved/set through accessors using properties because it makes memory management nice and simple, as well as gives you easy-to-understand dot notation.
6: Implementation ivars are somewhat new. It's a good place to put private ivars, since you want to only expose what's needed in the public header, but subclasses don't inherit them AFAIK.
3 & 7: Public method and property declarations, then implementations.
5: Private interface. I always use private interfaces whenever I can to keep things clean and create a kind of black box effect. If they don't need to know about it, put it there. I also do it for readability, don't know if there are any other reasons.
This is an example of all kinds of variables declared in Objective-C. The variable name indicate its access.
File: Animal.h
#interface Animal : NSObject
{
NSObject *iProtected;
#package
NSObject *iPackage;
#private
NSObject *iPrivate;
#protected
NSObject *iProtected2; // default access. Only visible to subclasses.
#public
NSObject *iPublic;
}
#property (nonatomic,strong) NSObject *iPublic2;
#end
File: Animal.m
#import "Animal.h"
// Same behaviour for categories (x) than for class extensions ().
#interface Animal(){
#public
NSString *iNotVisible;
}
#property (nonatomic,strong) NSObject *iNotVisible2;
#end
#implementation Animal {
#public
NSString *iNotVisible3;
}
-(id) init {
self = [super init];
if (self){
iProtected = #"iProtected";
iPackage = #"iPackage";
iPrivate = #"iPrivate";
iProtected2 = #"iProtected2";
iPublic = #"iPublic";
_iPublic2 = #"iPublic2";
iNotVisible = #"iNotVisible";
_iNotVisible2 = #"iNotVisible2";
iNotVisible3 = #"iNotVisible3";
}
return self;
}
#end
Note that the iNotVisible variables are not visible from any other class. This is a visibility issue, so declaring them with #property or #public doesn't change it.
Inside a constructor it's good practice to access variables declared with #property using underscore instead self to avoid side effects.
Let's try to access the variables.
File: Cow.h
#import "Animal.h"
#interface Cow : Animal
#end
File: Cow.m
#import "Cow.h"
#include <objc/runtime.h>
#implementation Cow
-(id)init {
self=[super init];
if (self){
iProtected = #"iProtected";
iPackage = #"iPackage";
//iPrivate = #"iPrivate"; // compiler error: variable is private
iProtected2 = #"iProtected2";
iPublic = #"iPublic";
self.iPublic2 = #"iPublic2"; // using self because the backing ivar is private
//iNotVisible = #"iNotVisible"; // compiler error: undeclared identifier
//_iNotVisible2 = #"iNotVisible2"; // compiler error: undeclared identifier
//iNotVisible3 = #"iNotVisible3"; // compiler error: undeclared identifier
}
return self;
}
#end
We can still access the not visible variables using the runtime.
File: Cow.m (part 2)
#implementation Cow(blindAcess)
- (void) setIvar:(NSString*)name value:(id)value {
Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
object_setIvar(self, ivar, value);
}
- (id) getIvar:(NSString*)name {
Ivar ivar = class_getInstanceVariable([self class], [name UTF8String]);
id thing = object_getIvar(self, ivar);
return thing;
}
-(void) blindAccess {
[self setIvar:#"iNotVisible" value:#"iMadeVisible"];
[self setIvar:#"_iNotVisible2" value:#"iMadeVisible2"];
[self setIvar:#"iNotVisible3" value:#"iMadeVisible3"];
NSLog(#"\n%# \n%# \n%#",
[self getIvar:#"iNotVisible"],
[self getIvar:#"_iNotVisible2"],
[self getIvar:#"iNotVisible3"]);
}
#end
Let's try to access the not visible variables.
File: main.m
#import "Cow.h"
#import <Foundation/Foundation.h>
int main(int argc, char *argv[]) {
#autoreleasepool {
Cow *cow = [Cow new];
[cow performSelector:#selector(blindAccess)];
}
}
This prints
iMadeVisible
iMadeVisible2
iMadeVisible3
Note that I was able to access the backing ivar _iNotVisible2 which is private to the subclass. In Objective-C all variables can be read or set, even those that are marked #private, no exceptions.
I didn't include associated objects or C variables as they are different birds. As for C variables, any variable defined outside #interface X{} or #implementation X{} is a C variable with file scope and static storage.
I didn't discuss memory management attributes, or readonly/readwrite, getter/setter attributes.

How do i keep my code organised when my app needs a helper class?

I have a few custom UIViewControllers in my app which need to know the string returned of an NSDate. I could copy and paste the same code between these classes, but that's obviously terrible practise. It's also probably not good to put it in 1 class as a method, then have another class add this class to take advantage of it's method. It seems like a messy thing to do. So what would you recommend i do?
To clarify - I need a method which is given an NSDate and returns a string, for use in several other classes.
Sounds like you either need a function, rather than a method:
//Helpers.h
#import <Foundation/Foundation.h>
NSString * makeAStringFromThisDateSomehow(NSDate * d);
//Helpers.m
#import "Helpers.h"
NSString * makeAStringFromThisDateSomehow(NSDate * d)
{
// Body
// of
// your
// function
}
Or to make a category on NSDate to do what you need:
//NSDate+AndrewsCategory.h
#import <Foundation/Foundation.h>
#interface NSDate(AndrewsCategory)
- (NSString *)Andrew_MakeAStringSomehow;
#end
//NSDate+AndrewsCategory.m
#import "NSDate+AndrewsCategory.h"
#implementation NSDate(AndrewsCategory)
- (NSString *)Andrew_MakeAStringSomehow {
// Body
// of
// your
// method
}
#end
Note the stupid prefix on the method name. That's important to keep your method names from colliding with other method names on framework classes. Usually you would use initials: your company's, yours, or the project's.
In either case, just import the relevant header where you need to use the function or method, and you should be hunky-dory.
I'd consider writing a category on NSDate. Categories let you extend the functionality of existing classes with additional methods without having to mess with the existing implementation of the class. So you can add yourMethod to NSDate, and in the future just be able to call [yourDate yourMethod].
To do this in Xcode, just hit ⌘N to create a new file, and choose Objective-C category, then give it some name and make it a category on NSDate.
Then set up your header:
#interface NSDate (YourCategory)
- (NSString *) yourMethod;
#end
And your implementation:
#implementation NSDate (YourCategory)
- (NSString *) yourMethod {
return [NSString stringWithFormat:#"yourMethod on this date: ", [self description]]; // for example
}
#end
Then just include "NSDate+YourCategory.h" in any file where you want to use yourMethod.
i'd recommend adding the method to a catagory and then adding the header to your projects pch file
#ifdef __OBJC__
#import "yourHeader.h"
#endif
if you google for NSDate+Helper that should give you an idea of the implementation.
Nik
It's probably good to put it in 1 class as a method, then have another class add this class to take advantage of it's method.
simple 1 or 2 methods NSObject subclasses won't make slightest differences in execution

Iphone: Replace functions using reflection

I have a small function which I want to rewrite, so that function is valid for every class.
At the moment I have 10 of the same functions which all work same but every function is for another class.
I know, that I have to do it with reflections, but I am not so sure how to do it.
I already read this link:
http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html
The functions I am talking about are:
-(NSCountedSet *)MissionGetReferecedNested:(id)modelObject
{
setOfObjects = [[NSCountedSet alloc]initWithArray:modelObject.MissionSectionList];
return setOfObjects;
}
-(NSCountedSet *)MissionGetSectionReferecedNested:(id)modelObject
{
setOfObjects = [[NSCountedSet alloc]initWithArray:modelObject.DamageAccountList];
return setOfObjects;
}
MissionSectionList and DamageAccountList are both NSMutableArrays from two different classes.
Is it possible to see if a class consists a NSMutableArray and if yes then it should call the .... modelObject.MyMutableArray?
You can use reflection like this:
- (NSCountedSet *)MissionGet:(id)modelObject
{
SEL propertySelector = NULL;
if ([modelObject respondsToSelector:#selector(MissionSectionList)]) {
propertySelector = #selector(MissionSectionList);
} else if ([modelObject respondsToSelector:#selector(DamageAccountList)]) {
propertySelector = #selector(DamageAccountList);
}
if (!propertySelector) {
[NSException raise:#"Invalid modelObject value" format:#"Model object %# does not contain any recognised selectors", modelObject];
}
return [[NSCountedSet alloc] initWithArray:[modelObject performSelector:propertySelector]];
}
But a more common technique among cocoa programmers would be:
- (NSCountedSet *)MissionGet:(id <MyCustomProtocol>)modelObject
{
return [[NSCountedSet alloc] initWithArray:[modelObject missionArray]];
}
Where you would accept any object which confirms to the protocol MyCustomProtocol. The protocol is defined in a header files somewhere, using:
#protocol MyCustomProtocol
#property (readonly) NSArray *missionArray;
#end
And then in each of your classes, declare it as implementing the protocol:
#interface MissionSectionListClass <MyCustomProtocol>
And add a method implementation:
#implementation MissionSectionListClass <MyCustomProtocol>
- (NSArray *)missionArray
{
return self.MissionSectionList;
}
#end
Using protocols is a bit more code, but it's the "right" way to go. It allows you to add support for new classes, without any change to your MissiongGet... method.
More info about protocols: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProtocols.html
EDIT : Cleared all my answer to this :
I think it's not possible to check if a class has a member variable of specified type. You can only check if a class has a specified method.
So, in this case it will be best if you make all your NSMutableArray list the same name, and then create a declared property for this list, and then do a respondsToSelector in your ...GetReferencedNested method.
So, for example, in all of your class create this property :
#property (nonatomic, retain) NSMutableArray * list;
and then in the ..MissionGetReferencedNested method :
if ([modelObject respondsToSelector:#selector(list)])
...
Correct me if i'm wrong...
In terms of style I'd also follow Abhi's suggestion.
But if you really want to inspect a class that you are stuck with and, for example build a NSCountedSet with the first NSMutableArray variable you can find, you could do it like this:
#import "Utilities.h"
#import <Foundation/Foundation.h>
#import <objc/objc-runtime.h>
#implementation Utilities
+ (NSCountedSet*)initCountedSetWithFirstArrayinObject:(id)someObject {
unsigned int c;
Ivar *ivar_arr = class_copyIvarList([someObject class], &c);
for (unsigned int i = 0; i < c; i++) {
if ([#"#\"NSMutableArray\"" isEqualToString:
[NSString stringWithCString:ivar_getTypeEncoding(ivar_arr[i]) encoding:NSUTF8StringEncoding]
]) {
return [[NSCountedSet alloc] initWithArray:object_getIvar(someObject, ivar_arr[i])];
}
}
return nil;
}
#end
Of course this has very limited real world use because it depends on you knowing that the first array will be the one you're interested in.
I think I have to go with the runtime type editing.(http://developer.apple.com/library/mac/#documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html)
The idea with the protocols was good but there I have to change a lot of things in the classes.(which is not possible/allowed) for me. My intension was only to change the functions so that I have only one function for all classes.
I think with the runtime type editing I can check what classes and attributes I have (?) Am I right?
Did somebody already work with runtime type editing?

Class not setting as expected

Icon is set as #property (nonatomic, retain) AHGridIcon *icon;
Usually i just do:
-(void)setIcon:(AHGridIcon *)iconLocal {
icon = iconLocal;
}
But i read a guide to getters setters and properties online which has lead me to believe that instead, this is right:
-(void)setIcon:(AHGridIcon *)iconLocal {
if (iconLocal != self.icon)
{
NSLog(#"local: %#", iconLocal);
NSLog(#"self.icon 1: %#", self.icon);
[iconLocal retain];
[icon release];
icon = iconLocal;
NSLog(#"self.icon 2: %#", self.icon);
}
}
The problem is, the original icon is staying put, it's not being replaced with the new icon. What am i doing wrong? Should i just revert to the usual way i do it?
You should use '#synthesize' unless you really need custom setter behavior.
like I posted in my comment:
the best way is to use #synthesize which will create a getter and a setter to with respect to the properties you wrote in your property (nonatomic, retain) => not threadsafe but fast getter and setter and a retaining (and also releasing) setter. If you dont need sophisticating stuff to do in your setter then you should not override the setter.
.h:
#property (nonatomic, retain) AHGridIcon *icon;
.m:
#implementation Something
#synthesize icon;
...
#end
The code you posted in your setter is nearly the same as the compiler would produce when only using synthesize.
Your usual way is not really nice because in your header is defined (in your property) that the setter is retaining but in your implementation you are overriding that correct setter which doesn't retain. It is nearly the same as the compiler would produce with an (nonatomic, assign) property.
But if you want to override your setter then it should look like the same as you wrote. For me it is working fine.
first retaining the new object
then releasing the old one
then assigning the local pointer to your new object
you can even omit your if but then it is really important that you first retain the new and then release the old objects (like you did - just want to mention that).
For solving your problem with an overriten setter: Your setter looks ok in my eyes. Have you also overriten the getter? If yes then post it here (you use it by calling self.icon in your log-call).
I've done a small test-program
#synthesize str;
- (void)setStr:(NSString *)localStr
{
if(str != localStr)
{
NSLog(#"old : %#", self.str);
NSLog(#"new1: %#", localStr);
[localStr retain];
[str release];
str = localStr;
NSLog(#"new2: %#", self.str);
}
}
and the output is fine:
old : (null)
new1: Hello
new2: Hello
old : Hello
new1: World
new2: World

Design issue in Iphone Dev - Generic implementation for Game Bonuses

So, I thought consulting you guys about my design, cause I sense there might be a better way of doing it.
I need to implement game bonuses mechanism in my app.
Currently there are 9 bonuses available, each one is based of different param of the MainGame Object.
What I had in mind was at app startup to initialize 9 objects of GameBonus while each one will have different SEL (shouldBonus) which will be responsible for checking if the bonus is valid.
So, every end of game I will just run over the bonuses array and call the isBonusValid() function with the MainGame object(which is different after every game).
How's that sound ?
The only issue I have currently, is that I need to make sure that if some bonuses are accepted some other won't (inner stuff)... any advice how to do that and still maintain generic implementation ?
#interface GameBonus : NSObject {
int bonusId;
NSString* name;
NSString* description;
UIImage* img;
SEL shouldBonus;
}
#implementation GameBonus
-(BOOL) isBonusValid(MainGame*)mainGame
{
[self shouldBonus:mainGame];
}
#end
Sounds ok, the only change I would consider is perhaps removing a bonus from the array should it be acepted. That way it is not checked in the future. This would also work for bonus that for other reason should no longer be available.
Whether or not the player can obtain a particular bonus according to the rules of your game isn't something the individual bonuses would know about. This is something the game itself would know. For example, you may have one game that allows bonuses A and B together, but another game that wouldn't.
So the logic to grant or deny a bonus should be in the MainGame object. I would organize it so that GameBonus is a plain bit bucket class and the logic is all in the MainGame. MainGame would be a superclass of any other custom games that might want to override the bonus logic.
A starting point:
typedef enum {
BonusTypeA, BonusTypeB, BonusTypeC
} BonusId;
#interface GameBonus : NSObject {
BonusId bonusId;
NSString *name;
NSString *description;
UIImage *img;
}
#property (nonatomic,assign) BonusId bonusId;
#property (nonatomic,retain) NSString *name;
#property (nonatomic,retain) NSString *description;
#property (nonatomic,retain) NSString *img;
#end
#interface MainGame : NSObject {
NSMutableSet *activeBonuses;
}
-(BOOL) tryToSetBonus:(BonusId)bonus; // tries to set, returns YES if successful.
-(BOOL) isBonusValid:(BonusId)bonus; // has no side effect, just check validity.
#end