I have two view controllers and nibs. I populated one view controller with a toggle switch and declared this in its header file:
#public UISwitch *toggleSwitch;
and exposed it as a property like this:
#property (nonatomic,retain) IBOutlet UISwitch *toggleSwitch;
I also connected the switch with toggleSwitch outlet. Now I want to use this toggleSwitch field in my other view controller, how do I do that? Isn't using #public in the field declaration enough? Please help. Thank you.
No problem at all. Just use the switch like this:
vcWhereYouDeclaredTheSwitch.toggleSwitch.on = YES;
or
BOOL test = [vcWhereYouDeclaredTheSwitch.toggleSwitch isOn];
inside your other view controller.
Here are some general thoughts about propertys:
Memory management : Behind the scenes it will create a setter which creates the variable with correct memory management. It will save you some headaches because you can easily see how the memory management is done (strong/weak and retain/copy/assign).
Accessibility from other classes: if you declare your #property in the .h and #synthesize it in the .m you ivar will be public readable and writeable. You can prevent this with a privat class extension. You even can declare a #property public readonly and declare them internally readwrite via a privat class extension.
Eg: a private property
// [In the implementation file]
#interface MyClass ()
#property (nonatomic, retain) NSMutableArray* someData; // private!!
#end
#implementation MyClass #synthesize someData
#end
Custom getter and setter: If you like you can still write custom getter and setters and you can even just write a getter or setter and let the other one automatically #synthesize. And you can write custom logic into such a getter and setter e.g. you can reload a tableview after a #property has changed.
Automatic Key-Value-Observing (KVO) compliant: If you use or planning to use KVO you get it basically for free by just declaring the property. Nothing else need to be done!
If you need you iVar to be public it is simpler to write one #property than writing a getter and setter for a iVar
With a #property you do not need to declare in iVar (in iOS and 64bit Mac Os X applications). You can do it via the #synthesize:
#synthesize myiVar = _myIvar;
You have made the property of UISwitch. So, you can use it anywhere by using the viewcontroller object.
Suppose you wanna use it in the view where you are currently then use it
self.toggleSwitch
// or
viewControllerObject.toggleSwitch
Related
this is my first post; this site has been an invaluable resource.
I'm fairly new to objective-c so please bear with.
So I have a base class with a few properties which I want "private" so I made them readonly. To be clear, I don't want them mutable externally, but I DO wan't to use the 'set' accessor within this class. So...
// .h file
#interface Vehicle
#property (nonatomic, readonly) int speed;
#end
Also I repeated the property declaration within a category interface block to make the accessors writable in this class
// .m file
//Private properties and methods
#interface Vehicle()
#property (nonatomic, readwrite) int speed;
#end
#implementation
#synthesize speed = _speed;
- (void) someMethod {
[self setSpeed:10]; // Works fine
}
#end
But now if I inherit this class the derived class no longer has the set accessor method (setSpeed in my case). Do I need to synthesize again? Seems like that would defeat the purpose of inheritence. I know i can modify the instance variable directly (_speed = 10;) but would rather not. I'm sure there's something wrong with my understanding. Thanks!
// Example
#interface Ship : Vehicle
#end
#implementation
- (void) someOtherMethod {
[self setSpeed: 2]; // DOES NOT WORK, would like it to
}
#end
But now if I inherit this class the derived class no longer has the set accessor method (setSpeed in my case).
Actually, it does have the set accessor, it's just that the compiler doesn't know about it. You have a choice:
put the class extension (the #interface Vehicle() .... #end bit in a separate header file that gets imported into the .m for Vehicle and its subclasses (or use a category)
redeclare the read/write property in a class extension for the subclass. To avoid a warning, use #dynamic speed in the subclass's implementation.
Since there is no such thing as 'protected' methods, you need to create a private shared header where your anonymous category goes. Then both your original implementation and your derived classes include this header to get access to this 'private' stuff.
I have spent a few days learning Objective-C and have a few questions about #property. I have experience with C# so understand the need for pointers, initialization etc.
So as an example:
#interface MyClass : NSObject
{
IBOutlet UIImageView *image;
}
#property (retain, nonatomic) UIImageView *image
#end
#implementation MyClass
#synthesise image
#end
I understand that #synthesise is used to create the #property. But I have a few questions just to help me clear things up:
Does the #property duplicate or replace my original definition, or does it merely set up the mutibility and atomicity of the original?
Does #synthesise remove my need to use image = [[UIImageView alloc] init]?
If I do not provide a #property and still go ahead creating and destroying my variable manually, does that make any difference?
Ultimately, is the difference between the 2, #property gives you more flexibility with regards to memory management and multi-threading and the normal one gives you the defaults.
Does the #prototype duplicate or replace my original definition, or does it merely set up the mutibility and atomicity of the original?
The ivar declaration of image is redundant when using the most recent compiler releases.
The former declares an ivar (type + name + instance storage).
The property declaration specifies the type, name, storage (in more recent compiler releases), declares the accessor methods (e.g. - (UIImageView *)image; and - (void)setImage:(UIImageView *)pImage;), and other property specifiers (which are used when the accessors are generated by the compiler).
Does #synthesise remove my need to use image = [UIImageView alloc]?
No. You still need to implement your initializer and dealloc (in MRC) appropriately.
If I do not provide an #property and still go ahead creating and destroying my variable manually, does that make any difference?
That would be fine, when you do not want/need boilerplate accessor methods generated for you. It's a design choice. Not every ivar needs accessor methods.
Ultimately, is the difference between the 2, #property gives you more flexibility with regards to memory management and multi-threading and the normal one gives you the defaults.
The biggest reason they exist is convenience. Properties save a lot of boilerplate code.
There is no more flexibility with properties -- properties implement the most practical uses.
It's infrequent that atomicity (in this context) is equivalent to proper thread safety and correct concurrent execution.
1) The property does not replace the class member. A property is a declaration that you want the accessors (getter and setter) for a class member to perform certain "automatic" tasks and have a certain name.
For example:
#interface MyClass : NSObject
{
NSInteger __myInt;
}
#property (assign) NSInteger myInt;
#end
#implementation MyClass
#synthesize myInt=__myInt;
#end
The above code, for all intents and purposes, is causing the following methods to be automatically generated at compile time:
-(NSInteger) myInt
{
return self->__myInt;
}
-(void) setmyInt:(NSInteger)val_
{
self->__myInt = val_;
}
Of course, what happens "in the background" when Xcode compiles your program is a bit different and more nuanced, but this is basically what happens.
2) I'm not entirely clear what you mean by this one... You always need to alloc and init your variables, regardless of accessor synthesis.
3) No. Properties/synthesis are only needed for a) convenience, be it syntactic or atomicity for multithreading, and b) external access to members inside your class.
EDIT:
To clarify on multithreading and properties, declaring a property nonatomic does a great deal for thread safety. This, and my response to #3, addresses your last concern in your question.
You can do this:
#interface MyClass : NSObject
#property (retain, nonatomic) IBOutlet UIImageView *image;
#end
#implementation MyClass
#synthesize image;
#end
Does the #prototype duplicate or replace my original definition, or does it merely set up the mutibility and atomicity of the original?
The property adds things on-top of the ivar like KVO and thread safety if it's atomic.
Does #synthesise remove my need to use image = [UIImageView alloc]?
No
If I do not provide an #property and still go ahead creating and destroying my variable manually, does that make any difference?
If you don't make a property you lose out on the things a property gets you like KVO, it's a judgment and api call on how the variable will be used. Under arc it is much easier to use straight up ivars because you don't have to replicate the retaining and releasing the property did automatically.
The 'image' in #property (retain, nonatomic) UIImageView *image line is just a name of the property and IBOutlet UIImageView *image; is an ivar which you access through self.image. I always name an ivar for property the same as the name but add _ :
UIImage * image_;
#property (retain, nonatomic) UIImageView *image;
#synthesize image = image_;
If you will not create an ivar for your property the Xcode do it automatically for you (the name of the ivar will be the same as the name of property)
If you have a property in your public interface like the following
#interface MyClass : NSObject
#property(strong) NSString *myProp;
#end
And then synthesize it, in effect synthesizing the variable:
#implementation MyClass
#synthesize myProp = _myProp; // or just leave it at the default name..
#end
What is the visibility of the instance variable _myProp? That is, is this considered #public, #protected or #private? I'm guessing since MySubClass could inherit from MyClass then it would also get the properties (naturally), but would it also inherit the instance variable visibility?
What difference does it make if I put the property in a class extension? That would hide the property from subclasses, and I'm guessing the instance variable, too. Is this documented anywhere?
A synthesized ivar is completely invisible to all code that cannot see the #synthesize line (which basically means anything outside of the .m file). It's not #protected, it's not #private, it's simply unknown. With a #private ivar, other code trying to access it will be told that it's private, but with a synthesized ivar, other code trying to access it will be told that the field simply doesn't exist.
As a thought experiment, try imagining a situation where the ivar acted like it was #protected. You make a subclass, and you muck about with the ivar there. Now you go back to the superclass and change #synthesize myProp to #synthesize myProp=foo. What happens in the subclass? When the compiler processes the subclass, it cannot see the #synthesize line, so it would have no idea that you just changed the name of the ivar. In fact, it cannot even tell if the property is backed by an ivar at all, or if it's implemented with custom-written accessor methods. I hope it's obvious why this means that the subclass cannot possibly access the ivar, and neither can any other class.
That said, I'm not quite sure what the compiler does if you write code in the same .m file that tries to access the ivar. I expect it will treat the ivar as #private (since the compiler can, in fact, see that the ivar exists).
Also, none of this has any bearing on the runtime methods. Other classes can still use the obj-c runtime methods to dynamically look up your class's ivar list and muck about with it.
If it is declared in your interface it is virtually public when using the #property declarative. If you want to use #property declaratives and keep them property truly private, you should create a private category in your implementation.
MyClass.h
#interface MyClass : NSObject {
#private
NSObject* foo;
}
#end
MyClass.m
#import "ClassWithPrivateProperty.h"
#interface MyClass ()
#property (nonatomic,retain) NSObject* foo;
#end
#implementation MyClass
#synthesize foo;
// class implementation...
#end
A synthesized variable acts as if declared #private:
#interface Garble : NSObject
#property (copy) NSString * s;
#end
#implementation Garble
#synthesize s;
#end
#interface Bargle : Garble
#end
#implementation Bargle
- (void) useS {
NSLog(#"%#", s); // error: instance variable 's' is private
}
#end
I swear I've seen this in the docs, but I can't find it right now. Will update if I track it down.
You can create a dynamic property and indicate it to the compiler that its instantiation would be at run time.
And then in your subclass write your own getter or synthesize the property.
#interface BaseClass : NSObject
#property (nonatomic, strong) NSString *ThisWillBeSynthesizedInRespectiveSubclasses;
#end
#implementation BaseClass
#dynamic ThisWillBeSynthesizedInRespectiveSubclasses;
#end
In Sub classes
#interface Subclass : BaseClass
#end
#implementation Subclass
#synthesize ThisWillBeSynthesizedInRespectiveSubclasses = _ThisWillBeSynthesizedInRespectiveSubclasses;
#end
or you write your own setter / getter methods.
Hope this helps !
Other classes have access to everything that they #include. In other words, to everything that is inside your header.
If something appears only in your implementation file, other classes (including subclasses) don't know it exists. A synthesized property is like that. Other classes know only about the property (a property means a getter and a setter method) but they don't know anything about the inner implementation of its methods.
Note, that the access specifiers (public/private/protected) in obj-c are only a hint to the compiler that even if something appears in the header file, it can't be accessed. The runtime does not check it in any way.
What happens if you put it into a class extension? Note that a property is a set of two methods. You just hide the methods from every class which includes your class main header but not the class extension header.
We use this for example to declare a property as readonly and in class continuation we declare it as readwrite. Then, we can use the setter only from inside of the class.
I am making a plug-in system for my application. It uses a framework with a class called vertCon, which currently looks like this:
#interface vertCon : NSObject {
NSProgressIndicator *progressBar;
}
/* May not be accessible by child classes */
#property (nonatomic, retain) IBOutlet NSProgressIndicator *progressBar;
/* These two are used by child classes and may not be overridden */
- (void)updateProgessIndicator; // <-- epic spelling fail
- (void)epicFailWithError:(NSError *)error;
#end
(there is one object of a child class of vertCon per progress bar)
How can I do this? Thanks.
You cannot prevent a subclass from overriding the methods. Also, having declared the progressBar property, you also cannot prevent access to your internal NSProgressIndicator reference.
You can prevent access to progressBar if you drop the declared property and declare the ivar as #privaate, as follows:
#interface vertCon : NSObject {
#private
NSProgressIndicator *progressBar;
}
// etc, etc
#end
However I suspect given the IBOutlet declaration that you need the ivar exposed as a property at least to allow setting it up via a xib.
This really is a case where you just have to document the intention (that is, subclasses should make use of, but not override, your update and epicFail methods).
You can put method signatures in your .m file in a private interface. In your case you might put this into vertCon.m:
#interface vertCon (PrivateMethods)
- (void)updateProgessIndicator; // <-- epic spelling fail
- (void)epicFailWithError:(NSError *)error;
#end
If I have a class with some IBOutlets, it seems kind of silly to create accessors for these.
But then I feel like I'm breaking OO practices by not always going through the accessors for instance variables.
I also feel the same way about some instance variables that should not be public, I'd rather not expose the inner workings of some classes. I can make the actual ivars private but the #property shorthand doesn't seem to be able to specify visibility. This leads me to not create accessors and just access the ivars directly. I'm not sure if this is frowned upon though. Is it?
What's the community's thoughts on this admittedly newbie question? (Please ignore dot syntax)
I'm not sure about accessing instance variables directly, I think one shouldn't, but for some variables it just doesn't make sense to use accessors. Like for the IBOutlets you mentioned.
I can only help you out with private accessors. Starting with Objective-C 2.0 you can declare extensions.
Class extensions are like “anonymous”
categories, except that the methods
they declare must be implemented in
the main #implementation block for the
corresponding class.
Just put this extension into a separate header file and you'll have private accessors that aren't visible in the header.
Public/Private
You can declare your iVars as in the #interface file to be readonly, but then re-declare them in a category so that your class can change them. Here's a quick intro to Categories.
An example:
//MyClass.h
#interface MyClass : NSObject {
NSString *name;
}
#property (readonly) NSString *name;
#end
And in the implementation file you can redeclare this:
//MyClass.m
#interface MyClass () //declare the class extension
#property (readwrite, copy) NSString *name; //redeclare the property
#end
#implementation MyClass
#synthesize name;
#end
Now, the name property is readonly external to the class, but can be changed by the class through property syntax or setter/getter syntax.
Really private iVars
If you want to keep iVars really private and only access them directly without going through #property syntax you can declare them with the #private keyword. But then you say "Ah, but they can always get the value outside the class using KVC methods such as setValueForKey:" In which case take a look at the NSKeyValueCoding protocol class method + (BOOL)accessInstanceVariablesDirectly which stops this.
IBOutlets as properties
The recommended way is to use #property and #synthesize. For Mac OS X, you can just declare them as readonly properties. For example:
//MyClass.h
#interface MyClass : NSObject {
NSView *myView;
}
#property (readonly) IBOutlet NSView *myView;
#end
//MyClass.m
#implementation MyClass
#synthesize myView;
#end