Is property getter called even if I access property by name? - objective-c

Let's say that I declare property in following way:
#property(nonatomic, strong, getter = isWorking) BOOL working;
Then instead of having the property to be synthesized I write the getter myself (and add some custom logic to it).
What will happen if I access the property in following way:
BOOL work = self.working;
Is the getter (and my custom logic there) still called or is it called only when I access the property using getter explicitly (BOOL work = self.isWorking;) ?

Oops. Just tried it. Apparently i use dot notation too much, and didn't realize just how much it was doing. :P
#import "NSObject.h"
#include <stdio.h>
#interface Test : NSObject
#property (getter=myStuff) int stuff;
#end
#implementation Test
-(int)myStuff { return 42; }
-(void)setStuff:(int)value { /* don't care */ }
#end
int main() {
#autoreleasepool {
Test* test = [[Test alloc] init];
/* All these work... */
printf("test.stuff == %d\n", test.stuff);
printf("[test myStuff] == %d\n", [test myStuff]);
printf("test.myStuff == %d\n", test.myStuff);
/* but here, there's an exception */
printf("[test stuff] == %d\n", [test stuff]);
return 0;
}
}
When i compile this (using clang in Linux), there are two warnings about the oddness of a missing -(int)stuff. And the output looks like
chao#chao-VirtualBox:~/code/objc$ ./a.out
test.stuff == 42
[test myStuff] == 42
test.myStuff == 42
: Uncaught exception NSInvalidArgumentException, reason: -[Test stuff]: unrecognized selector sent to instance 0x2367f38
chao#chao-VirtualBox:~/code/objc$
So, umm, yeah. Disregard half of the stuff below. :P
self.working is just syntactic sugar for [self working] (or [self setWorking:value] if you're assigning to it). Either one will do the same thing: return the value of [self isWorking], because that's the getter you defined.
If you want to avoid the getter, try _working or self->_working (or whatever you named the ivar). Otherwise, self.working, [self working], and [self isWorking] (and even self.isWorking if you're feeling brave) should all give you the same result.

Related

Why does "conformsToProtocol" not check for "required" method implementations?

I am trying to enforce a "formal" #protocol, but cannot reliably test my classes/instances as to whether they ACTUALLY implement the protocol's "required" methods, vs. simply "declaring" that they conform to the protocol.
A complete example of my quandary…
#import <Foundation/Foundation.h>
#protocol RequiredProtocol
#required
- (NSString*) mustImplement; #end
#interface Cog : NSObject <RequiredProtocol> #end
#implementation Cog #end
#interface Sprocket : NSObject #end
#implementation Sprocket
- (NSString*) mustImplement
{ return #"I conform, but ObjC doesn't care!"; } #end
int main(int argc, char *argv[]) {
Protocol *required = #protocol(RequiredProtocol);
SEL requiredSEL = #selector(mustImplement);
void (^testProtocolConformance)(NSObject*) = ^(NSObject *x){
NSLog(#"Protocol:%#\n"
"Does %# class conform:%# \n"
"Do instances conform:%# \n"
"Required method's result:\"%#\"",
NSStringFromProtocol ( required ),
NSStringFromClass ( x.class ),
[x.class conformsToProtocol:required] ? #"YES" : #"NO",
[x conformsToProtocol:required] ? #"YES" : #"NO",
[x respondsToSelector:requiredSEL] ? [x mustImplement]
: nil );
};
testProtocolConformance ( Cog.new );
testProtocolConformance ( Sprocket.new );
}
Result:
Protocol:RequiredProtocol
Does Cog class conform:YES
Do instances conform:YES
Required method's result:"(null)"
Protocol:RequiredProtocol
Does Sprocket class conform:NO
Do instances conform:NO
Required method's result:"I conform, but ObjC doesn't care!"
Why is it that a class and it's instances that DO implement the #protocol's methods (Sprocket) return NO to conformsToProtocol?
And why does one that DOESN'T ACTUALLY conform, but SAYS that it DOES (Cog) return YES?
What is the point of a formal protocol if the declaration is all that's needed to feign conformance?
How can you ACTUALLY check for complete implementation of multiple #selectors without MULTIPLE calls to respondsToSelector?
#Josh Caswell.. Without diffing the two.. I'd guess that your response achieves similar effect to the category on NSObject I've been using in the meantime…
#implementation NSObject (ProtocolConformance)
- (BOOL) implementsProtocol:(id)nameOrProtocol {
Protocol *p = [nameOrProtocol isKindOfClass:NSString.class]
? NSProtocolFromString(nameOrProtocol)
: nameOrProtocol; // Arg is string OR protocol
Class klass = self.class;
unsigned int outCount = 0;
struct objc_method_description *methods = NULL;
methods = protocol_copyMethodDescriptionList( p, YES, YES, &outCount);
for (unsigned int i = 0; i < outCount; ++i) {
SEL selector = methods[i].name;
if (![klass instancesRespondToSelector: selector]) {
if (methods) free(methods); methods = NULL; return NO;
}
}
if (methods) free(methods); methods = NULL; return YES;
}
#end
Conforming to a protocol is just a "promise", you can't know if the receiver of conformsToProtocol: actually implements all the required methods. Is enough that you declare that the class conforms to the protocol using the angle brackets syntax, and conformsToProtocol: will return yes:
Discussion
A class is said to “conform to” a protocol if it adopts the protocol or inherits from another class that adopts it. Protocols are adopted by listing them within angle brackets after the interface declaration.
Full source: NSObject's conformsToProtocol: .
Protocols declarations have just the advantage that you can know at compile time if a class really adopts that required methods. If not, a warning will be given. I suggest to don't rely on conformsToProtocol:, but to use introspection instead. That is, verify if a class/object implements a method by calling instancesRespondToSelector: / respondsToSelector: :
+ (BOOL)instancesRespondToSelector:(SEL)aSelector;
- (BOOL)respondsToSelector:(SEL)aSelector;
What compiler are you using? Xcode/Clang issues 2 warnings and 1 error...
Think of a protocol as a club with membership requirements. Asking whether someone is a member of the club, provable by them having a membership card (NSObject<ReqiredProtocol>), should tell you that a person meets those requirements. However the lack of a membership doesn't mean they don't meet the requirements.
E.g. someone (Sprocket) might meet all the requirements to join but choose not to. Someone else (Cog) may failed to meet the requirements but a sloppy administrator might let them in.
The latter is why I asked about the compiler (the sloppy administrator ;-)). Try your code as entered on Xcode 4.6.3/Clang 4.2 produces warnings and errors (as does using GCC 4.2):
The warnings state that Cog fails to implement the required methods;
The error complains about [x mustImplement] as x is not known to have the required method as it is of type NSObject - you need to cast to remove that, just [(id)x mustImplement] will do as you've already tested the method exists.
In summary, you can only rely on conformsToProtocol if you know the originator of the code didn't ignore compiler warnings - the checking is done at compile time.
Addendum
I missed the last sentence of your question. If you wish to discover whether a class meets the requirements of a protocol, even if it doesn't declare that it does, e.g. Sprocket above (or if you are obtaining code from folk who ignore compiler warnings - the Cog author above), then you can do so using the facilities of the Obj-C runtime. And you'll only have to write one call to repsondsToSelector...
I just typed in the following and quickly tested it on your sample. It is not throughly tested by any means, caveat emptor etc. Code assumes ARC.
#import <objc/runtime.h>
#interface ProtocolChecker : NSObject
+ (BOOL) doesClass:(Class)aClass meetTheRequirementsOf:(Protocol *)aProtocol;
#end
#implementation ProtocolChecker
+ (BOOL) doesClass:(Class)aClass meetTheRequirementsOf:(Protocol *)aProtocol
{
struct objc_method_description *methods;
unsigned int count;
// required instance methods
methods = protocol_copyMethodDescriptionList(aProtocol, YES, YES, &count);
for (unsigned int ix = 0; ix < count; ix++)
{
if (![aClass instancesRespondToSelector:methods[ix].name])
{
free(methods);
return NO;
}
}
free(methods);
// required class methods
methods = protocol_copyMethodDescriptionList(aProtocol, YES, NO, &count);
for (unsigned int ix = 0; ix < count; ix++)
{
if (![aClass respondsToSelector:methods[ix].name])
{
free(methods);
return NO;
}
}
free(methods);
// other protocols
Protocol * __unsafe_unretained *protocols = protocol_copyProtocolList(aProtocol, &count);
for (unsigned int ix = 0; ix < count; ix++)
{
if (![self doesClass:aClass meetTheRequirementsOf:protocols[ix]])
{
free(protocols);
return NO;
}
}
free(protocols);
return YES;
}
#end
You should of course want to know exactly how this works, especially the * __unsafe_unretained * bit. That is left as an exercise :-)
CRD is right; the compiler tells you about actual conformance, and it should be listened to. If that's being ignored, the runtime doesn't have any built-in method to double-check. Classes maintain internal lists of protocol objects internally; conformsToProtocol: just looks at that.
At the risk that someone is going to come along and tell me to stop fiddling with the ##(%!^& runtime again, if you really truly need to check actual implementation, this is one way you can do so:
#import <objc/runtime.h>
BOOL classReallyTrulyDoesImplementAllTheRequiredMethodsOfThisProtocol(Class cls, Protocol * prtcl)
{
unsigned int meth_count;
struct objc_method_description * meth_list;
meth_list = protocol_copyMethodDescriptionList(p,
YES /*isRequired*/,
YES /*isInstanceMethod*/,
&meth_count);
/* Check instance methods */
for(int i = 0; i < meth_count; i++ ){
SEL methName = meth_list[i].name;
if( ![class instancesRespondToSelector:methName] ){
/* Missing _any_ required methods means failure */
free(meth_list);
return NO;
}
}
free(meth_list);
meth_list = protocol_copyMethodDescriptionList(p,
YES /*isRequired*/,
NO /*isInstanceMethod*/,
&meth_count);
/* Check class methods, if any */
for(int i = 0; i < meth_count; i++ ){
SEL methName = meth_list[i].name;
if( ![class respondsToSelector:methName] ){
free(meth_list);
return NO;
}
}
free(meth_list);
return YES;
}
If I had a hammer...
All of these answers are good. To them, I would add one more point: calling conformsToProtocol: is almost always a mistake. Because it tells whether the class says that it conforms to the protocol, rather than whether it actually provides specific methods:
It is possible to create a class that claims to conform, but does not, by silencing various warnings, resulting in crashes if you assume that a required method exists.
It is possible to create a class that conforms to the protocol but does not claim to do so, resulting in methods not getting called on a delegate even though they exist.
It can lead to programming errors creeping in when the protocol changes, because your code checks for conformance to a protocol before calling a method that used to be required, but no longer is.
All of these issues can cause unexpected behavior.
IMO, if you want to know if a class handles a method, the safest approach is to explicitly ask it if it handles that method (respondsToSelector:), rather than asking it if it conforms to a protocol that just happens to contain that method.
IMO, conformsToProtocol: should really have been a function in the Objective-C runtime instead of being exposed on NSObject, because it generally causes more problems than it solves.

Objective-C - iVar Scoped Method Variables?

I was messing around in Objective-C earlier, and I ran into a quite common situation:
I had a class, which was not a singleton, that needed a variable shared between method calls, like static, but each instance needed it's own variable. However, this variable only needed to be used in one particular method, we'll call it -foo.
What I'd love to do, is have a macro, let's call it ivar, which lets me do the following:
#implementation MyClass
-(foo)
{
ivar int someVal = 10; // default value, ivar scoped variable.
}
-(bar)
{
someVal = 5; // error, outside of `foo`'s scope.
}
#end
How the variable is defined does not matter to me (either a macro like OBJC_IVAR(Type, Name, Default) or ivar someType someName = value), as long as it meets the following requirements:
Has thread safety
Can have variable of same name (but different value) in another method
Type-less (doesn't matter what type the variable is)
Default Value support
Variable can be declared in one line (I shouldn't have to write 15 lines of code just to put a variable in my code)
I am currently working on an Objective-C++ implementation myself, I was just wondering if anyone else had any thoughts (or existing tools) on how to do this.
Obviously, this doesn't have to be done with a true iVar. More likely, this should be done with associated objects at run-time, which also manages deallocation for us.
After a lot of time spent, I believe I have a fully working solution in Objective-C++. Some of the features:
The variables are unique. As long as they have a different scope, their values are independent
Each instance has it's own values
Thread safety (accomplished by associated objects)
Simple variable declaration:
Macro overloading: only specify the information that you need
Possible ways to define an OBJC_IVAR:
OBJC_IVAR(); // creates a warning, does nothing
OBJC_IVAR(Name); // creates an ivar named 'Name' of type 'id'
OBJC_IVAR(Type, Name); // creates an ivar named 'Name' of type 'Type'
OBJC_IVAR(Type, Name, Default); // creates an ivar named 'Name', of type 'Type', and a default value of 'Default' (which is only executed once);
Full Type Support with C++ templates (__weak, __strong, __autoreleasing, volatile, etc. are all supported)
Subclasses do not share variables with their superclasses (so no chance for conflicts, variables really are limited to their scope).
Can be used in singletons without issue
Is fast, takes ~15-30 CPU cycles to look up a variable, and once it's looked up, takes as long as any other variable to set it.
Most of the hard work is done by the pre-processor, which allows for faster code
Just drag-and-drop into an existing Xcode project, doesn't rely on a custom processor
Some minor cons to the implementation:
Objects must have an ownership specifier (limitation with C++ references: Reference to non-const type 'id' with no explicit ownership). Is easily fixed by adding __strong, __weak, or __autoreleasing to the type of the variable
Implementation is hard to read. Because it relies so much on C++ templates and Objective-C working together in harmony, it's difficult to just change 'one thing' and hope for it to work. I have added extensive comments to the implementation, so hopefully that frees some of the burden.
Method swizzling can confuse this majorly. Not the largest of issues, but if you start playing around with method swizzling, don't be surprised if you get unexpected results.
Cannot be used inside a C++ object. Unfortunately, C++ doesn't support runtime attributes, like objective-c does, so we cannot rely upon our variables being cleaned up eventually. For this reason, you cannot use OBJC_IVAR while inside a C++ object. I would be interested in seeing an implementation for that, though.
#line can mess this up drastically, so don't use it.
Version History
1.0: Initial Release
1.1: Updated OBJC_IVAR_NAME to rely only on the preprocessor. As a result, we cannot use __func__.
So, without further ado, here is the code:
OBJC_IVAR.hpp
//
// OBJC_IVAR.h
// TestProj
//
// Created by Richard Ross on 8/17/12.
// Copyright (c) 2012 Ultimate Computer Services, Inc. All rights reserved.
//
#ifndef OBJC_IVAR_HPP
#define OBJC_IVAR_HPP
#import <Foundation/Foundation.h>
#import <objc/runtime.h>
#import "NSValue+CppObject.h"
// Argument counting algorithm. Not too complex
#define __NARG(_1, _2, _3, _4, _5, VAL, ...) VAL
#define NARG(...) __NARG(__VA_ARGS__, 5, 4, 3, 2, 1, 0)
// Different implementations based on number of parameters passed in
#define __OBJC_IVAR(N, ...) _OBJC_IVAR_ ## N (__VA_ARGS__)
#define _OBJC_IVAR(N, ...) __OBJC_IVAR(N, __VA_ARGS__)
// Usage: OBJC_IVAR(Type (optional), Name (required), Default (optional))
#define OBJC_IVAR(...) _OBJC_IVAR(NARG(__VA_ARGS__), __VA_ARGS__)
// create a unique name. we use '__COUNTER__' here to support scoping on the same line, for compressed source code
#define __OBJC_IVAR_STRINGIFY_NAME(file, line, name, counter) #file ":" #line " " #name ":" #counter
#define _OBJC_IVAR_NAME(file, line, name, counter) __OBJC_IVAR_STRINGIFY_NAME(file, line, name, counter)
#define OBJC_IVAR_NAME(name) _OBJC_IVAR_NAME(__FILE__, __LINE__, name, __COUNTER__)
// old style creation. advantage: uses __func__ to determine calling function
// #define OBJC_IVAR_NAME(Name) [NSString stringWithFormat:#"%s:%i %s:%s:%i", __FILE__, __LINE__, __func__, #Name, __COUNTER__]
// implemenations for each of the overloads
#define _OBJC_IVAR_0(...) _Pragma("message \"Cannot call OBJC_IVAR with 0 params!\"")
#define _OBJC_IVAR_1(Name) _OBJC_IVAR_2(__strong id, Name)
// first major implemenation. because we do no assignment here, we don't have to check for is_set
#define _OBJC_IVAR_2(Type, Name) Type& Name = (_OBJC_IVAR::IMPL<Type>(self, OBJC_IVAR_NAME(Name)))
// this is where things get fun. we have 'OBJC_IVAR_CUR_NAME', instead of calling OBJC_IVAR_NAME
// multiple times, because we must ensure that COUNTER does not change during the course of the macro
// this is the 'inner bowels' of C, and it's quite hacky. Returns a reference to an associated object
// which is wrapped in a NSValue. Note that we only evaluate 'default' once throught the course of the
// application's cycle, so you can feel free to put intensive loading code there.
static NSString *_OBJC_IVAR_CUR_NAME;
#define _OBJC_IVAR_3(Type, Name, Default) Type& Name = (_OBJC_IVAR::IS_SET(self, (_OBJC_IVAR_CUR_NAME = OBJC_IVAR_NAME(Name))) ? _OBJC_IVAR::IMPL<Type>(self, _OBJC_IVAR_CUR_NAME) : _OBJC_IVAR::IMPL<Type>(self, _OBJC_IVAR_CUR_NAME, Default))
// namespace to wrap al lof our functions
namespace _OBJC_IVAR
{
// internal dictionary of all associated object names, so that we don't run
// into memory management issues. we use a set here, because we should never
// have duplicate associated object names.
static NSMutableSet *_names = [NSMutableSet set];
// wraps a value and a reference to a value. used over std::reference_wrapper,
// as that doesn't actually copy in the value passed. That is required for what
// we are doing, as we cannot be assigning to constants.
template<typename T>
class Wrapper {
private:
// private value wrapped by this object.
T _value;
// private reference wrapped by this object. should always point to _value.
T& _ref;
public:
// default constructor. assumes 'T' has a valid 0-argument constructor
Wrapper() : _value(), _ref(_value) { }
// argument constructor. makes sure that value is initialized properly
Wrapper(T val) : _value(val), _ref(_value) { }
// returns the reference wrapped by this object
operator T& () {
return _ref;
}
T& get() {
return _ref;
}
};
// interns a name. because objc_getAssociatedObject works only by comparing
// pointers (and +stringWithFormat: isn't guaranteed to return the same pointer),
// we have to make sure that we maintain a list of all valid associated object
// names. these are NOT linked to specific objects, which allows us to reuse some
// memory
inline NSString *name_intern(NSString *name)
{
// intern the value. first check if the object has been interned already,
// and if it is, return that interned value
if (id tmpName = [_names member:name])
{
name = tmpName;
}
// if we haven't interned this value before, then add it to the list and return it.
else
{
[_names addObject:name];
}
return name;
}
// check and see if the requested iVar has been set yet. used for default value setting
BOOL IS_SET(id target, NSString *name)
{
// first intern the name
name = name_intern(name);
// check if the object has this property. objc_getAssociatedObject will ALWAYS
// return NULL if the object doesn't exist. Note the bridged cast. This is because
// objc_getAssociatedObject doesn't care what you throw into the second parameter,
// as long as it is a pointer. That gives us the flexibility at a later date, to,
// for example, just pass a pointer to a single byte, and pull out the value that
// way. However, we pass in a NSString pointer, because it makes it easy for us to
// use and to re-use later.
id val = objc_getAssociatedObject(target, (__bridge const void *) name);
return val != nil;
}
// the actual implementation for setting the iVar. luckily this code isn't too hacky,
// but it is a bit confusing.
template<typename T>
Wrapper<T>& IMPL(id target, NSString *name)
{
// first intern the name
name = name_intern(name);
// define a reference. we use pointers & new here, because C++ memory managment is
// weird at best. Most of the time, you should be using RAII, but when dealing with
// templates & objective-c interpolation, it is almost required that you use pointers
// with new.
Wrapper<T> *reference = nullptr;
// check and see if the object already contains this property, if so, return that value
NSValue *result = objc_getAssociatedObject(target, (__bridge const void *) name);
if (result == nil)
{
// at this point, we need to create a new iVar, with the default constructor for the type.
// for objective-c objects this is 'nil', for integers and floating point values this is 0,
// for C++ structs and classes, this calls the default constructor. If one doesn't exist,
// you WILL get a compile error.
reference = new Wrapper<T>();
// we now set up the object that will hold this wrapper. This is an extension on NSValue
// which allows us to store a generic pointer (in this case a C++ object), and run desired
// code on -dealloc (which will be called at the time the parent object is destroyed), in
// this case, free the memory used by our wrapper.
result = [NSValue valueWithCppObject:reference onDealloc:^(void *) {
delete reference;
}];
// finally, set the associated object to the target, and now we are good to go.
// We use OBJC_ASSOCIATION_RETAIN, so that our NSValue is properly freed when done.
objc_setAssociatedObject(target, (__bridge const void *) name, result, OBJC_ASSOCIATION_RETAIN);
}
// from result, we cast it's -cppObjectValue to a Wrapper, to pull out the value.
reference = static_cast<Wrapper<T> *>([result cppObjectValue]);
// finally, return the pointer as a reference, not a pointer
return *reference;
}
// this is pretty much the same as the other IMPL, but it has specific code for default values.
// I will ignore everything that is the same about the two functions, and only focus on the
// differences, which are few, but mandatory.
template<typename T>
Wrapper<T>& IMPL(id target, NSString *name, const T& defVal)
{
name = name_intern(name);
Wrapper<T> *reference = nullptr; // asign to be the default constructor for 'T'
NSValue *result = objc_getAssociatedObject(target, (__bridge const void *) name);
if (result == nil)
{
// this is the only difference. Instead of constructing with the default constructor,
// simply pass in our new default value as a copy.
reference = new Wrapper<T>(defVal);
result = [NSValue valueWithCppObject:reference onDealloc:^(void *) {
delete reference;
}];
objc_setAssociatedObject(target, (__bridge const void *) name, result, OBJC_ASSOCIATION_RETAIN);
}
reference = static_cast<Wrapper<T> *>([result cppObjectValue]);
return *reference;
}
}
#endif // OBJC_IVAR_HPP
NSValue+CppObject.h
//
// NSValue+CppObject.h
// TestProj
//
// Created by Richard Ross on 8/17/12.
// Copyright (c) 2012 Ultimate Computer Services, Inc. All rights reserved.
//
#import <Foundation/Foundation.h>
// Extension on NSValue to add C++ object support. Because of the difficulty
// involved in templates, I took the easy way out and simply passed in a block
// of code to be run at dealloc.
#interface NSValue (CppObject)
// create a new NSValue instance that holds ptr, and calls 'deallocBlock' on destruction.
+(id) valueWithCppObject:(void *) ptr onDealloc:(void (^)(void *)) deallocBlock;
-(id) initWithCppObject:(void *) ptr onDealloc:(void (^)(void *)) deallocBlock;
// get the held pointer of this object. I called it -cppObjectValue, so
// there was no confusion with -pointerValue.
-(void *) cppObjectValue;
#end
NSValue+CppObject.m
//
// NSValue+CppObject.m
// TestProj
//
// Created by Richard Ross on 8/17/12.
// Copyright (c) 2012 Ultimate Computer Services, Inc. All rights reserved.
//
#import "NSValue+CppObject.h"
// the concrete NSValue subclass for supporting C++ objects. Pretty straight-forward interface.
#interface ConcreteCppObject : NSValue
{
// the underlying object that is being pointed to
void *_object;
// the block that is called on -dealloc
void (^_deallocBlock)(void *);
}
#end
#implementation ConcreteCppObject
// object initialization
+(id) valueWithCppObject:(void *)ptr onDealloc:(void (^)(void *))deallocBlock
{
return [[self alloc] initWithCppObject:ptr onDealloc:deallocBlock];
}
-(id) initWithCppObject:(void *)ptr onDealloc:(void (^)(void *))deallocBlock
{
if (self = [super init])
{
_object = ptr;
_deallocBlock = deallocBlock;
}
return self;
}
// required methods for subclassing NSValue
-(const char *) objCType
{
return #encode(void *);
}
-(void) getValue:(void *)value
{
*((void **) value) = _object;
}
// comparison
-(BOOL) isEqual:(id)compare
{
if (![compare isKindOfClass:[self class]])
return NO;
return [compare cppObjectValue] == [self cppObjectValue];
}
// cleanup
-(void) dealloc
{
// this should manage cleanup for us
_deallocBlock(_object);
}
// value access
-(void *) cppObjectValue
{
return _object;
}
#end
// NSValue additions for creating the concrete instances
#implementation NSValue (CppObject)
// object initialization
+(id) valueWithCppObject:(void *)ptr onDealloc:(void (^)(void *))deallocBlock
{
return [[ConcreteCppObject alloc] initWithCppObject:ptr onDealloc:deallocBlock];
}
-(id) initWithCppObject:(void *)ptr onDealloc:(void (^)(void *))deallocBlock
{
return [[self class] valueWithCppObject:ptr onDealloc:deallocBlock];
}
// unless the NSValue IS a ConcreteCppObject, then we shouldn't do anything here
-(void *) cppObjectValue
{
[self doesNotRecognizeSelector:_cmd];
return nil;
}
#end
Example Usage:
#import "OBJC_IVAR.hpp"
#interface SomeObject : NSObject
-(void) doSomething;
#end
#implementation SomeObject
-(void) doSomething
{
OBJC_IVAR(__strong id, test, #"Hello World!");
OBJC_IVAR(int, test2, 15);
NSLog(#"%#", test);
NSLog(#"%i", test2 += 7);
// new scope
{
OBJC_IVAR(int, test, 100);
NSLog(#"%i", ++test);
}
[self somethingElse];
}
-(void) somethingElse
{
OBJC_IVAR(int, newVar, 7);
NSLog(#"%i", newVar++);
}
#end
int main()
{
SomeObject *obj = [SomeObject new];
[obj doSomething];
[obj doSomething];
[obj doSomething];
}
I had a class, which was not a singleton, that needed a variable
shared between method calls, like static, but each instance needed
it's own variable.
In that case, the variable is part of the object's state, and it's therefore most appropriate to use an instance variable (or a property). This is exactly what ivars are for, whether they're used in a dozen methods or just one.
I am currently working on an Objective-C++ implementation myself, I
was just wondering if anyone else had any thoughts (or existing tools)
on how to do this.
My advice is to not do it at all. If your goal is to avoid clutter, don't go needlessly trying to add a new storage class to the language.
However, if you're determined to pursue this line, I'd look at using blocks instead of associated objects. Blocks get their own copies of variables that are scoped to the lifetime of the block. For example, you can do this:
- (void)func
{
__block int i = 0;
void (^foo)() = ^{
i++;
NSLog(#"i = %d", i);
};
foo();
foo();
foo();
}
and the output you get is:
i = 1
i = 2
i = 3
Perhaps you can find a clever way to wrap that up in a macro, but it looks to me like a lot of trouble just to avoid declaring an instance variable.

Passing in a custom selector implementation

Supposed I have two objective-c classes, LBFoo and LBBar.
In LBFoo I have a method that looks like this:
- (void)doSomethingWithFoo:(NSNumber*)anArgument
{
if(anArgument.intValue > 2)
[LBBar doSomethingWithLBBar];
else
[LBBar doSomethingElseWithLBBar];
}
What I would like to do instead is pass an implementation to LBBar that was not declared ahead of time. (As in dynamically override an existing #selector within LBBar)
I know that an IMP type exists, is it possible to pass an IMP to a class in order to change its selector implementation.
you can use the method_setImplementation(Method method, IMP imp) function in objective-c runtime.
if you want to set an instance method, it would work something like this
method_setImplementation(class_getInstanceMethod([yourClass class], #selector(yourMethod)), yourIMP);
if you want a class method, just use class_getClassMethod instead of class_getInstanceMethod. The arguments should be the same.
that's all there is to it. Note that IMP is just a void function pointer with the first 2 parameters being id self and SEL _cmd
You can certainly use the runtime functions to do something like this,* but I'd suggest that this is exactly the sort of problem that Blocks were introduced to solve. They allow you to pass around a chunk of executable code -- your method can actually accept a Block as an argument and run it.
Here's a SSCCE:
#import <Foundation/Foundation.h>
typedef dispatch_block_t GenericBlock;
#interface Albatross : NSObject
- (void)slapFace:(NSNumber *)n usingFish:(GenericBlock)block;
#end
#implementation Albatross
- (void)slapFace:(NSNumber *)n usingFish:(GenericBlock)block
{
if( [n intValue] > 2 ){
NSLog(#"Cabbage crates coming over the briny!");
}
else {
block(); // Execute the block
}
}
#end
int main(int argc, const char * argv[])
{
#autoreleasepool {
Albatross * p = [Albatross new];
[p slapFace:[NSNumber numberWithInt:3] usingFish:^{
NSLog(#"We'd like to see the dog kennels, please.");
}];
[p slapFace:[NSNumber numberWithInt:1] usingFish:^{
NSLog(#"Lemon curry?");
}];
}
return 0;
}
*Note that using method_setImplementation() will change the code that's used every time that method is called in the future from anywhere -- it's a persistent change.

Objective-C blocks usage

I have been looking around online, doing research into how to use blocks. I have also decided to set up a basic example to try and understand the way in which they work.
Essentially what I want to do is have a 'block variable' (no sure if thats the correct term) in which I can store a block of code. I then want to be able to set the code in this block at pointX (methodA or methodB) in my code, then run the block of code at pointY (methodX).
So to be specific, my question is 3-fold
Using the example below is the setup / usage of blocks correct and valid?
In methodX how do I execute the code inside the block (self.completionBlock)?
When creating the block in methodA and methodB will the code be called there and then? If so how can I stop this from happening (all I want to do is set up the code in the block to be called later)?
I may have completely misunderstood how blocks are used, apologies if this is the case, however I'm relatively new to Objective-C and I'm trying to learn.
Here is my code so far:
.h
typedef void (^ CompletionBlock)();
#interface TestClass : NSObject
{
CompletionBlock completionBlock;
NSString *stringOfText;
NSString *otherStringOfText;
}
#property(nonatomic, copy)CompletionBlock completionBlock;
#property(nonatomic, retain)NSString *stringOfText;
#property(nonatomic, retain)NSString *otherStringOfText;
- (void)methodA:(NSString *)myText;
- (void)methodB:(NSString *)myText and:(NSString *)myOtherText;
- (void)methodX;
#end
.m
- (void)methodA:(NSString *)myText;
{
if ([self.stringOfText isEqualToString:#""])
{
// Set the variable to be used by the completion block
self.stringOfText = #"I visited methodA"; // normally make use of myText
// Create the completion block
__block TestClass *blocksafeSelf = self;
self.completionBlock = ^()
{
[blocksafeSelf methodA:blocksafeSelf.stringOfText];
blocksafeSelf.stringOfText = nil;
};
}
else
{
// Do some other stuff with self.stringOfText
}
}
- (void)methodB:(NSString *)myText and:(NSString *)myOtherText;
{
if ([self.stringOfText isEqualToString:#""] || [self.otherStringOfText isEqualToString:#""])
{
// Set the variable to be used by the completion block
self.stringOfText = #"I visited methodB"; // normally make use of myText
self.otherStringOfText = #"I also visited methodB"; // normally make use of myOtherText
// Create the completion block
__block TestClass *blocksafeSelf = self;
self.completionBlock = ^()
{
[blocksafeSelf methodB:blocksafeSelf.stringOfText and:blocksafeSelf.otherStringOfText];
blocksafeSelf.stringOfText = nil;
blocksafeSelf.otherStringOfText = nil;
};
}
else
{
// Do some other stuff with self.stringOfText and self.otherStringOfText
}
}
- (void)methodX
{
// At this point run the block of code in self.completionBlock...how?!
}
In my example either methodA or methodB will be called first. Then some time later (perhaps from a different class) methodX will be called (only ever after methodA or methodB have been called).
It's worth noting that the methods methodA, methodB and methodX are all in a singleton class.
NOTE: This is just a dummy example to try and understand the workings of blocks, I'm fully aware there are other ways to achieve the same result.
Here's the code, just to be clear:
- (void)methodX
{
if(self.completionBlock)
self.completionBlock();
}
I think you want to do self.completionBlock(); in methodX.

Dynamic method creation in Objective-C

In the book The Pragmatic Programmer, the authors suggest that all method inputs should be validated. This allows problems with a method to be caught early and their sources traced easily.
In my Mac application, I accomplished this by creating an Assert class. This class has several class methods. These methods determine if some precondition is met, and if it is not, then an exception is thrown. A typical assertion might looks something like this:
-(void) setWidth: (int) theWidth {
[Assert integer: width isGreaterThanInteger: 0];
width = theWidth;
}
This works really well, and significantly reduced the amount of time I've spend bug hunting. However, I've noticed lately some of the assertion methods are very useful as predicates. For example, my integer:isGreaterThanInteger:andLessThanInteger: and my stringIsNotEmpty: methods are equally useful. To this end, I created a second class Predicate, which I filled with several of my more useful predicate methods. So I took the logic from the assert methods, and moved it into Predicate, and then rewrote my Assert methods like the following:
if ![Predicate predicateMethod]
throw exception
This has turned into a maintenance nightmare. If I change the name of a method name in Predicate, I must also change it in Assert to stay consistent. If I update the documentation of an Assert method, then I must do the same to a Predicate method.
Ideally, I would like the reconstruct the Assert class so that when any method is called on it, it intercepts the selector. The Predicate class can then be checked to see if it responds to the selector, and if it does, the method is called on Predicatewith the same arguments that were passed into the Assert method. If the Predicate method returns false, then an exception is thrown.
Is there a way to do this in Objective-C?
Thanks.
You could use -forwardingTargetForSelector: to simply forward the method to another object, but if you want advanced behavior (like checking the return value to see if it's false), you may need to use -forwardInvocation:. (However, note that the documentation says this is "much more expensive" than the former option.)
If you're using pure Objective-C, you should see the "Forwarding" discussion here. It basically describes how to do exactly what you want, including example code.
If you're using Cocoa then you might have to use forwardInvocation: instead.
I ended up overriding resolveClassMethod:. While overriding forwardInvocation might have worked (I would have had to figure out some way to override it for the class object), resolveClassMethod: seems like it's the easier and more efficient method. Here's what my final implementation ended up looking like:
#import "Assert.h"
#import "Predicate.h"
#include <objc/objc-runtime.h>
void handlePredicateSelector(id self, SEL _cmd, ...);
#implementation Assert
+(void) failWithMessage: (NSString *) message
{
NSLog(#"%#", message);
[NSException raise:#"ASSERTION FAILURE" format:message];
}
+(void) fail
{
[Assert failWithMessage:#"An unconditional failure has been detected."];
}
+(BOOL) resolveClassMethod: (SEL) selector
{
if ([(id) [Predicate class] respondsToSelector:selector])
{
/*
The meta class fix was taken from here: http://iphonedevelopment.blogspot.com/2008/08/dynamically-adding-class-objects.html
*/
//get the method properties from the Predicate class
Class predicateMetaClass = objc_getMetaClass([[Predicate className] UTF8String]);
Method predicateMethod = class_getClassMethod(predicateMetaClass, selector);
const char *encoding = method_getTypeEncoding(predicateMethod);
Class selfMetaClass = objc_getMetaClass([[self className] UTF8String]);
class_addMethod(selfMetaClass, selector, (IMP) handlePredicateSelector, "B#:?");
return YES;
}
return [super resolveClassMethod:selector];
}
#end
void handlePredicateSelector(id self, SEL _cmd, ...)
{
//get the number of arguments minus the self and _cmd arguments
NSMethodSignature *predicateMethodSignature = [(id) [Predicate class] methodSignatureForSelector:_cmd];
NSUInteger numberOfArguments = [predicateMethodSignature numberOfArguments] - 2;
NSInvocation *predicateInvocation = [NSInvocation invocationWithMethodSignature:predicateMethodSignature];
[predicateInvocation setTarget:[Predicate class]];
[predicateInvocation setSelector:_cmd];
va_list ap;
va_start(ap, _cmd);
for (int i = 0; i < numberOfArguments; i++)
{
void *arg = va_arg(ap, void *);
[predicateInvocation setArgument:&arg atIndex:i+2];
}
va_end(ap);
BOOL returnValue;
[predicateInvocation invoke];
[predicateInvocation getReturnValue:&returnValue];
//determine if the assertion is true
if (!returnValue)
{
[Assert failWithMessage:[NSString stringWithFormat: #"The following assertion failed: %#", NSStringFromSelector(_cmd)]];
}
}
The only thing I couldn't really figure out was how to get the type encoding from the method signature. It didn't seem to affect the output of the methods, but I would like to fix it if I can.