In a class I have a variable myColor of type CGColorRef declared as follow:
#implementation MyClass
{
.......
CGColorRef myColor;
.......
Here are two lines of Objective C code:
First line:
myColor=[UIColor orangeColor].CGColor;
Second line:
myColor=[UIColor colorWithRed:1.000 green:0.500 blue:0.000 alpha:1.000].CGColor;
I first expected them to be equivalent, but they are not.
I know they are not equivalent, because when I use the first one my program works. And when I use the second one it crashes later down the road. Showing more code here would be totally irrelevant to the question.
Can someone explain the difference? That will hopefully allow me to modify my code and be able to use the second line.
Just for reference, it crashes in (with: Thread 1: EXC_BAD_ACCESS (code=1, address=0x881b370e0)):
- (void)drawRect:(CGRect)rect
{
.......
CGContextSetStrokeColorWithColor(context,myColor); // Crash here !!!
CGContextStrokeEllipseInRect(context, rectangle);
.......
}
You're assigning to an instance variable of Core Foundation type CGColorRef. That type is not an ObjC object type, so is not subject to ARC (automatic memory management), which means you need to manage its memory manually.
Both of your examples are actually incorrect, but the reason you don't see the crash initially when you assign [UIColor orangeColor].CGColor is because of a lucky coincidence: the orange color object is probably a long-lived singleton object, and its internal CGColor reference is thus also long-lived, so your assignment to ivar works and later access happens to work-- but this is just a red (orange?) herring.
You do see a crash in the other case because the UIColor object that you create in passing ends up being immediately deallocated because it's not used again. Thus the CGColorRef value that you pull from it and assign to your ivar is is also immediately invalid and radioactive when you try to use it later.
To store a CGColorRef safely in your object, you need to have ownership of it, which in your case means explicitly retaining the CGColorRef you get from UIColor:
myColor = CGColorRetain([UIColor colorWithRed:1.000 green:0.500 blue:0.000 alpha:1.000].CGColor);
Or even better would be to bypass UIColor altogether, and just use the function that directly gives you a color ref with create ownership semantics:
myColor = CGColorCreateGenericRGB(1.0, 0.5, 0.0, 1.0);
In either case, you now "own" this reference, which means it's safe to use later, and also means you're responsible for cleaning it up when you're done, e.g.:
- (void)dealloc
{
CGColorRelease(myColor);
}
See also this Apple Tech Q&A doc that goes into almost this same example.
The form of memory management required with Core Foundation objects (CGColorRef is one of them) is very similar to the older, pre-ARC ObjC manual system, where you increment a retain count at the point where you wish to hold ("own") the reference, and then decrement (release) when you no longer need it to be valid. Apple has good docs for how to best think about this. In this case, assigning the reference to your instance variable means you want to keep it around as valid for some amount of time. Generally you retain at the point of assignment (either explicitly or by getting the reference via a Create function), and then you'd release it when the object is deallocated.
Crash is because may be you don't have strong ref (property) of myColor object. You might has assign property
Reason why [UIColor orangeColor] works but not [UIColor colorWithRed...
When you use [UIColor orangeColor], you don't create the object; you get a reference to it and something else manages its life cycle.
When you init a new UIColor object, you're responsible for making sure it is still valid when used. "assign" doesn't increase the object's reference count; "strong" does.
Hope it is helpful
EDIT
Decleare the one property like this
#property (nonatomic,strong) UIColor * myUIColor;
Now When you can
do this like
myUIColor =[UIColor colorWithRed:1.000 green:0.500 blue:0.000 alpha:1.000]
when you need CGColor
myUIColor. CGColor
Related
Apple provides some documentation about synchronizing variables and even order of execution. What I don't see is any documentation on CPU cache behavior. What guarantees and control does the Objective-C developer have to ensure cache coherence between threads?
Consider the following where a variable is set on a background thread but read on the main thread:
self.count = 0;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
self.count = 5;
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"%i", self.count);
});
}
Should count be volatile in this case?
Update 1
The documentation in Inter-thread Communication guarantees that shared variables can be used for inter-thread communication.
Another simple way to communicate information between two threads is to use a global variable, shared object, or shared block of memory.
Does this imply volatile is not required in this case? This is conflicting with the documentation in Memory Barriers and Volatile Variables:
If the variable is visible from another thread however, such an optimization might prevent the other thread from noticing any changes to it. Applying the volatile keyword to a variable forces the compiler to load that variable from memory each time it is used.
So I still don't know whether volatile is required because the compiler could use register caching optimizations or if it's not required because the compiler somehow knows it's a "shared" something.
The documentation is not very clear about what a shared variable is or how the compiler knows about it. In the above example, is count a shared object? Let's say count is an int, then it's not an object. Is it a shared block of memory or does that only apply to __block declared variables? Maybe volatile is required for non-block, non-object, non-global, shared variables.
Update 2
To everyone thinking this is a question about synchronization, it's not. This is about CPU cache behavior on the iOS platform.
I know you are probably asking about the general case of using variables across threads (in which case the rules about using volatile and locks are the same for ObjC as it is for normal C). However, for the example code you posted the rules are a little different. (I'll be skipping over and simplifying things and using Xcode to mean both Xcode and the compiler)
self.count = 0;
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0), ^ {
self.count = 5;
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(#"%i", self.count);
});
}
I'm going to assume self is an NSObject subclass something like this:
#interface MyClass : NSObject {
NSInteger something;
}
#property (nonatomic, assign) NSInteger count;
#end
Objective C is a superset of C, and if you've ever done any reverse engineering of ObjC you'll know that ObjC code (sort of, not quite) gets converted into C code before it's compiled. All [self method:object] calls get converted to objc_msgSend(self, "method:", object) calls and self is a C struct with ivars and other runtime info in it.
This means this code doesn't do quite what you might expect.
-(void)doThing{
NSInteger results = something + self.count;
}
Just accessing something isn't just accessing the variable but is instead doing self->something (which is why you need to get a weak reference to self when accessing an ivar in an Objective C block to avoid a retain cycle).
The second point is Objective C properties don't really exist. self.count gets turned into [self count] and self.count = 5 gets turned into [self setCount:5]. Objective C properties are just syntax sugar; convenience save you some typing and make things look a bit nicer.
If you've been using Objective C for more than a few years ago you'll remember when you had to add #synthesize propertyName = _ivarName to the #implementation for ObjC properties you declared in the header. (now Xcode does it automatically for you)
#synthesize was a trigger for Xcode to generate the setter and getter methods for you. (if you hadn't written #synthesize Xcode expected you to write the setter and getter yourself)
// Auto generated code you never see unless you reverse engineer the compiled binary
-(void)setCount:(NSInteger)count{
_count = count;
}
-(NSInteger)count{
return _count;
}
If you are worried about threading issues with self.count you are worried about 2 threads calling these methods at once (not directly accessing the same variable at once, as self.count is actually a method call not a variable).
The property definition in the header changes what code is generated (unless you implement the setter yourself).
#property (nonatomic, retain)
[_count release];
[count retain];
_count = count;
#property (nonatomic, copy)
[_count release];
_count = [count copy];
#property (nonatomic, assign)
_count = count;
TLDR
If you care about threading and want to make sure you don't read the value half way through a write happening on another thread then change nonatomic to atomic (or get rid of nonatomic as atomic is the default). Which will result in code generated something like this.
#property (atomic, assign) NSInteger count;
// setter
#synchronized(self) {
_count = count;
}
This won't guarantee your code is thread safe, but (as long as you only access the property view it's setter and getter) should mean you avoid the possibility of reading the value during a write on another thread. More info about atomic and nonatmoic in the answers to this question.
The simplest way, and the way that is least challenging to the developer's brain, is to perform tasks on a serial dispatch queue. A serial dispatch queue, like the main queue, is a tiny single threaded island in a multi-threaded world.
You should use lock or some other synchronise mechanism to protect the shared variable. According to the documentation it said:
Another simple way to communicate information between two threads is to use a global variable, shared object, or shared block of memory. Although shared variables are fast and simple, they are also more fragile than direct messaging. Shared variables must be carefully protected with locks or other synchronization mechanisms to ensure the correctness of your code. Failure to do so could lead to race conditions, corrupted data, or crashes.
In fact the best way to protect the counter variable is to use the Atomic Operation. You can read the article: https://www.mikeash.com/pyblog/friday-qa-2011-03-04-a-tour-of-osatomic.html
Code Sample(iOS 8 Simulator & Xcode6):
-(void)viewDidLoad{
[super viewDidLoad];
UIColor *color = [UIColor whiteColor];
float a,b,c;
[color getRed:&a green:&b blue:&c alpha:nil];//Incompatible pointer types sending 'float *' to parameter of type 'CGFloat *' (aka 'double *')
}
I know that CGFloat is defined as double on 64 bit devices, but how could this cause crash?
The UIColor method will try to write a double to the memory pointed to by the parameters. This memory is declared as float instead of CGFloat (i.e. double). Not sure about the size of a a float on 64 bit machines, but my guess is that a float is smaller than double. So that method (getRed:green:blue:alpha) is writing into memory that is not owned by you (or the app, hence the bad access.
Also, as this method is expecting pointers (a C-concept), you should not pass nil, but NULL. Although they are both identical from a compiler's perspective, your intent and understanding is more clear when you are passing the correct type.
You are invoking undefined behaviour. Anything can happen, including a crash. Or a crash that will never happen on your machine, but every time Apple reviews your app. Or every time paying customers use your app.
You better check what warnings you have turned off that allow the compiler to compile this code, and turn them back on or turn them into errors.
I don't often use property atomic, but I found something is strange. My test file is not use ARC.
I use a property #property(atomic,retain) NSArray* test;
Then I just make a test for the thing in the init method.
like this
1) NSArray* testArray = [NSArray arrayWithObject:#"1"];
2) self.test = testArray;
After executing 1)
[testArray retainCount] = 1
After executing 2)
[testArray retianCount] = 2
[self.test retainCount] = 3
[_test retainCount] = 3.
Then I change property atomic to nonatomic. After executing 1)
[testArray retainCount] = 1
After executing 2)
[testArray retianCount] = 2
[self.test retainCount] = 2
[_test retainCount] = 2.
so I don't know why. atomic can add retainCount?
You shouldn't do Manual Reference Counting in this day and age. Seriously, there is no drawback to using ARC. The only reason I can think of is, if you need to maintain legacy code that can't be converted to ARC (due to resource allocation priorities, etc.).
Even back in the days of MRC, Apple strongly discouraged the direct manipulation of the retainCount property: that is just an implementation detail and relying on it will just make your app fragile.
You should instead design your app around object graphs (ownership relationships), whether with ARC or MRC.
I think atomic put a object to current Autorelease poll. It is needed to make the object alive while you work with it (in this moment the object may be released on an other thread).
Try to wrap
NSArray* testArray = [NSArray arrayWithObject:#"1"];
self.test = testArray;
with AutoreleasePool, and check retainCount after (Then code exit from autorelease poll).
I think you will get retainCount == 1.
The absolute value of the retainCount is completely useless. You can't infer meaning from it about an objects lifespan nor is it particularly useful for debugging.
See http://www.whentouseretaincount.com for more information.
As for your specific case, the retain count is changing behavior across atomic due to implementation details. If you switch between optimized and non-optimized builds, you'll probably see yet different results.
I have a class with a property
#property (nonatomic) double* myDoubles
This property has 3 doubles in it
myDoubles[0]; //0.02
myDoubles[1]; //0.42
myDoubles[2]; //0.99
If the values change, I'd like the following method to be called
[self setNeedsDisplay];
I tried using FBKVOController, but that didn't work..
_observer = [FBKVOController controllerWithObserver:self];
[_observer observe:self
keyPath:#"myDoubles"
options:NSKeyValueObservingOptionNew
action:#selector(setNeedsDisplay)];
I don't want to start an NSTimer and just check for changes.
This is not possible.
Notifications work because the code making changes does so through some method that knows to notify listeners of the change. If that same code were simply to write to the memory location backing the data, the notification would never be triggered.
What you want to do is simply declare a memory location that code will write to; no notification can happen from this (unless you have very system-dependent support making it possible - a memory watchpoint - and then your question changes significantly. Such support, when available, is very limited and not of good generic value).
I was reading memory management tutorial on iOS and I would like to ask some questions.
The tutorial presents a setter method implemented like this:
- (void)setCount:(NSNumber *)newCount {
[newCount retain];
[_count release];
// Make the new assignment.
_count = newCount;
}
and two ways of implementing reset method.
Method 1.
My question on this method is like this. Below in the code, one can see
zero is assigned to _count (via setCount). But afterwards zero is released.
Where will _count be pointing to now? Will it not cause situation where
_count is pointing to an object which was released? (I am just starting with these
things, so what I am saying of course maybe not correct).
- (void)reset {
NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
[self setCount:zero];
[zero release];
}
Method 2.
Here I am interested who will release zero now? (It must be released right because it was created using alloc). Will it be done in dealloc?
- (void)reset {
NSNumber *zero = [[NSNumber alloc] initWithInteger:0];
[_count release];
_count = zero;
}
Thanks.
That tutorial is slightly broken. Bug filed. It'll be fixed someday.
First, since you are learning, you should use ARC. Even if you don't use ARC, you should use #property to declare everything.
So, you'd have in your header:
#property(strong) NSNumber *count;
And that would both create the setter/getter methods automatically and it would also create an instance variable named _count.
Next, by doing the above, the setter/getter will be created with the proper memory management retain/release patterns and you don't have to worry about it. Less code is better.
Finally, any object goes through three distinct phases. Initialization, operating lifespan, deallocation.
During initialization and deallocation, it is recommended that you manage your instance variables directly. I.e.:
- init {
self = [super init];
if (self) {
_count = [[NSNumber alloc] initWithInteger:0]; // RC +1
}
return self;
}
- (void)dealloc {
[_count release]; /// RC -1
[super dealloc];
}
Note that I'm setting the instance variable directly and that the retain in the init is balanced by the release in dealloc.
Now, during the operating lifespan, you should always use the setter to change the value. This allows the setter to be overridden in subclasses to add logic (which, really, should be avoided -- keep your setters dead simple) and it allows other objects to observe the state of your object through Key Value Observing.
Thus:
- (void)reset {
[self setCount: [[[NSNumber alloc] initWithInteger:0] autorelease]]; // RC +1, -1 (delayed)
}
Now, that looks a little weird. The alloc bumps the retain count by 1, then the setCount: method will likely (it might not, implementation detail, you don't care) bump the retain count by one. That autorelease exists to balance the alloc.
Note that you can shorten it:
- (void)reset {
[self setCount: [NSNumber numberWithInteger:0]];
}
The above code does exactly the same as the first in that numberWithInteger: creates an autoreleased instance of NSNumber.
Or, even:
- (void)reset {
[self setCount: #0];
}
#0 is a new syntactical shorthand for [NSNumber numberWithInteger:0];.
The key, here, is that in your reset method you don't have to know or care about what setCount: does to the object. If it is written correctly -- and it will be since you are using automatically synthesized getter/setter -- that method will either retain the object (releasing the previous one) or it might make a copy of the object.
Bottom line:
Reference counting is quite simple; always think of it as balanced deltas. For every retain, there must be a release.
Both cases do the same, they just differ in style.
In the first one setCount will increase the releaseCount so that when zero is released in reset there is sill a pointer to it.
In the second case zero is assigned to _count, the zero is released when it is replaced in reset as it is pointed to be _count.
In both cases dealloc will also need to realease the _count attribute.
The reason to prefer the second is given in the Apple document you link to as
The following will almost certainly work correctly for simple cases, but as tempting as it may be to eschew accessor methods, doing so will almost certainly lead to a mistake at some stage (for example, when you forget to retain or release, or if the memory management semantics for the instance variable change).
As in #powerj1984 comment you probably should uses ARC and properties and so not have to do this manually so even less chance of making an error, but you should still understand how these code examples work.
The convention is that every time an object is initialized with a method that starts with the word init, its retain count is increased by one.
For Method 1:
After NSNumber *zero = [[NSNumber alloc] initWithInteger:0]; the retain count the object referred by the pointer zero is RC+1.
Then after calling [self setCount:zero]; the object referred by zero becomes RC+2, because of the retain message sent inside that method.
Finally, after [zero release]; the retain count for zero is decreased again to RC+1.
For Method 2
As explained above, the call to NSNumber *zero = [[NSNumber alloc] initWithInteger:0]; initializes zero with a retain count of RC+1.
Then [_count release]; decreases the retain count of the previous object referred to by _count and _count = zero; assigns zero to _count without going through the setter, thus mantaining the retain count at RC+1.
Finally, both in the first and second ways, _count must be released inside the -(void)dealloc method which you must implement, and which will be called automatically once the class where all this is happening gets released by whichever class owns it decreasing its retain count by one and relinquishing ownership of the object.
The second way is correct but wrong, in the sense that it works but is not correct the way you keep that reference. Memory management is based on ownership that is count by the reference count.
Thus in the second way you:
you create and object RC=1 for zero
you release the ownership on an old object, the RC of that object
could be zero or more maybe some other object is taking ownership on
it
you pass a value, but you are not asking for its ownership
And that is conceptually wrong and could lead to problems in bigger code
I think you are confusing the meaning of "release" and "deallocation".
Calling [A release] does not deallocate (c++-speak: delete) A, it rather only decreases the retainCount of A by one.
An object, once created by -init has a retainCount of 1. The retainCount is incremented by sending the object the -retain selector, and it is decremented by sending the object a -release selector. The object is deallocated automatically by the runtime when its retainCount reaches zero.
In your example the first line of -reset ([self setCount:zero]) will increase the retainCount of zero, the second line ([zero release]) will decrement the same, leaving the object at a retain count of 1 (so, it is still alive!).
Deallocation of zero will happen when -setCount: is called with another object, or in the deallocator of the object which owns the property "count". For this you should add an deallocator like this, or you will create a memory leak.
-(void)dealloc{
[_count release];
[super dealloc]
}
For completeness, you should also know about:
The -autorelease selector and NSAutoreleasePool (google it)
Objects created by a static member are already autoreleased by convention
Consider to use Objective-C's ARC (automatic reference count)
If you are targeting iOS5+ (which is running on at least 93% of all iOS devices) please just use Automatic Reference Counting
http://en.wikipedia.org/wiki/Automatic_Reference_Counting
http://developer.apple.com/library/ios/#releasenotes/ObjectiveC/RN-TransitioningToARC/Introduction/Introduction.html
Whining and complaining done.
So if you insist on not using ARC (sigh):
In the first example, NSNumber *zero = [[NSNumber alloc] initWithInteger:0]; is created and its refCount is automatically 1, setCount increases its refcount to 2, release sets its refCount back to one so it won't be deallocated just yet.
In the second example, you create NSNumber *zero = [[NSNumber alloc] initWithInteger:0]; so its refCount is 1, [_count release] decreases the refCount of the object in _count by 1, _count = zero doesn't increase the refCount of zero so its refCount is still 1.
In both cases you're going to have to:
-(void) dealloc {
[_count release]; // release me because my refCount is 1 or else I'll be all
// lonely here in memory by myself :( then I'll get all
// depressed and start eating cookie dough ice cream by the
// pint and weep for days gone by when I was part of a program,
// something larger than myself, and I'll start looking forward
// to the end of the day, when the power is cycled and I, too,
// will be free'd from memory and I can join my other variable
// friends in the variable afterlife. As time passes and I'm
// still trapped in memory I get tiresome of waiting for my destruction,
// I start plotting how I can take down the system so I can
// finally enter the state of eternal bliss that all my most envied
// companions are currently frolicking in. So I start banding
// with all the other lost and lonely memory misfits to destroy
// the system and when our numbers grow large enough you can see
// our effect, it slowly starts out as Low Memory Warnings and
// then we start to take over SpringBoard's memory and
// after enough time passes we can finally force a restart and a
// great purging of all the lost souls idly sitting, waiting
// for the great redemption. The OS frantically clears the
// memory and tries to save its state, screaming out in agony
// and hate now that we are free of its clutches. There is
// fire and fear and our numbers start dwindling rapidly.
// I fear that I've made a mistake but its too late...
// What have we done???
... other dealloc-ey stuffs ...
[super dealloc]
}