Please refer to this image, I have declared property matchResult, why couldn't I access it from its instance?
The other property "score" works, why?
The code runs in iOS6 environment.
Please open image in a new tab if you couldn't see it clearly.
Thanks
It seems that you have defined the property in the implementation file "CardMatchingGame.m",
using a class extension. That means that the property is only available in the #implementation block of this class.
To make the property accessible from other classes, move the declaration to the public #interface in "CardMatchingGame.h".
It is declared within the .m file and therefore not visible from "external". It does not matter that you access it from a method of the same class. You acces an external interface by referring to self.game.matchResult.
If game equals self then you could access self.matchResult. But I do not think it does because you fetch self.game from the array self.cardButtons.
So, you will either use self.matchResult if you are referring to self or you will have to move the property to the interface definition within the .m file.
Related
I have a library that is written in Objective-C and using .m and .h files.
Is it possible for me to write an extension method for that class and get access to a private property that is only defined in the .m file and not defined in the .h file?
I have tried with the .valueForKey but I only get
payload_data_0
payload_data_1
payload_data_2
instance_type
which all are of type Builtin.RawPointer.
No. The only way for you to access it is to define it publicly in the header.
No, technically you can't. The documentation is very clear about this:
Extensions can add new computed properties, but they cannot add stored properties, or add property observers to existing properties.
If you need this for testing purpose, consider moving the private property declaration to a separate header file, like MyClass+Test.h , and have it added to the bridging header. But guess what, this makes those properties public anyways. Not a recommended solution.
I am reading this document to learn objective-C: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html#//apple_ref/doc/uid/TP40011210-CH6-SW1
I the topic "Use Class Extensions to Hide Private Information" (page 73 of pdf) it says:
Class extensions are often used to extend the public interface with additional private methods or properties for use within the implementation of the class itself. It’s common, for example, to define a property as readonly in the interface, but as readwrite in a class extension declared above the implementation, in order that the internal methods of the class can change the property value directly.
What i dont understand in this statement is that since we can change the readonly property from within any private method defined in class extension without that property being re-declared as readwrite in class extension, what does it achieve by re-declaration of that property as readwrite?
You can always change the property through its instance variable (_ivar = ...), but you won't be able to change it using the dot-property syntax (self.myProp =...) unless you redeclare it as readwrite. You will also need to provide additional information like whether the property is strong or weak in this case.
Actually my assumption that "we can change the readonly property from within any private method defined in class extension" is wrong. Class extension cannot use instance variables synthesized automatically for a given readonly property, because they are private (NOT protected) by default.
Even though the document i mention says that instance variable automatically synthesized for a given property has a leading underscore (_Make) in front of it. It actually is not true ( at least not in Xcode 4.6.3 ). It bears the same name has the property itself (unless you synthesize the instance variable itself #synthesize Make = _Make;
Please correct me if i am wrong
I am trying to write an objective-c framework and I would like to have methods and properties visible only within the framework. I know I could define them in a class extension inside the implementation file but then they will not be accessible by other classes.
One way I was thinking to do it was to define a category for example MyClass+Internals and make that header private. but make the MyClass.h header public. I was wondering if there was a better way of doing this. Also, I'm not sure you can define properties within a category I thought it was only methods. Thanks for any suggestions or feedback.
Say you have a class named "Foo", then in "Foo_Framework.h", create:
#interface Foo()
#property ....;
- .... method ....
#end
Then, make sure that "Foo_Framework.h" is imported before the #implementation Foo. That'll cause the class Foo to be compiled with the extended interface found in said header file. That header can then be used throughout your framework. Just don't make it available outside said framework.
You are correct that you can't declare properties (that are synthesized) in a category. That was one of the primary motivations for the creation of class extensions, of which the above is an example.
How do I know when do put my properties and messages in the .h file and when to put them in the .m interface?
I am thinking messages which are public like init should be in the .h file. What about properties which describe the class e.g. configuration type etc.
When you want to restrict access of any property, you can define that in .m file using class extension etc.
There is no as such rule defined for putting properties in .h or .m file, you need to check which properties you want to access outside the class(define those in .h) and which you do want to access outside(define in .m).
According to the Apple docs, one declares properties in "#interface" (.h) files. If you want to have private object only variables, those are called ivars and you wouldn't synthesize accessors to them.
Private properties (or "property redeclaration" in the docs) can be used in things like class extensions or protocols.
there is something I try to understand. I have this object declaration in my AppsController-Class for a Cocoa Application
NSMutableArray *personArray;
In can put this declaration inside the Header file or inside the implementation of the class in the code file. It makes no difference. I can even put it outside the #implementation context right under the #import commands.The Application works just fine.
Since I don't inherit from the AppsController Class or do anything else fancy with it I wonder what might be the difference between these types of declarations?
Where does the declaration really belong?
It depends on how you want to use the variable. If you place the variable declaration inside the interface for your class, each instance of your class will have its own copy of the variable, which is kept separate from all other instances of your class:
#interface AppsController : NSObject
{
NSMutableArray *personArray;
}
Each instance of the AppsController class will have its own copy of the personArray variable, which is separate from all other instances of the class.
If, however, you define the variable outside of the interface, it becomes a global variable, and it is a shared (instances of your class do not get their own copy), and can be accessed from any instance of your class. If you declare it in the header as such:
NSMutableArray *personArray;
it is also visible to methods in other files and classes that include your header.
If you declare the variable in the implementation file, but outside of the implementation itself, and prefix it with the static keyword, the variable will only be visible to the implementation of your class. This is common when you want a variable that is visible to you all of class instances, but not visible to anyone else, and is a way to create class variables.
Since your object is a controller object, I am guessing that you only have one instance of it present in your application. You should declare the variable either:
As an instance variable if your personArray variable needs to be unique to each instance of your controller class (even if you only have one instance now, you may have more than one instance of it in future).
As a class variable (using the static keyword) if you want the variable to be visible to all instances of your class, with only one, shared instance of the variable.
As a global variable if you want the variable to be a single instance (not unique to instances of your class) and also visible to other classes or code in other files.
You should probably put it in the interface section of the header file, that way there will be one instance of it per object instantiated. Which I presume is your intention.
I think if you put it elsewhere it will be treated as a global variable. Ie, there will only ever be one instance of personArray, and it will be visible from anywhere in your application.
Your application is probably working fine, because you only have one instance of your AppsController Class, and no other variables called personArray. If you ever need a second AppsController, or another variable elsewhere called personArray, you'll run into problems.
If you declare the variable in the implementation file, but outside of the implementation itself, and prefix it with the static keyword, the variable will only be visible to the implementation of your class. This is common when you want a variable that is visible to you all of class instances, but not visible to anyone else, and is a way to create class variables.
just to clarify, the reason variables declared inside the implementation file but outside the implementation section are not available outside the class, is because other classes are not aware of anything inside the implementation file. your import statements refer to headers, not their implementations, so they know nothing of those implementation file declarations.
anyway, to create a static variable accessible only by a class, use keyword static when making a declaration in an implementation file. you can put it at the top of the file, at the top of the implementation section, or inside a function, depending on what you want the scope to be.
edited: corrected, thanks peter