I'd like to store objective-c block in a property for later use. I wasn't sure how to do it so I googled a bit and there is very little info about the subject. But I've managed to find the solution eventually and I've thought that it might be worth sharing for other newbies like me.
Initially I've thought that I would need to write the properties by hand to use Block_copy & Block_release.
Fortunately I've found out that blocks are NSObjects and - copy/- release is equivalent to Block_copy/Block_release. So I can use #property (copy) to auto generate setters & getters.
Edit: updated for ARC
typedef void(^MyCustomBlock)(void);
#interface MyClass : NSObject
#property (nonatomic, copy) MyCustomBlock customBlock;
#end
#implementation MyClass
#end
MyClass * c = [[MyClass alloc] init];
c.customBlock = ^{
NSLog(#"hello.....");
}
c.customBlock();
Alternatively, without the typedef
#property (copy, nonatomic) void (^selectionHandler) (NSDictionary*) ;
You can find a very good explanation of this in WWDC 2012 session 712 starting in page 83. The correct way of saving a block under ARC is the following:
#property(strong) my_block_type work;
Be careful with the retain cycles. A good way to solve is set the block to nil when you do not need it anymore:
self.work = nil;
Related
In ARC, I want an atomic property for multi-thread access:
#interface MyClass
#property (atomic, strong) NSString *myString;
#end
I also want a custom setter and getter for various reasons, like debugging or tracking.
Solution A, I override the setter and getter:
#implementation MyClass
#synthesize myString = _myString;
static int i;
- (void)setMyString:(NSString *)myString
{
_myString = myString;
NSLog(#"%d", i++);
}
- (NSString *)myString
{
return _myString;
}
#end
Solution B, I extend the class interface to have a different synthesized property:
#interface MyClass ()
#property (atomic, strong) NSString *myPrivateString;
#end
#implementation MyClass
#synthesize myPrivateString = _myPrivateString;
static int i;
- (void)setMyString:(NSString *)myString
{
_myPrivateString = myString;
NSLog(#"%d", i++);
}
- (NSString *)myString
{
return _myPrivateString;
}
#end
Is solution A atomic? Is solution B atomic? If none of them are atomic, should I use objc_setProperty and objc_getProperty, or should I use #synchronized(self), or is there a better locking mechanism to avoid locking self?
(sub-question: in case B, getting or setting _myPrivateString directly is as safe as getting or setting self.myPrivateString or not as safe?)
Is solution A atomic?
No, it's not. As you are providing a custom version of the getter/setter methods, you'll also need to provide the locking mechanism. Using #synchronized(self) will work, however if there is high contention for this property, you might want to create a locking object for each property. That's unlikely, however.
Is solution B atomic?
Yes it is, however be sure to use self.myPrivateString = myString; to ensure you access the getter/setter methods, where the locking is implemented.
I would recommend using solution A as it's simple, which is always good.
Because you are using an instance variable without a leading underscore, you have fallen into the trap of actually accessing the instance variable instead of the accessor method. When you access the instance variable, "atomic" won't do _anything" for you. Anyone with any Objective-C experience will advice you very, very strongly not to use instance variables without the leading underscore. Just remove the #synthesize (so you built yourself a trap, fell into it, and you actually did extra work to do so).
So none of your solutions is in any way atomic.
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)
I saw in the libraries for use cocos2d strange #property and #synthesize
Standard in the examples is written as follows:
in .h
CGFloat minimumTouchLengthToSlide;
}
#property(readwrite, assign) CGFloat minimumTouchLengthToSlide;
in .m
#synthesize minimumTouchLengthToSlide
But in lib https://github.com/cocos2d/cocos2d-iphone-extensions/tree/master/Extensions/CCScrollLayer and another libs\extensions
in .h
CGFloat minimumTouchLengthToSlide_;
}
#property(readwrite, assign) CGFloat minimumTouchLengthToSlide;
in .m
#synthesize minimumTouchLengthToSlide = minimumTouchLengthToSlide_;
What is the meaning of this code?
Why they changed minimumTouchLengthToSlide to minimumTouchLengthToSlide_ and added minimumTouchLengthToSlide = minimumTouchLengthToSlide_;
Its often considered good practice to name the instance variable different from the property. The resoning behind this is that in that case you cannot accidently use the instance variable instead of the property. This is not that important when using value types such as integers and floats but more important when using reference types on retain properties. Consider a property
#property (nonatomic, retain) NSString *myString;
...
#synthesize myString;
The compiler takes care of retaining the string when you do self.myString = someString. But when you write myString = someString you do not actually use the property but rather the variable directly and no retaining will take place. This can lead to zombies, leaks etc. By giving the instance variable a different name like this:
#property (nonatomic, retain) NSString *myString;
...
#synthesize myString = myString_;
you can no longer write myString = someString because this would issue a compiler error. If you needed to use the instance variable directly you could always write _myString = someString but in practice this is rarely needed.
There are other cases when you write explicit property methods but the issue is basically the same, you cannot accidently bypass the property methods when using the second variant.
So basically this is a method to avoid unnecessary errors when handling properties (mostly retain-properties).
#property and #synthesize are a really cool feature of Objective-C to allow the automatic creation of getter and setter methods. In your examples they would create:
- (CGFloat)minimumTouchLengthToSlide and
- (void)setMinimumTouchLengthToSlide:(CGFloat)newLength; for free.
#synthesize minimumTouchLengthToSlide = minimumTouchLengthToSlide_ means they are telling Objective-C that when someone tries to access that property, then it should point at the instance variable minimumTouchLengthToSlide_
readwrite,assign describe what happens when someone sets the property. Assign means that the value is not retained, the variable is just pointed. An example of what that method might look like could be this:
- (void)setMinimumLengthToSlide:(CGFloat)newLength {
[self willChangeValueForKey:#"minimumLengthToSlide"]; // let observers know this property is changing
minimumLengthToSlide_ = newLength;
[self didChangeValueForKey:#"minimumLenghtToSlide"];
}
You can read more about them here.
I read some tutorials here about properties ,but i still have some doubts to clarify, is there a difference between
#interface MyClass : NSObject {
}
#property(nonatomic,retain) NSString *temp;
#end
AND
#interface MyClass : NSObject {
NSString *temp;
}
#property(nonatomic,retain) NSString *temp;
#end
The difference is that in the first version, the compiler will automatically create an instance variable (IIRC, it will be named _temp but I don't know for sure). This is only supported on iOS and Mac 64 bit.
In the second example, you provide the variable.
There's actually a way to tell the compiler which variable to use for the property, which I use a lot:
#interface MyClass : NSObject {
NSString *temp_;
}
#property(nonatomic,retain) NSString *temp;
#end
#implementation MyClass
#synthesize temp = temp_;
#end
This way the variable and the property have different names and you can't confuse them (e.g. by forgetting to prefix self.).
Minor side-note: it's often desirable to use copy instead of retain for NSString *, since you might assign an NSMutableString * to the property. Now if you would change that mutable string unexpected things might happen.
Does the first one even work? If there is no instance variable its a bit hard to have a property to access it.
#properties are meant for you, so you can be lazy, they write the following 2 methods for you ( if not set to readonly ):
- (void)setYourVariable:(id)new;
- (id)yourVariable;
it also allows you to use "someClass.itsVariable;" instead of "[someClass itsVariable];"
Another thing, when you create your header files make sure that the biggest variables ( like pointers ) are on the top and the smallest on the bottom, this saves ram.
thus:
NSObject *someObject;
NSObject *someOtherObject;
int anInt;
short aShort;
BOOL fakeBool;
instead of:
BOOL fakeBool;
NSObject *someObject;
short aShort;
NSObject *someOtherObject;
int anInt;
This has to do with the compiler, you can check this by using sizeof()
In the modern runtime (Objective-C 2.0) it is the same because the compiler will generate the variable for you. See Question about #synthesize
Quoting The Objective-C Programming Language > Declared Properties > Property Implementation Directives:
There are differences in the behavior of accessor synthesis that
depend on the runtime:
For the legacy runtimes, instance variables must already be declared in the #interface block of the current class. If an instance
variable of the same name as the property exists, and if its type is
compatible with the property’s type, it is used—otherwise, you get a
compiler error.
For the modern runtimes, instance variables are synthesized as needed. If an instance variable of the same name already exists, it is
used.
The practical difference that I've found is that the debugger doesn't appear to show you the value of properties, just instance variables.
Therefore, your first example, which (assuming you use the #synthesize directive to create your getter/setter) automatically creates the ivar, will not have a value that you can easily retrieve during debug. You'll end up having to send a lot of NSLog messages, rather than just looking at the values while stepping through your code.
As an aside, which seems to relate to this topic, I typically prepend my ivars with "iv" and change my color settings in XCode preferences so that I'm never unsure whether I'm accessing a property or an ivar.
Example
#interface MyClass : NSObject {
NSString *ivName;
NSString *ivTitle;
}
#property (nonatomic, copy) NSString *Name;
#property (nonatomic, copy) NSString *Title;
#end
Now, this then requires a small trick (to tie the two together) when synthesizing the properties, which I show below:
#implementation MyClass
#synthesize Name = ivName;
#synthesize Title = ivTitle;
This way, it's always very easy for me to know exactly what's going on at a glance. Yes, context can also tell you whether you're accessing an ivar/property, but why not make it easier?
I tend to use properties exclusively in my classes, especially now that you can declare properties in a class extension thanks to the modern Objective-C 2.0 runtime—I use this feature to create "private" properties.
My question is if there is any good reason to ever declare ivars in a class interface anymore. I prefer my public-facing interfaces to be as minimal and clean as possible, only revealing aspects of my class that are pertinent.
For example, I would tend to do the following:
MyClass.h:
#interface MyClass : NSObject
#property (nonatomic, copy) NSString * publicString;
#property (nonatomic, copy, readonly) NSString * readOnlyString;
#end
MyClass.m:
#interface MyClass ()
#property (nonatomic, copy, readwrite) NSString * readOnlyString;
#property (nonatomic, copy) NSString * privateString;
#end
#implementation MyClass
#synthesize publicString = publicString_;
#synthesize readOnlyString = readOnlyString_;
#synthesize privateString = privateString_;
- (void)init
{
self = [super init];
if (self != nil)
{
self.publicString = #"Public String";
self.readOnlyString = #"Read-Only String";
self.privateString = #"Private String";
}
return self;
}
- (void)dealloc
{
[publicString_ release];
[readOnlyString_ release];
[privateString_ release];
[super dealloc];
}
#end
Code style preferences aside, are there any issues with avoiding ivars entirely like this?
I may have found an answer that's suitable enough for me to explicitly back my properties with ivars. It doesn't appear as if the debugger will list any automatically synthesized ivars, so there's no way to just drill through self during debugging and check various values other than manually calling the property accessors, which is tedious. Unless they change this, this is probably more than enough reason for me to just go back to declaring ivars explicitly.
The main issue, if it bothers you at all, is that per Cocoa With Love, dynamic instance variables such as those you're using aren't supported by runtimes other than those for 64bit Intel/PowerPC (fixed per Chuck's comment below) and ARM (for iOS).
I'm not currently able to find an authoritative Apple document on the issue; note that restricting to the latest OS X, v10.6, is not sufficient since it is available for and supported on the 32bit Intel machines that Apple shipped immediately after switching from PowerPC.
Late extra thought: without knowing about any potential changes in Xcode 4, a good reason to declare otherwise private instance variables within the header file is to mark them as IBOutlets and wire them up graphically. That's really only relevant to a very specific type of class and member variable though, admittedly.
I have to agree with LucasTizma on the debugging issue.
When I began using XCode4, I started not explicitly declaring ivars and let them be created for me using #synthesize aVar = _aVar syntax. While trying to debug code, I noticed that I couldn't hover the cursor over the variable and see its value.
For me, this is just unacceptable. I guess it's back to declaring them explicitly.
Beyond Tommy's concern, declaring an ivar is certainly good practice, especially if your code might be reused or if you might come back to your code sometime.