There is a conceptual overview of Blocks objects in objective-c within this Apple reference:
http://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Blocks/Blocks.pdf
However, it does not really explain two topics that concern me and may concern other people. The first question is like that: can I assign a nil to a Block reference? Or should I use NULL? Or can I use neither of them?
The second problem lies in the sphere of memory management. Say, I have declared such a method creating a block object on the stack.
-(void)makeTheClass
{
TheClass *object = [[TheClass alloc] init];
object.blockReference = ^(void) { return nil; }
}
This object, being created within some scope, is going to be destroyed after it goes out of it. But TheClass object is actually going to store a reference to this (nearly destroyed) Block:
typedef id (^WeirdBlockType)(void);
#interface TheClass {
WeirdBlockType blockReference;
}
How do I declare a class property for such a block?
What's the difference between these two:
#property (nonatomic, retain) WeirdBlockType blockReference;
#property (nonatomic, copy) WeirdBlockType blockReference;
?
It is clearly said in the Apple documentation that block copying moves the block to the heap. But what if I just retain it? Is it going to be destroyed after it goes out of makeTheClass method scope?
Well I've found the solution.
Thanks to Gojan for his answer, but he was actually wrong in one place:
Wevah was right. Retain on a block has no effect until it is completely moved to the heap, and only Block_copy accomplishes such a task.
Perhaps blocks are not the only objects that cannot be retained while they are on the stack; but whilst you create (alloc and init) any NSObject subclass instances on the heap by default, you don't care about it - retain works as usual. Block objects are created on the stack by default, that's why the work a little unexpectedly.
Thanks everybody!
can I assign a nil to a Block
reference? Or should I use NULL?
nil can be read as "an empty id type" and NULL is defined like ((void *)0). The difference here is the context. If you are working with NSObject's based objects you should use nil.
In the case of blocks you should use nil because you can interact with the block like if it was an NSObject (you can retain it, release it, etc). But if you use NULL it should work.
How do I declare a class property for
such a block? What's the difference
between these two:
#property (nonatomic, retain) WeirdBlockType blockReference;
#property (nonatomic, copy) WeirdBlockType blockReference;
?
In the documentation says:
If you are using Objective-C, you can
send a block copy, retain, and release
(and autorelease) messages.
So both declarations are valid, but if you ask my I prefer retain than copy.
In conclusion:
Blocks are treated like objects defined and instantiated at the same time (runtime) so after you get a perdurable reference to it you can think that reference like any other object.
Related
As someone that's new to Objective-C can someone give me an overview of the retain, assign, copy and any others I'm missing, that follow the #property directive? What are they doing and why would I want to use one over another?
Before you know about the attributes of #property, you should know what is the use of #property.
#property offers a way to define the information that a class is intended to encapsulate.
If you declare an object/variable using #property, then that object/variable will be accessible to other classes importing its class.
If you declare an object using #property in the header file, then you have to synthesize it using #synthesize in the implementation file. This makes the object KVC compliant. By default, compiler will synthesize accessor methods for this object.
accessor methods are : setter and getter.
Example:
.h
#interface XYZClass : NSObject
#property (nonatomic, retain) NSString *name;
#end
.m
#implementation XYZClass
#synthesize name;
#end
Now the compiler will synthesize accessor methods for name.
XYZClass *obj=[[XYZClass alloc]init];
NSString *name1=[obj name]; // get 'name'
[obj setName:#"liza"]; // first letter of 'name' becomes capital in setter method
List of attributes of #property
atomic, nonatomic, retain, copy, readonly, readwrite, assign, strong, getter=method, setter=method, unsafe_unretained
atomic is the default behavior. If an object is declared as atomic then it becomes thread-safe. Thread-safe means, at a time only one thread of a particular instance of that class can have the control over that object.
If the thread is performing getter method then other thread cannot perform setter method on that object. It is slow.
#property NSString *name; //by default atomic`
#property (atomic)NSString *name; // explicitly declared atomic`
nonatomic is not thread-safe. You can use the nonatomic property attribute to specify that synthesized accessors simply set or return a value directly, with no guarantees about what happens if that same value is accessed simultaneously from different threads.
For this reason, it’s faster to access a nonatomic property than an atomic one.
#property (nonatomic)NSString *name;
retain is required when the attribute is a pointer to an object.
The setter method will increase retain count of the object, so that it will occupy memory in autorelease pool.
#property (retain)NSString *name;
copy If you use copy, you can't use retain. Using copy instance of the class will contain its own copy.
Even if a mutable string is set and subsequently changed, the instance captures whatever value it has at the time it is set. No setter and getter methods will be synthesized.
#property (copy) NSString *name;
now,
NSMutableString *nameString = [NSMutableString stringWithString:#"Liza"];
xyzObj.name = nameString;
[nameString appendString:#"Pizza"];
name will remain unaffected.
readonly If you don't want to allow the property to be changed via setter method, you can declare the property readonly.
Compiler will generate a getter, but not a setter.
#property (readonly) NSString *name;
readwrite is the default behavior. You don't need to specify readwrite attribute explicitly.
It is opposite of readonly.
#property (readwrite) NSString *name;
assign will generate a setter which assigns the value to the instance variable directly, rather than copying or retaining it. This is best for primitive types like NSInteger and CGFloat, or objects you don't directly own, such as delegates.
Keep in mind retain and assign are basically interchangeable when garbage collection is enabled.
#property (assign) NSInteger year;
strong is a replacement for retain.
It comes with ARC.
#property (nonatomic, strong) AVPlayer *player;
getter=method If you want to use a different name for a getter method, it’s possible to specify a custom name by adding attributes to the property.
In the case of Boolean properties (properties that have a YES or NO value), it’s customary for the getter method to start with the word “is”
#property (getter=isFinished) BOOL finished;
setter=method If you want to use a different name for a setter method, it’s possible to specify a custom name by adding attributes to the property.
The method should end with a colon.
#property(setter = boolBool:) BOOL finished;
unsafe_unretained There are a few classes in Cocoa and Cocoa Touch that don’t yet support weak references, which means you can’t declare a weak property or weak local variable to keep track of them. These classes include NSTextView, NSFont and NSColorSpace,etc. If you need to use a weak reference to one of these classes, you must use an unsafe reference.
An unsafe reference is similar to a weak reference in that it doesn’t keep its related object alive, but it won’t be set to nil if the destination object is deallocated.
#property (unsafe_unretained) NSObject *unsafeProperty;
If you need to specify multiple attributes, simply include them as a comma-separated list, like this:
#property (readonly, getter=isFinished) BOOL finished;
The article linked to by MrMage is no longer working. So, here is what I've learned in my (very) short time coding in Objective-C:
nonatomic vs. atomic
- "atomic" is the default. Always use "nonatomic". I don't know why, but the book I read said there is "rarely a reason" to use "atomic". (BTW: The book I read is the BNR "iOS Programming" book.)
readwrite vs. readonly
- "readwrite" is the default. When you #synthesize, both a getter and a setter will be created for you. If you use "readonly", no setter will be created. Use it for a value you don't want to ever change after the instantiation of the object.
retain vs. copy vs. assign
"assign" is the default. In the setter that is created by #synthesize, the value will simply be assigned to the attribute. My understanding is that "assign" should be used for non-pointer attributes.
"retain" is needed when the attribute is a pointer to an object. The setter generated by #synthesize will retain (aka add a retain count) the object. You will need to release the object when you are finished with it.
"copy" is needed when the object is mutable. Use this if you need the value of the object as it is at this moment, and you don't want that value to reflect any changes made by other owners of the object. You will need to release the object when you are finished with it because you are retaining the copy.
After reading many articles I decided to put all the attributes information together:
atomic //default
nonatomic
strong=retain //default
weak= unsafe_unretained
retain
assign //default
unsafe_unretained
copy
readonly
readwrite //default
Below is a link to the detailed article where you can find these attributes.
Many thanks to all the people who give best answers here!!
Variable property attributes or Modifiers in iOS
Here is the Sample Description from Article
atomic
-Atomic means only one thread access the variable(static type).
-Atomic is thread safe.
-but it is slow in performance
-atomic is default behavior
-Atomic accessors in a non garbage collected environment (i.e. when using retain/release/autorelease) will use a lock to
ensure that another thread doesn't interfere with the correct setting/getting of the value.
-it is not actually a keyword.
Example :
#property (retain) NSString *name;
#synthesize name;
nonatomic
-Nonatomic means multiple thread access the variable(dynamic type).
-Nonatomic is thread unsafe.
-but it is fast in performance
-Nonatomic is NOT default behavior,we need to add nonatomic keyword in property attribute.
-it may result in unexpected behavior, when two different process (threads) access the same variable at the same time.
Example:
#property (nonatomic, retain) NSString *name;
#synthesize name;
Explain:
Suppose there is an atomic string property called "name", and if you call [self setName:#"A"] from thread A,
call [self setName:#"B"] from thread B, and call [self name] from thread C, then all operation on different thread will be performed serially which means if one thread is executing setter or getter, then other threads will wait. This makes property "name" read/write safe but if another thread D calls [name release] simultaneously then this operation might produce a crash because there is no setter/getter call involved here. Which means an object is read/write safe (ATOMIC) but not thread safe as another threads can simultaneously send any type of messages to the object. Developer should ensure thread safety for such objects.
If the property "name" was nonatomic, then all threads in above example - A,B, C and D will execute simultaneously producing any unpredictable result. In case of atomic, Either one of A, B or C will execute first but D can still execute in parallel.
strong (iOS4 = retain )
-it says "keep this in the heap until I don't point to it anymore"
-in other words " I'am the owner, you cannot dealloc this before aim fine with that same as retain"
-You use strong only if you need to retain the object.
-By default all instance variables and local variables are strong pointers.
-We generally use strong for UIViewControllers (UI item's parents)
-strong is used with ARC and it basically helps you , by not having to worry about the retain count of an object. ARC automatically releases it for you when you are done with it.Using the keyword strong means that you own the object.
Example:
#property (strong, nonatomic) ViewController *viewController;
#synthesize viewController;
weak (iOS4 = unsafe_unretained )
-it says "keep this as long as someone else points to it strongly"
-the same thing as assign, no retain or release
-A "weak" reference is a reference that you do not retain.
-We generally use weak for IBOutlets (UIViewController's Childs).This works because the child object only
needs to exist as long as the parent object does.
-a weak reference is a reference that does not protect the referenced object from collection by a garbage collector.
-Weak is essentially assign, a unretained property. Except the when the object is deallocated the weak pointer is automatically set to nil
Example :
#property (weak, nonatomic) IBOutlet UIButton *myButton;
#synthesize myButton;
Strong & Weak Explanation, Thanks to BJ Homer:
Imagine our object is a dog, and that the dog wants to run away (be deallocated).
Strong pointers are like a leash on the dog. As long as you have the leash attached to the dog, the dog will not run away. If five people attach their leash to one dog, (five strong pointers to one object), then the dog will not run away until all five leashes are detached.
Weak pointers, on the other hand, are like little kids pointing at the dog and saying "Look! A dog!" As long as the dog is still on the leash, the little kids can still see the dog, and they'll still point to it. As soon as all the leashes are detached, though, the dog runs away no matter how many little kids are pointing to it.
As soon as the last strong pointer (leash) no longer points to an object, the object will be deallocated, and all weak pointers will be zeroed out.
When we use weak?
The only time you would want to use weak, is if you wanted to avoid retain cycles
(e.g. the parent retains the child and the child retains the parent so neither is ever released).
retain = strong
-it is retained, old value is released and it is assigned
-retain specifies the new value should be sent -retain on assignment and the old value sent -release
-retain is the same as strong.
-apple says if you write retain it will auto converted/work like strong only.
-methods like "alloc" include an implicit "retain"
Example:
#property (nonatomic, retain) NSString *name;
#synthesize name;
assign
-assign is the default and simply performs a variable assignment
-assign is a property attribute that tells the compiler how to synthesize the property's setter implementation
-I would use assign for C primitive properties and weak for weak references to Objective-C objects.
Example:
#property (nonatomic, assign) NSString *address;
#synthesize address;
unsafe_unretained
-unsafe_unretained is an ownership qualifier that tells ARC how to insert retain/release calls
-unsafe_unretained is the ARC version of assign.
Example:
#property (nonatomic, unsafe_unretained) NSString *nickName;
#synthesize nickName;
copy
-copy is required when the object is mutable.
-copy specifies the new value should be sent -copy on assignment and the old value sent -release.
-copy is like retain returns an object which you must explicitly release (e.g., in dealloc) in non-garbage collected environments.
-if you use copy then you still need to release that in dealloc.
-Use this if you need the value of the object as it is at this moment, and you don't want that value to reflect any changes made by other
owners of the object. You will need to release the object when you are finished with it because you are retaining the copy.
Example:
#property (nonatomic, copy) NSArray *myArray;
#synthesize myArray;
Atomic property can be accessed by only one thread at a time. It is thread safe. Default is atomic .Please note that there is no keyword atomic
Nonatomic means multiple thread can access the item .It is thread unsafe
So one should be very careful while using atomic .As it affect the performance of your code
prefer this links about properties in objective-c in iOS...
https://techguy1996.blogspot.com/2020/02/properties-in-objective-c-ios.html
I couldn't think of core data refer to anything outside coredata. So there is no way there will be reference cycle. At most core data object points to another coredata objects.
however, I may be wrong.
Managedobjectcontext do not hold strong reference to core data.
Is there any guide here?
Is there any guide here?
Here is a link to Core Data Programming Guide: Object Lifetime Management.
It was updated on July 2014, so it may have new information not published when you asked this question.
By default, though, the references between a managed object and its context are weak. This means that in general you cannot rely on a context to ensure the longevity of a managed object instance, and you cannot rely on the existence of a managed object to ensure the longevity of a context. Put another way, just because you fetched an object doesn’t mean it will stay around.
The exception to this rule is that a managed object context maintains a strong reference to any changed
This means your references to NSManagedObject subclasses (Core Data objects) should be strong.
I am currently also unsure whether or not references should be strong or weak. The previous guys stated that they should be strong, but then I found this on:
https://developer.apple.com/library/prerelease/watchos/documentation/Cocoa/Conceptual/CoreData/CoreDataandStoryboards.html#//apple_ref/doc/uid/TP40001075-CH10-SW1
In the example code, Apple does this:
#interface DetailViewController : UIViewController
#property (weak) AAAEmployeeMO *employee;
#end
What we tend to do is to have a strong reference to the primary key of the object, and then a weak property that does lazy initialization if the object is nil. Like this;
#interface MyVC : UIViewController
#property (nonatomic, strong) NSString *objectId;
#property (nonatomic, weak) SomeObject *myCoolObject;
#end
#implementation MyVC
- (SomeObject *)myCoolObject {
if (_myCoolObject == nil) {
_myCoolObject = [SomeObject MR_findFirstByAttribute:#"primaryKey" withValue:self.objectId];
}
return _myCoolObject;
}
I'm still not sure if this is the correct way of doing it though. Please correct me.
I have to fix some existing code that builds just fine with LLVM (on iOS) so that it builds with llvm-gcc-4.2 too. I'm done with pretty much everything, except this pattern which is found at a few places:
#property (nonatomic, retain) __block id myProperty;
I suspect the intent here is to allow access to the property from inside a block without retaining self. How can I remove the __block attribute, which gcc doesn't support here, but still achieve the same effect?
I'll suggest you've found a compiler bug, the declaration:
#property (nonatomic, retain) __block id myProperty;
is meaningless. The __block qualifier is used on local (stack allocated) variables so they are passed by reference to blocks, so they can be updated, and are usually[*] stored on the heap rather than the stack.
Therefore the qualifier __block has no meaning on a property declaration which is concerned with object instances, which are heap allocated at all times in Obj-C.
Just drop the __block from the property declarations - for every compiler.
[*] If a block is never copied to the heap a compiler may optimize __block variables and not move those to the heap either.
just before you use the variable in a block, create a local pointer of type __block. Don't ever use __block in #property declarations.
EG: TypeOfVariable __block *bock_pointer = self.property;
^{ inside the block use bock_pointer }
I know that the #property generates the getters and setters in Objective-c. But I've seen some classes where they declare attributes with their respective #property and some times just the #property with no attributes and seams to work the same way. Whats the difference?
I know that the #property generates the getters and setters in Objective-c.
No you don't. #property declares a property which is a getter and optionally a setter (for read/write properties). The generation of the getter and setter is done by the #synthesize in the implementation (or by you writing the getter and setter).
But I've seen some classes where they declare attributes with their respective #property
Do you mean like this?
#interface Foo : NSObject
{
Bar* anAttribute; // <<=== this is an instance variable
}
#property (retain) Bar* anAttribute;
#end
In the modern Objective-C run time, if you #synthesize the property, you can leave out the instance variable declaration and the compiler will put it in for you. Whether you explicitly declare the instance variable or not is a matter of personal preference.
Just to confuse you a bit, in the very latest compiler, you can omit the #synthesize and the compiler will put it in for you as long as you haven't explicitly created a getter or setter.
Under ios 5.0, there are ten different attributes you can attach to a property declaration: nonatomic, readwrite, readonly, getter=name, setter=name, strong, retain, copy, weak, assign. (strong, weak are new under ios 5.0 and are only meaningful if you use ARC).
nonatomic declares that variable access should not be protected against multithreaded concurrent access. This isn't the default, although 99% of the time it's what you want (since this protection makes your code run slower with no benefit if you're not doing multithreading).
readwrite/readonly should be fairly obvious - readwrite is the default, and if you declare a property readonly, it has no setter.
getter=, setter= control what the getter & setter methods should be called. If you omit them, they'll be called property name and set*property name*, respectively.
The remaining attributes (strong, weak, retain, copy, assign) are hints to the memory manager, and their behavior varies depending on whether you're using ARC or not. If you're not, then the "retain" property tells the setter method to automatically call retain on any object that it gets a reference to. This means that you must also call release in the deallocator.
The "assign" property tells the setter not to call retain - so if the object is released by another object, this pointer could be left dangling.
The "copy" property tells the setter to call retain and also to make a copy of the property - this is useful when you get, say, an NSDictionary and you don't want the caller to pass an instance of NSMutableDictionary and change the contents out from underneath you.
If you're using ARC, you'll normally only set "strong" or "weak". (strong is a synonym for retain, so they can be used interchangeably). "strong" tells ARC to retain the variable for you - "weak" tells it not to. "weak" is useful when you have a potential "retain cycle" where object A refers to object B and object A - if they both retain each other, you have a memory leak, so you'll want to make one of them a weak reference.
In the book I'm studying from for iPhone dev, they utilize IBOutlet instances using the Interface Builder. An example would be a UIButton. So they add a thing in the struct like this:
IBOutlet UIButton *whateverButton;
Then they add a #property for each of these in the .h, and a #synthesize in the .m.
Then they include a release in the dealloc of the .m. Two questions:
Is the release necessary? Aren't all properties already handled automatically?
How can I check the ref count to see what's happening, for debug purposes...?
Is the release necessary? Aren't all
properties already handled
automatically?
If the property is retained, the release is necessary. When you declare a #property and #synthesize it, all you get is the accessors, there is no special automatic behaviour in dealloc.
Also, there is nothing magical about IBOutlet – it’s just a marker for Interface Builder to see which properties you would like to appear in IB. It’s simply an empty macro, Cmd-click the IBOutlet keyword to see its definition:
#ifndef IBOutlet
#define IBOutlet
#endif
Same thing goes for IBAction which expands to void.
How can I check the ref count to see
what's happening, for debug
purposes...?
When I need to debug memory management, I usually simply set up a breakpoint in the dealloc method or log a string there. It is also helpful to log the retainCount of an object around the calls that might do something fishy with it.
It might also help to see how the #synthesize directive creates the accessors. When you declare a retained #property and ask the compiler to #synthesize them, you get something like this:
#property(retain) NSString *foo;
#synthesize foo;
- (void) foo {
return foo;
}
- (void) setFoo: (NSString*) newFoo {
// Try to think what would happen if this condition wasn’t
// here and somebody called [anObject setFoo:anObject.foo].
if (newFoo == foo)
return;
[foo release];
foo = [newFoo retain];
}
This isn’t exactly the thing, but it’s close enough. Now it should be more clear why you should release in dealloc.
Properties are not "handled automatically." The closest that comes to being true is that synthesized accessors handle their memory management responsibilities properly. But that is just those accessors. Properties are just a way of declaring accessible "things" on your class. They don't get much special treatment beyond that. It doesn't turn on some sort of garbage collection. So yes, release is necessary.
And you should use the debugging tools like Instruments if you want to inspect a running app for leaks or memory that doesn't get released. I would not look at the ref count directly, because it's almost dangerously useless — there's no guarantee that the ref count will be what you expect at any point, and that doesn't necessarily indicate a problem.
You should read Apple's memory management rules for Cocoa. It's pretty simple once you've absorbed that. I wouldn't necessarily recommend reading other guides first, because subtle misstatements can lead you down the wrong path (for instance, the idea that properties will be released for you probably came from hearing somebody misstate how they work).
Is the release necessary? Aren't all
properties already handled
automatically?
It depends on how the property is implemented. If it is auto-implemented (#synthesize'd), the property will retain its value in the setter and release it if set to another value. If you just got into Obj-C and Cocoa, you should read about the conventions for memory management. I have put up a post on my blog about them, there are plenty of resources elsewhere too.
How can I check the ref count to see
what's happening, for debug
purposes...?
You can check the NSObject retainCount property. Information on that is here. For advanced debugging purposes, there is the NSZombieEnabled environment flag that will cause all release message to not decrement the reference count but log an error when an object that would have normally been released is accessed.