How to prevent automatic retain/release when calling Obj-C message from C++?
-
26-10-2019 - |
Question
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!)
Solution
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.
OTHER TIPS
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?