I am working with MapKit and want to be able to add a (NSString *)itemTag value to each of my annotations. I have created myAnnotiation.m and myAnnotation.h
I tried adding itemTag to the myAnnotation.h/m but when I try to access currentAnnotation.itemTag within my main code, it says "itemID not found in protocols" - so I went to the MapKit.Framework and into MKAnnotation.h. I added (NSString *)itemID, but when I save the .h file in the Framework, it changes the file's icon and doesn't appear to by jiving with everything else.
Any help or links to help would be greatly appreciated. I am not even sure if I'm on the right path here, but Googling "modify iphone sdk framework" does not turn up much.
Why are you trying to modify the framework? You should be defining itemID as a property or instance variable (or both) in myAnnotation.h. You say that currentAnnotation.itemTag
didn't work; for that to work, you need to have itemTag defined as a property of whatever class currentAnnotation belongs to.
Changing the header file for the framework won't recompile it, so you won't be able to get that to work.
EDIT: Here's an example.
In MyAnnotation.h:
#interface MyAnnotation : NSObject <MKAnnotation> {
NSString *itemID;
// Other instance variables
}
#property (nonatomic, retain) NSString *itemID;
// Class and instance methods.
#end
In MyAnnotation.m:
#implementation MyAnnotation
#synthesize itemID;
// Your code here.
#end
The #property call defines the property and the #synthesize call will create setters and getters for you (methods to set and retrieve the value of itemID). In MyAnnotation.m, you can use self.itemID or [self itemID] to get the value of itemID, and you can use self.itemID = #"something" or [self setItemID:#"Something"] to set the value.
EDIT 2:
When you get currentAnnotation, if the compiler doesn't know that the annotation is an instance of your MyAnnotation class, it won't know about itemID. So, first ensure that you've included this line at the beginning of your .m file:
#import MyAnnotation.h
That wil ensure that the compiler knows about the class. When you use currentAnnotation, you cast it as an instance of MyAnnotation like so:
(MyAnnotation*)currentAnnotation
That should quiet down the warnings.
Related
I am creating an iPhone custom framework which should be able to be integrated into any iPhone app.
I have created some properties in one of the public header files of my framework. I want to give #package level access to those properties, so that those properties can be accessed only with in the classes inside the framework.
I do not want the user to use those properties.
Please tell me whether doing this is possible. If yes, please give me some idea on how to achieve this!.
First you should know that there is no way to completely forbid a user of your library to call a method. Even if you don't declare it in your header, a user could declare it on its own and use it. He would still have to find out the name of your property though, for instance by running classdump on your library.
Therefore in Objective-C, we make properties private by not declaring them in the header (which is the public part of your class), but by declaring them in the implementation (which is the "private" part of your class).
If you create another header which contains a category on your class, you can add some properties to it that will not be in the main header - so not on the public declaration of your class - but that can still be imported by other classes of your library that know about this header.
For instance:
MyClass+SecretProperties.h:
#interface MyClass ()
#property (strong) NSString *secretString;
#end
MyClass.m:
#import "MyClass.h"
#import "MyClass+SecretProperties.h"
#implementation MyClass
#synthesize secretString; // Depending on your runtime, you may not even need to this - properties are auto-synthesized in the latest SDKs.
…
#end
OtherClass.m:
#import "MyClass.h"
#import "MyClass+SecretProperties.h"
// Now you can use secretString on instances of MyClass
Then since you only export MyClass.h with your library, users have no idea that there is a secretString property :) This is the closest you can get to a #package scope AFAIK.
If you want to make those property as private then use below things.
In your .m file use extension characteristics of objective c.
#interface InitialViewController ()
//declare your property here
#end
In Objective C you can now use #property and #synthesize to auto generate get and set methods. My question is: Do I still need to declare the property in the interface? My program compiles and runs fine without it. But most books and other examples still have it. Why?
#interface Person : NSObject {
// do i need the declaration "NSString name;"? why?
// i have notice that my program works fine without it.
// but many programming examples still incude it.
// NSString name;
}
#property NSString *name;
#end
#implementation Person
#synthesize name;
#end
This depends on runtime. Modern runtime is used in iOS and you don't have to declade ivars. This is not always the case in OS X though. See here - http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtVersionsPlatforms.html
What you're talking about is the ivar. You do not need to declare it as the #synthesize adds it for you. This did not use to be the case on older compilers (and obviously before #propertiy was added to the language), thus a lot of people and books still do.
PS: You also do not need the {...} if you don't have any ivars, e.g.:
#interface Person : NSObject
#property NSString *name;
//...
You do not need to; the ivar will be generated for you. But the debugger won't show you auto-generated ivars, so I like to declare them anyways.
You don't need to declare the ivar. The #synthesize directive does it for you if you omit the ivar.
I see some examples sometimes would declare a property as well as variable other times they do not .e.g. some time I see code like this
#interface Test : NSObject
{
UIProgressView* _progressView;
}
#property (nonatomic,retain)UIProgressView* progressView;
#end
at other times I will come across
#interface Test : NSObject
#property (nonatomic,retain)UIProgressView* progressView;
#end
Why what are the reasons ? I am learning and almost always use property and variable both.
I have used UIProgressView just as example.
Using ivars instead properties is only useful if you want #protected access (access from subclasses only), or support the old runtime (which required both).
It depends whether the property is synthesized against an iVar or derived in some other way (or against another iVar).
IF we have an instance of the class - i.e:
Test *myTest = [[Test alloc] init];
Then basically the property declaration
#property (nonatomic,retain)UIProgressView* progressView;
is telling anyone interested in using the interface that they can access the following two functions on an instance of this class:
[myTest progressBar];
[myTest setProgressBar:aProgressBar];
And objective C also lets you use shorthand notation:
myTest.progressBar =
xxx = myTest.progressBar
which does exactly the same thing.
It is not necessary for these two methods to be implemented via an iVar of the same name as the property, or even via an iVar at all (they could do even do a database fetch or derive the value).
If you #synthesize the property (which means you want the precompiler to generate the above methods for you) and don't explicitly specify an iVar on the #synthesize directive, then the methods described above will automatically be generated (due to the synthesize method) to set or get the value to/from an iVar of the same name as the property (and the implementation will include retain/release logic depending on the property directive.
If you don't #synthesize the property then you provide your own implementation and it can be anything you want. It is also possible to #synthesize the property but include a directive to use a different iVar in the method definition:
#synthesize progressBar=someOtheriVar;
in which case you will not see an iVar of the same name as the property in the header file either.
I have a simple question:
I have a NSManagedObject subclass that I've been using for some time and it was working perfectly fine.
Today I added a new property to it with the corresponding iVar. The property is a simple (nonatomic,retain) NSString *.
And as normal i added #synthesize to the property to generate setter and getter functions.
However, there is no way i can use the newly defined property!!! I keep getting "property not found on object of type" error and my build fails.
Here are a few chunks of code that will clear things out:
//import the core data header first CoreData/CoreData.h
#interface Contact : NSManagedObject
{
NSString *contactID;
NSString *firstName;
NSString *myDevMod;
}
#property (nonatomic,retain) NSString *contactID;
#property (nonatomic,retain) NSString *firstName;
#property (nonatomic,retain) NSString *myDevMod;
#end
and the corresponding .m implementation:
#import "Contact.h"
#implementation Contact
#synthesize contactID, firstName, myDevMod;
and the code that uses the Contact class:
#import "Contact.h" //at the start
Contact *aContact = [[Contact alloc] init];
aContact.contactID = someId; //works perfectly fine
aContact.firstName = someName; //works perfectly fine
aContact.myDevMod = #""; //THIS IS WHERE THE ERROR OCCURS!!
[aContact doSomethingHere];
[aContact release];
What do you think could be the error??
Thanks in advance for your support.
Weirdly the site won't let me add a comment so :
comment:
Sounds odd. First thing I'd try is removing the #property lines and #synthesize line - so the getters and setters are created automagically. Also try: aContact.myDevMod = someName; to see if that actually works - might shed some light.
I had exact the same problem last night. It took me about 5 hours to fix that. My first attempts were to create the model classes again with menue Editor -> Create NSManagedObject Subclass...
But that didn´t help. Even if i had deleted the classes beforehand Xcode did not recognize the properties. I´ve deleted the model as well and rebuild it with same name. And created the NSManagedObject Subclasses again. Didn't help. Then i´ve deleted the model and the MOS again and build it up from scratch! But with different names! Took me again a long time to change my code but after that everthing seemed to be normal. Now i can add, change and delete attributes in the model and the properties NSManagedObject Subclasses and Xcode recognizes them again.
But boy, it almost drove me nuts!!! And i still don't know what happend!
My experience is that it isn't the model or the objects that need to be recreated.
Most of the time you can recreate the file you are working in. Make a new NSView of what every .h and .m file and copy the info over to the new file, and it will work.
I wonder if I'm doing something completely stupid here... I'm clearly missing something. I've gotten used to the pattern of defining properties of a custom class, however I seem to be hitting a point where extended classes do not recognize new properties. Case of point, here's my header file:
#import <UIKit/UIKit.h>
#import "MyTableViewController.h"
#interface MyRootController : MyTableViewController {
NSMutableArray *sectionList;
}
#property (nonatomic, retain) NSMutableArray *sectionList;
#end
Now, for some reason that "sectionList" property is not turning green within my interface file (ie: it's not being recognized as custom property it seems). As a result, I'm getting all kinds of errors down in my implementation. The first is right at the top of my implementation where I try to synthesize the property:
#import "MyRootController.h"
#implementation MyRootController
#synthesize sectionList;
That synthesize line throws the error "No declaration of property 'sectionList' found in the interface". So, this is really confusing. I'm clearly doing something wrong, although I can't put my finger on what.
One thought: I am extending another custom class of my own. Do I need to specify some kind of super-class declaration to keep the architecture from getting sealed one level up?
Drat, it was a pathing issue. I still haven't figured out quite how XCode decides what folder to place new files into... and when two joined files end up in different folders, things don't work. Thanks for the reply, fbrereto.