How to prevent automatic retain/release when calling Obj-C message from C++? - objective-c

I've got some code like this:
#interface MyTimer : NSObject
- (int)getValue;
#end
#interface TimerHolder : NSObject {
ExternalControl* m_externalControl;
}
#property (retain, nonatomic) MyTimer* timer;
#end
class ExternalControl {
__unsafe_unretained TimerHolder* m_holder;
public:
ExternalControl(TimerHolder* holder) : m_holder(holder);
int getTimer() { return [m_holder.timer getValue] };
};
The method ExternalControl::getTimer() is called very frequently. During profiling, I noticed that during a call to getTimer(), obc-j also calls objc_retain and objc_release (presumably on m_holder or m_holder.timer), which ends up sucking up a lot of time! Removing __unsafe_unretained didn't make a difference.
By construction, I know that whenever ExternalControl::getTimer() is called, m_holder and its timer will stay alive for the duration of the call, so I think the retains/releases are unnecessary.
Is there any way to prevent them from being called?
I'm using XCode 4.2 with iOS 5 SDK, with ARC enabled. Is ARC responsible and removing it would remove the retains/releases? (I didn't want to spend time re-creating a project without ARC just to test this, before checking with you my friends!)

I can only speak from a non-ARC experience as I haven't used it yet (and not planning it being old school).
However, I have several projects using a C++ library and keeping references to it in the obj-C code.
I know for a fact that retain/release isn't called unless explicitly requested.
BTW, I couldn't use Obj-C when linking the C++ library and instead had to use Obj-C++ otherwise the C++ constructor/destructors weren't called as expected. It was just a matter of renaming the .m file into .mm
Hope this help.

If you want to manually handle retain/release for just that class (disable ARC).
set the "-fno-objc-arc" compiler flag in the build phases tab for that source file.

The WWDC 2011 sessions on ARC specifically mention that when compiled for debug, ARC retain/releases are not optimized.
If you haven't, try running your code in Release mode and profiling it. You should see a significant difference.
However, I know ARC doesn't take into account the kind of design assumptions you imply when you say "By construction". But, ARC shouldn't be touching your your "__unsafe_unretained" instance variable... are you sure those retain/release calls are being passed a pointer to that?

Related

how to properly alloc/dealloc this pointer? objective-c

*beginner iOS programmer, please explain with patience
suppose i have 2 classes - Foo, Bar
in class Bar, i have a pointer to an instance of Foo, which i set during init. (and because i dont know how to properly import Foo and Bar with each other, i end up setting the type to id instead of Foo)
#implementation Bar{
id pointerToInstanceOfFoo;
}
how do i write my dealloc function for Bar? or DO I even override the dealloc function?
right now i have
-(void)dealloc{
pointerToInstanceOfFoo = NULL;
[super dealloc];
}
i still want that pointer to Foo to be around when Bar dies, but am i doing things right? several questions:
if Foo and Bar imports from each other, how do i do this? or is this bad software design?
right now i have the pointer "pointerToInstanceOfFoo" set in the #implementation... is this equivalent to declaring a private pointer in class Bar?
should i instead be using
#property (nonatomic, weak) id pointerToInstanceOfFoo
instead? if so, why do i keep getting this error about no weak pointers in ARC?
do i need
delete pointerToInstanceOfFoo;
in the dealloc function??
Sorry for the confusion, any explanations/answers would be greatly appreciated!!
P.S. i'm using XCode 4.4 and running on iOS 5.0 with cocos2d v2.1 beta... i think it's using arc
You are not allowed to use [super dealloc] in ARC. So if that compiles, you are not using ARC and you need cals to retain and release. Writing a whole tutorial on that is not something that will fit in a stack overflow answer. As for your other questions:
1) Just import them in the implementation file, not the header file.
2) Yes
3) If it makes you happy. The error probably means you are targeting below iOS 5.0 (I.e. the deployment target in your project settings is set to less than 5.0), in which weak pointers are not supported, or ARC is turned off. I don't think you've accurately reported the error message since it makes no sense.
4) "delete" is not valid objective-c or valid c.
P.S. No, you don't want that pointer to be around after Bar is deallocated because that would be a memory leak. Perhaps you want a static variable instead of an instance variable?
As borrden mentioned, retain/release and objective-c memory management is a considerably large topic, one that has been extensively dealt with. I'd recommend reading this to get started and do some more research from there.
Though you can (should?) use ARC and save yourself some hassle, understanding the regular retain/release cycles will give you a better understanding of strong/weak references in ARC. While you don't have to understand everything about memory management in objective-c while using ARC, you still need to understand some of it.

Objective C: How to generate warning for instance variables not declared in the class’ interface?

I handled several issues recently when working on my company's iOS project using XCode 4.2 and Apple LLVM complier 3.0 / LLVM-GCC.
Below is the code
A.h
#interface A{
int _count;
};
#property(nonatomic,assign) count;
#end
A.mm
#implementation A
#synthesize count = _cont;//note a typo here !!!
//... I use _count in below code
#end
The typo will not generate a compile error or warning, the compiler or run-time (actually I am not sure who did it, to my best guess should be the compiler) will generate a _cont instance ivar for us.
This feature is great for encapsulation. Our header files could be much cleaner. However such a typo is hard to notice. So I am wondering if are there any setting to generate warning for this case? I search Clang's official site without any finding.
Someone would suggest me to not declare the instance in class interface at all and always use self.count. first I don't like this code style, second there are cases your "setCount" method may do something more than just change the instance value,lastly we began our product before this feature is introduced. I don't want to change exist code's style.
Does anyone here encounter the same problem? Are there any good ideas and best practice ?
This is not possible. How should the compiler recognize your typo?
Also you should have recognized that it is not necessary to write your own ivar for your property anymore, as #synthesize count = _count; is already enough to reach you iVar via _count later in the code.

Including ARC headers in non-ARC project

I made a static library that was coded using ARC. I plan to distribute this library for other people to use. I understand that nothing needs to be done to include an ARC static library in a non-ARC project, but what about including ARC header files? For example, the headers for my ARC static library declare properties as weak and strong but when I try to include these headers in a non-ARC project, the compiler freaks out.
Any ideas?
For strong, you can just use retain. They're identical.
weak is trickier, and while I know several ways that should work, I'm not certain the best way to handle it.
First, make sure you actually need it. If you're supporting iOS4, you can't have weak anyway, so the issue is moot. My gut feeling is that I'd probably just avoid weak and make all these problems go away. weak is nice, but it's not that big a deal to avoid in most cases.
That said, there are some approaches that will work. The best is probably to declare weak accessors without properties in the header. Instead of this:
#property (nonatomic, readwrite, weak) id delegate;
Do this:
- (id)delegate;
- (void)setDelegate:(id)aDelegate;
Then you can still declare a weak property inside your implementation file. The caller can still use dot notation for this, BTW.
It's possible that you'll get a compile error here, since setDelegate: technically takes a __strong id. If that's the case, just hand-implement setDelegate:
- (void)setDelegate:(id)aDelegate {
_delegate = aDelegate;
}
Haven't tested it, but that should work. You might also declare the ivar _delegate to be __weak in the #implementation block rather than declaring it as a weak property.
Like I said; I haven't tested any of this out. Please post your findings if it works.

Adding Member Variables in Objective C

First I have to do
#property (retain) aMember;
Then in implementation file I got to do
#synthesize aMember;
Then in dealloc, I got to do
self.aMember= nil; (or [aMember release])
That's 3 times writing what essentially is the same
Is there a way to speed this up?
I mean I can drag drop a control from a IB and xcode automatically generate those codes why I can't do that for more normal codes?
As someone coming from C# and managed languages for my day job I completely agree with you in questioning this 3 step process. In fact its almost crazy easy to create properties in C# in MS Visual Studio, but I digress.
Even though there are these 3 lines you have to write there is a huge amount of work going on under the covers for your.
Your declaration of the #property tells objective-c some important attributes (atomic, nonatomic, retain, copy, etc) in how to deal with your property when it is set by users of your class. When you think about this, these attributes (without you writing any code) are; helping you create thread safe code, handling references to objects so you don't have to worry about them disappearing on you, or copying values so you have your own copy of an object. The #property is also important since it is declared in your header file (typically). This give other developers an idea of the properties of your class and some small hints as to how objects they pass into those properties will be handled during its lifetime.
The #synthesize is also doing quite a bit of work by creating the getters and setters for that property, that also handle all sorts of memory management for you. You don't need to worry about releasing the old references and correctly referencing the new object. This alone to me is a great feature, especially when you are new to objective-c and it is easy to forget to deal with memory management at every turn. The #synthesize just does it for you and you don't have to write all the get and set code yourself.
The dealloc call is just life in a non-memory managed environment. While it adds additional steps, I appreciate the benefits that explicit memory management allows in a constrained environment such as the phone.
So all 3 steps are required, are different and when you think about it actually do quite a bit of work for you under the covers.
Unfortunately, that's how it is (for now). Apple had recently toyed with allowing Clang to implicitly synthesize your properties, which would have reduced your work to:
#interface Blah : NSObject
#property (retain) Blorg *blorg;
#end
#implementation Blah
- (void)dealloc {
[blorg release];
[super dealloc];
}
#end
When you didn't want an instance variable to be synthesized, you'd just explicitly put #dynamic blorg in your implementation. But this feature was removed due to some unforeseen complications, despite mostly positive reactions from developers.
So, I think it's safe to expect that Apple's still working on this. But for now, you do need to explicitly synthesize.
A few other notes:
If you are using garbage collection, you don't need to implement -dealloc: just make sure to do any last-minute cleanup in -finalize (such as notification unregistration).
You could also avoid the -dealloc bit by wrapping your instance variable in a C++ class which performs memory management during construction and destruction: #property prop_wrapper<Blorg> blorg; would work. Then, when your object is destroyed, ~prop_wrapper() would be called on your object. I've done this, and it works, but I recommend against it, since it doesn't play nice with KVO and KVC.
You could iterate through the properties of an object, and release those that are annotated with copy or retain. Then, in -dealloc, you'd have something like [self releaseProperties]. I've also done this, but I also recommend against it, since it can cause subtle problems which may result in inexplicable crashes if you're not careful.
To actually add a member variable in objective-c you don't need to do any of that.
What you're doing in those 3 steps is:
Declare properties for a member variable. (In your case you are indicating that you want the property setter to 'retain' the object that it sets your member variable to)
Declare the property getters and setters in a default way for your property.
Release the object that your property is retaining.
IF you only wanted to declare a member variable, all you had to do was declare it inside your class:
#interface SomeClassObject : NSObject {
int someMemberVariable;
}
#end
That's 3 times writing what essentially is the same
No it isn't.
#property (retain) aMember;
The above line declares a property so that the compiler knows it is OK to send the messages -aMember and -setAMember: to objects of your class. It also tells the compiler (and developers) that the property is a retain property (i.e. the object you set the property to will be retained), that it is read/write and that it is atomic.
#synthesize aMember;
The above line tells the compiler that it should automatically generate the setter and getter methods for the declared property. You can leave that out but then you have to write your own setter and getter.
[aMember release]; // in dealloc
Is there to tell the runtime that when the object is being deallocated, it no longer needs to hold a reference to that instance variable. This is necessary because, when you use reference counting rather than garbage collection, the runtime does not automatically clean up unwanted objects.
Each of those lines does a different thing. So you are not doing the same thing three times.

Objective-C properties, how do they work?

Assume we have a class Foo with a property bar.
Declared like this in the header:
#interface Foo : NSObject {
int bar;
}
#property (nonatomic, assign) int bar;
#end
In the .m I have #synthesize bar; of course.
Now, my question is, if I remove the int bar; line, the property behaves the same way, so, is that line really necessary? Am I missing some fundamental concept?
Thanks!
The "modern" Objective-C runtime generates ivars automatically if they don't already exist when it encounters#synthesize.
Advantages to skipping them:
Less duplication in your code. And the #property gives the type, name and use (a property!) of the ivar, so you're not losing anything.
Even without explicitly declaring the ivar, you can still access the ivar directly. (One old release of Xcode has a bug that prevents this, but you won't be using that version.)
There are a few caveats:
This is not supported with the "old" runtime, on 32-bit Mac OS X. (It is supported by recent versions of the iOS simulator.)
Xcode may not show autogenerated ivars in the debugger. (I believe this is a bug.)
Because of the debugger issue, at the moment I explicitly add all my ivars and flag them like this:
#interface Foo : NSObject {
#ifndef SYNTHESIZED_IVARS
int ivar;
#endif
}
#property (nonatomic, assign) int bar;
#end
My plan is to remove that block when I've confirmed the debugger is able to show the ivars. (For all I know, this has already happened.)
If there is not a instance variable (ivar) with the same name as the property the modern runtime creates a new ivar of the specified property name to hold the property value when it sees #synthesize.
If your property was not defined nonatomic and you want your code to be threadsafe it may help you to not reference the ivar (whether you declared it or it was synthesized), as that will prevent you from accessing it directly when the property is being changed. To my knowledge there is no way to acquire the same lock that is acquired by #synthesize for an atomic property and therefore you cannot perform safe reads of an atomic property's ivar other than by its synthesized accessor (unless you code an explicit setter and lock something yourself). If you are interested in writing you own accessors I have a blog post on that here.
I believe it is more usual to have an explicit ivar for each property, but this may be because most code is intended to be compatible with the legacy runtime rather than because it is inherently good practice.
Edit: I have corrected paragraph 1 to say that the synthesized ivar has the name of the property; I couldn't see any discussion of its name in Apple's docs so I had assumed it was not user accessible. Thanks to the commenters for pointing this out.
In the latest Objective-C runtime, it turns out that all ivars (in this case, bar) are dynamically added to the class from the #property/#synthesize declaration and do not need a corresponding ivar declaration in the class header. The only caveat to this is that latest Objective-C runtime which supports this feature does not include support for 32 bit applications.
This page from the excellent Cocoa with Love blog explains more.
If you are using the modern Obj-C runtime (e.g. with the LLVM compiler in Xcode 4), the compiler can automatically create the instance variable for you. In that case, you don't need to declare the ivar.
The modern runtime is supported by iOS, the iOS Simulator and 64-bit Mac OS X. You can't build your project for 32-bit OS X with the modern runtime.
I believe it only works that way in 64bit mode. If you try to build for a 32bit target, it will throw an exception.
Scott Stevenson has a good overview of the objective-c 2 changes, and mentions the 64bit runtime changes here