Key-Value-Coding with arbitrary methods, not only properties - objective-c

It seems that -valueForKey: and -valueForKeyPath: work with arbitrary methods, not only with properties. This seems very convenient:
I first stumbled upon it in Interface Builder, and then made some experiments:
// Thing.h
#import <Foundation/Foundation.h>
#interface Thing : NSObject
- (BOOL) alwaysYES;
- (BOOL) alwaysNO;
#end
// Thing.m
#import "Thing.h"
#implementation Thing
- (BOOL) alwaysYES
{
return YES;
}
- (BOOL) alwaysNO
{
return NO;
}
#end
I can call these methods via -valueForKey: and -valueForKeyPath: despite the fact that they are normal methods and no properties:
Thing *aThing = [[Thing alloc] init];
id result;
result = [aThing valueForKey:#"alwaysYES"];
NSLog(#"result is: %#", result);
result = [aThing valueForKeyPath:#"alwaysNO"];
NSLog(#"result is: %#", result);
Compiles, runs and gives the correct results. Is this documented anywhere? Can I safely use it? How can i understand it?

Cocoa's key-value coding (KVC) system is older than support for explicit properties (declared with #property) in Objective-C, so KVC is defined in terms of methods, not properties.
“Default Search Pattern for valueForKey:” in the Key-Value Coding Programming Guide spells out how valueForKey: decides what to do. It starts by looking for (amongst other things) a method whose name is exactly the key you passed to valueForKey:. Here is the full search pattern, quoted from the documentation:
Searches the class of the receiver for an accessor method whose name matches the pattern get<Key>, <key>, or is<Key>, in that order. If such a method is found it is invoked. If the type of the method's result is an object pointer type the result is simply returned. If the type of the result is one of the scalar types supported by NSNumber conversion is done and an NSNumber is returned. Otherwise, conversion is done and an NSValue is returned. Results of arbitrary types are converted to NSValue objects, not just NSPoint, NSRange, NSRect, and NSSize types).
Otherwise (no simple accessor method is found), searches the class of the receiver for methods whose names match the patterns countOf<Key> and objectIn<Key>AtIndex: (corresponding to the primitive methods defined by the NSArray class) and <key>AtIndexes: (corresponding to the NSArray method objectsAtIndexes:).
If the countOf<Key> method and at least one of the other two possible methods are found, a collection proxy object that responds to all NSArray methods is returned. Each NSArray message sent to the collection proxy object will result in some combination of countOf<Key>, objectIn<Key>AtIndex:, and <key>AtIndexes: messages being sent to the original receiver of valueForKey:. If the class of the receiver also implements an optional method whose name matches the pattern get<Key>:range: that method will be used when appropriate for best performance.
Otherwise (no simple accessor method or set of array access methods is found), searches the class of the receiver for a threesome of methods whose names match the patterns countOf<Key>, enumeratorOf<Key>, and memberOf<Key>: (corresponding to the primitive methods defined by the NSSet class).
If all three methods are found, a collection proxy object that responds to all NSSet methods is returned. Each NSSet message sent to the collection proxy object will result in some combination of countOf<Key>, enumeratorOf<Key>, and memberOf<Key>: messages being sent to the original receiver of valueForKey:.
Otherwise (no simple accessor method or set of collection access methods is found), if the receiver's class method accessInstanceVariablesDirectly returns YES, the class of the receiver is searched for an instance variable whose name matches the pattern _<key>, _is<Key>, <key>, or is<Key>, in that order. If such an instance variable is found, the value of the instance variable in the receiver is returned. If the type of the result is one of the scalar types supported by NSNumber conversion is done and an NSNumber is returned. Otherwise, conversion is done and an NSValue is returned. Results of arbitrary types are converted to NSValue objects, not just NSPoint, NSRange, NSRect, and NSSize types.
If none of the above situations occurs, returns a result the default implementation invokes valueForUndefinedKey:.

This is parallel to the fact that you can call these methods using property syntax:
BOOL ok = aThing.alwaysYES
In that case and in your case, exactly the same thing happens: the first thing the runtime tries is to treat this as a getter method. What you've written is a getter method.
As for your question "can I safely use it", safely yes, but what you're doing is kind of silly, since you know (and have declared) that these methods exist. KVC is about probing to see whether methods exist. If you have a reason to specify one of these methods by string name, there are better ways to call it than using KVC.

Properties are nothing special at runtime; they generate a getter and setter (if not readonly) which conforms to KVC; for example:
#property NSString *aString;
will generate:
- (NSString)aString {
...
}
- (void)setAString(NSString *string) {
...
}
just as if you had declared those methods in the header (which itself is optional).
See the Key Value Coding Fundamentals documentation.

Related

What does Objective-C property get resolved to in runtime?

What does Objective-C property get resolved to in runtime? Will calling [obj valueForKey:#"property"] always yield the same result?
e.g.
obj.property
First, note that obj.property is precisely the same as [obj property]. Dot syntax is just syntactic sugar. While there are some small run-time implementation details related to properties that are different than other methods, for the purposes of this discussion, think only in terms of "I have an ivar named _key and a method called -key." The fact that you created that ivar and method by declaring a property is irrelevant for valueForKey:.
valueForKey: is a method, and it can be overridden by a class to return whatever it likes. The default behavior is that valueForKey: will first look for a method whose name matches the key, and will return the result of that. In the vast majority of cases, this means that if you have a property, then valueForKey:#"property" will return the value of it.
The full search path for the default implementation of valueForKey: is explained in "Accessor Search Implementation Details", but here is the "short" version:
get<Key>, <key>, is<Key> (yes, the first place it looks is getKey, which is a little embarrassing because you should not prefix getters with get unless they return values by reference, but there you go; it is the first thing checked.)
countOf<Key>, objectIn<Key>AtIndex:, and <key>AtIndexes. If a legal combination of these are found, then an NSArray-like proxy object is returned.
countOf<Key>, enumeratorOf<Key>, and memberOf<Key>:. If all three are found, then an NSSet-like proxy object is returned.
If accessInstanceVariablesDirectly is YES (the default), then ivars are checked, named _<key>, _is<Key>, <key>, or is<Key>. Yes, this is a way to access an object's private ivars.
If everything else failed, then it calls valueForUndefinedKey:, which is free to return a result (and this is in fact a very useful thing to do if you want a generic key/value store).
But nine times out of ten, you're going to get the value of the method named <key>.
Side note: valueForKey: returns an object. If the return is a number-like scalar (including BOOL), it will return an NSNumber. Otherwise it will return an NSValue. There is some special handling for NSPoint, NSRange, NSRect, and NSSize (on Mac; on iOS, only NSRange is handled specially I believe).
obj.property is the same as [obj property], not [obj valueForKey:#"property"];. The latter is part of a system called Key Value Coding that's separate from properties.

Would it be beneficial to begin using instancetype instead of id?

Clang adds a keyword instancetype that, as far as I can see, replaces id as a return type in -alloc and init.
Is there a benefit to using instancetype instead of id?
Yes, there are benefits to using instancetype in all cases where it applies. I'll explain in more detail, but let me start with this bold statement: Use instancetype whenever it's appropriate, which is whenever a class returns an instance of that same class.
In fact, here's what Apple now says on the subject:
In your code, replace occurrences of id as a return value with instancetype where appropriate. This is typically the case for init methods and class factory methods. Even though the compiler automatically converts methods that begin with “alloc,” “init,” or “new” and have a return type of id to return instancetype, it doesn’t convert other methods. Objective-C convention is to write instancetype explicitly for all methods.
Emphasis mine. Source: Adopting Modern Objective-C
With that out of the way, let's move on and explain why it's a good idea.
First, some definitions:
#interface Foo:NSObject
- (id)initWithBar:(NSInteger)bar; // initializer
+ (id)fooWithBar:(NSInteger)bar; // class factory
#end
For a class factory, you should always use instancetype. The compiler does not automatically convert id to instancetype. That id is a generic object. But if you make it an instancetype the compiler knows what type of object the method returns.
This is not an academic problem. For instance, [[NSFileHandle fileHandleWithStandardOutput] writeData:formattedData] will generate an error on Mac OS X (only) Multiple methods named 'writeData:' found with mismatched result, parameter type or attributes. The reason is that both NSFileHandle and NSURLHandle provide a writeData:. Since [NSFileHandle fileHandleWithStandardOutput] returns an id, the compiler is not certain what class writeData: is being called on.
You need to work around this, using either:
[(NSFileHandle *)[NSFileHandle fileHandleWithStandardOutput] writeData:formattedData];
or:
NSFileHandle *fileHandle = [NSFileHandle fileHandleWithStandardOutput];
[fileHandle writeData:formattedData];
Of course, the better solution is to declare fileHandleWithStandardOutput as returning an instancetype. Then the cast or assignment isn't necessary.
(Note that on iOS, this example won't produce an error as only NSFileHandle provides a writeData: there. Other examples exist, such as length, which returns a CGFloat from UILayoutSupport but a NSUInteger from NSString.)
Note: Since I wrote this, the macOS headers have been modified to return a NSFileHandle instead of an id.
For initializers, it's more complicated. When you type this:
- (id)initWithBar:(NSInteger)bar
…the compiler will pretend you typed this instead:
- (instancetype)initWithBar:(NSInteger)bar
This was necessary for ARC. This is described in Clang Language Extensions Related result types. This is why people will tell you it isn't necessary to use instancetype, though I contend you should. The rest of this answer deals with this.
There's three advantages:
Explicit. Your code is doing what it says, rather than something else.
Pattern. You're building good habits for times it does matter, which do exist.
Consistency. You've established some consistency to your code, which makes it more readable.
Explicit
It's true that there's no technical benefit to returning instancetype from an init. But this is because the compiler automatically converts the id to instancetype. You are relying on this quirk; while you're writing that the init returns an id, the compiler is interpreting it as if it returns an instancetype.
These are equivalent to the compiler:
- (id)initWithBar:(NSInteger)bar;
- (instancetype)initWithBar:(NSInteger)bar;
These are not equivalent to your eyes. At best, you will learn to ignore the difference and skim over it. This is not something you should learn to ignore.
Pattern
While there's no difference with init and other methods, there is a difference as soon as you define a class factory.
These two are not equivalent:
+ (id)fooWithBar:(NSInteger)bar;
+ (instancetype)fooWithBar:(NSInteger)bar;
You want the second form. If you are used to typing instancetype as the return type of a constructor, you'll get it right every time.
Consistency
Finally, imagine if you put it all together: you want an init function and also a class factory.
If you use id for init, you end up with code like this:
- (id)initWithBar:(NSInteger)bar;
+ (instancetype)fooWithBar:(NSInteger)bar;
But if you use instancetype, you get this:
- (instancetype)initWithBar:(NSInteger)bar;
+ (instancetype)fooWithBar:(NSInteger)bar;
It's more consistent and more readable. They return the same thing, and now that's obvious.
Conclusion
Unless you're intentionally writing code for old compilers, you should use instancetype when appropriate.
You should hesitate before writing a message that returns id. Ask yourself: Is this returning an instance of this class? If so, it's an instancetype.
There are certainly cases where you need to return id, but you'll probably use instancetype much more frequently.
There definitely is a benefit. When you use 'id', you get essentially no type checking at all. With instancetype, the compiler and IDE know what type of thing is being returned, and can check your code better and autocomplete better.
Only use it where it makes sense of course (i.e. a method that is returning an instance of that class); id is still useful.
Above answers are more than enough to explain this question. I would just like to add an example for the readers to understand it in terms of coding.
ClassA
#interface ClassA : NSObject
- (id)methodA;
- (instancetype)methodB;
#end
Class B
#interface ClassB : NSObject
- (id)methodX;
#end
TestViewController.m
#import "ClassA.h"
#import "ClassB.h"
- (void)viewDidLoad {
[[[[ClassA alloc] init] methodA] methodX]; //This will NOT generate a compiler warning or error because the return type for methodA is id. Eventually this will generate exception at runtime
[[[[ClassA alloc] init] methodB] methodX]; //This will generate a compiler error saying "No visible #interface ClassA declares selector methodX" because the methodB returns instanceType i.e. the type of the receiver
}
You also can get detail at The Designated Initializer
**
INSTANCETYPE
**
This keyword can only be used for return type, that it matches with return type of receiver. init method always declared to return instancetype.
Why not make the return type Party for party instance, for example?
That would cause a problem if the Party class was ever subclassed. The subclass would inherit all of the methods from Party, including initializer and its return type. If an instance of the subclass was sent this initializer message, that would be return? Not a pointer to a Party instance, but a pointer to an instance of subclass. You might think that is No problem, I will override the initializer in the subclass to change the return type. But in Objective-C, you cannot have two methods with the same selector and different return types (or arguments). By specifying that an initialization method return "an instance of the receiving object," you would never have to worry what happens in this situation.
**
ID
**
Before the instancetype has been introduced in Objective-C, initializers return id (eye-dee). This type is defined as "a pointer to any object". (id is a lot like void * in C.) As of this writing, XCode class templates still use id as the return type of initializers added in boilerplate code.
Unlike instancetype, id can be used as more than just a return type. You can declare variables or method parameters of type id when you are unsure what type of object the variable will end up pointing to.
You can use id when using fast enumeration to iterate over an array of multiple or unknow types of objects. Note that because id is undefined as "a pointer to any object," you do not include an * when declaring a variable or object parameter of this type.
The special type instancetype indicates that the return type from the init method will be the same class as the type of object it is initializing (that is, the receiver of the init message). This is an aid for the compiler so that it can check your program and flag potential
type mismatches—it determines the class of the returned object based on context; that is, if you’re sending the init message to a newly alloc’ed Fraction object, the compiler will infer that the value returned from that init method (whose return type has been declared as type instancetype) will be a Fraction object. In the past the return type from an initialization method was declared as type id. This new type makes more sense when you consider subclassing, as the inherited initialization methods cannot explicitly define the type of object they will return.
Initializing Objects, Stephen G. Kochan, Programming in Objective-C, 6th Edition

What's the difference between KVC and Properties?

So, I've already read up on the documentation which notes
Objective-C 2.0’s dot syntax and key-value coding are orthogonal technologies. You can use key-value coding whether or not you use the dot syntax, and you can use the dot syntax whether or not you use KVC. Both, though, make use of a “dot syntax.” In the case of key-value coding, the syntax is used to delimit elements in a key path. It is important to remember that when you access a property using the dot syntax, you invoke the receiver’s standard accessor methods.
It then provided an example that supposedly showed the difference between the two. However, I still don't get, what's the difference between KVC and property accessor methods? Aren't they the same? And how do I distinguish between dots that call setValue:forKeyPath: and simple accessors?
However, I still don't get, what's the difference between KVC and property accessor methods?
KVC is a way to call property accessor methods, or otherwise access a property.
What do I mean by “otherwise access”? For KVC purposes, an instance variable with no accessor methods counts as an informal property. It'll get or set the value of the instance variable directly if no matching accessor pair can be found. (Yes, this is not worth using in modern code. Always declare an #property for anything you intend to access elsewhere, and, inversely, don't use KVC to access anything that isn't a public property.)
Property accessor methods are what KVC will call if they exist (preferred, both by KVC and by every sane programmer, over direct ivar access). An accessor may get or set an instance variable, as synthesized accessors do, or access some other storage.
Accessors are implementation, properties are interface, and KVC is one way to use them.
And how do I distinguish between dots that call setValue:forKeyPath: and simple accessors?
A key path is a string, whereas a property-access expression is an expression. The compiler evaluates a property-access expression and translates it into one or more Objective-C messages, whereas a key path is evaluated by KVC at run time.
So, when you use a key path:
[someObject setValue:theValue forKeyPath:#"foo.bar.baz"];
You know it's a key path because (1) it's a string, as indicated in this case by the string-literal syntax #"…", and (2) you're passing the key-path string to setValue:forKeyPath: for it to evaluate.
Using a key path is using KVC to access the named properties. It will send any relevant accessor messages on your behalf.
When you use a property-access expression:
someObject.foo.bar.baz = theValue;
You know it's a property access expression because you are not identifying the properties with a string. You are accessing them (sending the accessor messages) yourself, in your own code.
There isn't much reason to use KVC in any form; when you know the property at authorship/compile time, it's best to have an #property declared and to access the property yourself, whether with property-access expressions or message expressions ([[[someObject foo] bar] setBaz:theValue]). The time to use KVC is when you don't know what property you want to access until run time, which is pretty rare. It's mainly a building-block technology behind KVO, Cocoa Bindings, parts of Core Animation, etc.
Mostly, you'll only want to access properties yourself.
Key value coding allows you to set and get the value of properties through code using the string name of the property. For example, if I had a property named foo which is of type NSString:
[self setValue:#"mystring" forKey:#"foo"];
// read the value by key
NSString *s = [self valueForKey:#"foo"];
Dot syntax is compile syntax sugar. As a personal preference (as some don't agree - fine) I don't use dot syntax but I still use KVC:
[myObj setFoo: #"someString"]
equals:
myObj.foo = #"someString";
They are orthogonal, different concepts but both dealing with how you interact with properties
Finally, you mention property syntax. Yet another orthogonal concept but related to dealing with properties.
With objective-c, convention is important. Follow them. Properties are the name of the property for the get and set[Name] for the assignment:
- (NSString*)foo
{
return _foo; // defined as (NSString*)_foo in header
}
- (void) setFoo: (NSString*)foo
{
if (foo == _foo)
return;
NSString* curr = _foo;
_foo = [foo retain];
[curr release];
}
Now, who wants to write something like that every time. So, enter #property syntax:
In header:
#property (retain) NSString *foo;
Then in .m:
#synthesize foo;
That's the equivalent of the hand written property accessors. It's compiler syntax sugar which expands the property code based on how you attribute the properties.
Docs:
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/KeyValueCoding/Articles/KeyValueCoding.html
http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html

Elementary Obj-C Question bout Methods

take example:
-(void)setName:(NSString *)name age:(int)age;
How would you call this method (in other words, the method's name is setName but what is the "age" parameter doing in there) and what do the types in parentheses mean? Is it just a way to tell the compiler what types are being returned?
[ myObject setName: #"Adam" age:18 ];
The age parameter is the second parameter in the method signature.
The types in parentheses are the expected types for the argument. e.g. name is expecting only an NSString and age is expecting only an int.
The - means that the method is an instance method, not a class method, which is denoted using a + instead.
The type in parentheses right after the - is the return type.
This is a great site for learning the basics of Objective-C: CocoaDevCentral
To answer, one would need a bit more information, but I'll be guessing this is from some sort of class named aClass, and you have an instance of aClass, named instance.
-(void)setName:(NSString *)name age:(int)age;
means you have a method, named setName:age:, that needs two arguments, one NSString, one int, and it returns a void. As it has a - as it's first character, it is an instance method.
[instance setName:#"James Hargrove" age:21];
Would call setName:age: on the instance.
(The instance should be created using, say,
aClass *instance = [[aClass alloc] init];
which would create an instance of aClass named instance, and initialize it.
This is the standard Objective-C method syntax. This could be read as:
A method with no return value (void) that
sets the name of the object (an NSString * parameter)
and the age (and integer
parameter).
Dissecting the method:
"-" The hyphen states that this is an instance method.
(void) The return type is void - or
no return type expected
setName:(NSString *) The first
parameter to be passed is the "name"
and is an NSString *.
age:(int)age The second parameter
to be passed is the "age" and is
an int.
In reality, the method syntax is actually quite self-documenting once understood (and quite foreign if you're used to more tradition C/C++ or Java syntax).
The actual example of the call of this method would be:
[someObject setName:#"Rich" age:101];
The method name is actually this:
setName:age:
You call it like this:
[someObject setName:#"Alice" age:20];
setName:age: is also the unique signature of that method, and with that signature you can call that method on any object you wish. For example:
NSArray* objects = ...
SEL mySelector = #selector(setName:age:);
for (id object in objects)
{
if ([object respondsToSelector:mySelector])
{
[object setName:#"Alice" age:20];
}
}
what do the types in parentheses mean? Is it just a way to tell the compiler what types are being returned?
Yes, those are "C casts". If everything was an object you wouldn't need those, but because you can pass and return plain old C types to and from your methods, the compiler needs to know the types of your parameters and return values.
You'd call this method like so:
[classInstance setName:#"name" age:123];
The first instance of "age:" indicates that the method receives another parameter, called "age" when used in the implementation of the method.
The types in parentheses indicate the types of data that are expected for each parameter, with the exception of the first one, "void", which means that this method returns nothing.
So, you would call this method as follows.
Say it is a method of an object named foo (of class Foo). Then you would call:
[foo setName:someName age:someAge].
If it were a static method, it would be preceded by a + instead of a minus as follows:
+(void)setName:(NSString *)name age:(int)age;
Then you would call
[Foo setName:someName age:someAge] //use the classname instead of the object name
The types are indeed there for type-checking by the compiler. You'll get warnings if you pass the wrong sort of data, and you will get warnings if your header doesn't match your implementation.
You can actually write Obj-C functions in a couple of different styles though, omitting some of this stuff. You can even write straight up C-style.

Using (id) in Objective-C

I have a function that I want to operate on two different custom objects. My first thought was to accept the argument as an (id) and operate on the id object. I can't quite seem to figure out how to do that, however.
Both classes (say apples and oranges) have interface variables:
NSDecimalNumber *count;
I want to do something similar to this:
-(NSDecimalNumber*)addCount:(id)addObject{
return [count decimalNumberByAdding:addObject.count];
}
I can't seem to figure out the syntax to make that happen. Is this the proper approach, or would it be better to subclass (from say a fruit class) and operate on the parent class?
-(NSDecimalNumber*)addCount:(Fruit*)addFruit{
return [count decimalNumberByAdding:addFruit.count];
}
While you can send a message to any object (id) - property accessors require that the compiler be aware of the type you are dealing with - this is because property accessors are syntactic sugar around calling specific getter and setter methods.
You have a few of ways of working around this:
Instead of accessing the count property, call the corresponding [getCount] methods.
If the different classes have different versions of this method, you can use a runtime type check:
Provide a base class for both types so that you can pass in something more specific than (id).
Define and implement a Protocol that both objects implement that defines a count property (or method).
Example of a dynamic type check:
if( [object isKindOfClass:[Apple Class] )
// call one overload of getCount
else if( [object isKindOfClass:[Orange Class] )
// call another overload of getCount
Personally, I favor strong typing in my code because it makes it easier to understand the intent. It also allows the IDE to support your coding effort with intellisense, static analysis, and refactoring features. So, in your case, I would use either #3 or #4 as an approach - depending on whether inheritance is really appropriate for the problem.
You should try not to access instance variables from another class.
In Objective-C it's enough that the two objects respond to the same selector (say count), however that would give you a compiler warning.
There are two ways you can get rid of this warning: either by subclassing from a common Fruit class or by having your two classes conform to a protocol. I'd go with the protocol:
#protocol FruitProtocol
- (NSDecimalNumber *)count;
#end
#interface Orange : NSObject<FruitProtocol>
#end
#interface Apple : NSObject<FruitProtocol>
#end
Then your method can look like this:
-(NSDecimalNumber*)addCount:(id<FruitProtocol>)addFruit {
return [count decimalNumberByAdding:[addFruit count]];
}
Here you are saying that your addCount expects any object that conforms to the FruitProtocol protocol, and hence can respond to the count selector, so the compiler will accept it.
The fact that you are trying to access 'addFruit.count' is the problem. The dot syntax is only for properties declared with #property (or for structs). If you change it to
[addFruit count]
and add
-(NSDecimalNumber*)count
{
return [[count retain] autorelease];
}
to each class, then it would work. However, you will notice you'll get a warning saying 'id' may not respond to the 'count' message, and unless you can be absolutely sure the items sent to this method implement a 'count' method, this is a problematic approach.
I agree with pgb's approach. You should define a protocol, and declare both classes to implement that protocol. This eliminates the problem of not knowing whether the object will respond to 'count' or not, as you now have a 'contract' of sorts.
If you want to keep the dot syntax with a property, you can declare it in the protocol:
#protocol FruitProtocol
#property(readonly) NSDecimalNumber * count;
- (NSDecimalNumber *)count
#end
and then, your function would be:
-(NSDecimalNumber*)addCount:(id<FruitProtocol>)addObject{
return [count decimalNumberByAdding:addObject.count];
}
You're sending the message to count, what is count? id is a pointer to any type of object. If you expect the object to have a count property, then you should only be able to pass in an Array (or some other type restriction).
-(NSDecimalNumber*)addCount:(NSArray*) Object{
return [count decimalNumberByAdding: [Object count]];
}
As I understand it, id does not have any methods or variables associated with it because it is a generic pointer that does not refer to any specific class. This page has some good info on ids if you scroll down a bit.
anObject this will not have a count variable, which is why your first attempt won't work. Creating a base class and using that as a parameter to the method seems like the best idea to me.