--- title: "MonoTouch ManualSelectorInvocation" lastmodified: '2009-09-07' redirect_from: - /MonoTouch_ManualSelectorInvocation/ --- MonoTouch ManualSelectorInvocation ==================================

Table of contents

Objective-C Selectors ===================== The Objective-C language is based upon **selectors**. A selector is a message that can be sent to an object or a **class**. MonoTouch maps instance selectors to instance methods, and class selectors to static methods. Unlike normal C functions (and like C++ member functions), you cannot directly invoke a selector using [P/Invoke](/Interop_with_Native_Libraries). (Aside: in theory you could use P/Invoke for non-virtual C++ member functions, but you'd need to worry about per-compiler name mangling, which is a world of pain better ignored.) Instead, selectors are sent to an Objective-C class or instance using the [objc_msgSend function](http://developer.apple.com/mac/library/documentation/Cocoa/Reference/ObjCRuntimeRef/Reference/reference.html#//apple_ref/c/func/objc_msgSend). You may find [this helpful guide on Objective-C messaging](http://developer.apple.com/iphone/library/documentation/cocoa/conceptual/ObjCRuntimeGuide/Articles/ocrtHowMessagingWorks.html) useful. Example ------- Suppose you want to invoke the [-[NSString sizeWithFont:forWidth:lineBreakMode:](http://developer.apple.com/iphone/library/documentation/UIKit/Reference/NSString_UIKit_Additions/Reference/Reference.html#//apple_ref/occ/instm/NSString/sizeWithFont:forWidth:lineBreakMode:)] selector. The declaration (from Apple's documentation) is: - (CGSize)sizeWithFont:(UIFont \*)font forWidth:(CGFloat)width lineBreakMode:(UILineBreakMode)lineBreakMode The return type, GSize, is a [System.Drawing.SizeF](http://docs.go-mono.com/monodoc.ashx?link=T%3aSystem.Drawing.SizeF) in managed code (which is a value type). The *font* parameter is a [UIFont](http://docs.go-mono.com/monodoc.ashx?link=T%3aMonoTouch.UIKit.UIFont) (and a type (indirectly) derived from [NSObject](http://docs.go-mono.com/monodoc.ashx?link=T%3aMonoTouch.Foundation.NSObject)), and is thus mapped to [System.IntPtr](http://docs.go-mono.com/monodoc.ashx?link=T:System.IntPtr). The width parameter, a CGFloat, is mapped to [System.Single](http://docs.go-mono.com/monodoc.ashx?link=T%3aSystem.Single). The lineBreakMode parameter, a UILineBreakMode, has already been bound in MonoTouch as the [UILineBreakMode](http://docs.go-mono.com/monodoc.ashx?link=T%3aMonoTouch.UIKit.UILineBreakMode) enumeration. Put it all together, and we want an objc_msgSend declaration that matches: ``` csharp SizeF objc_msgSend(IntPtr target, IntPtr selector, IntPtr font, float width, UILineBreakMode mode); ``` Checking the [MonoTouch.ObjCRuntime.Messaging](http://docs.go-mono.com/monodoc.ashx?link=T%3aMonoTouch.ObjCRuntime.Messaging%2f*) members, we don't see a match for this prototype. Consequently, we will need to declare it ourself: ``` csharp [DllImport (MonoTouch.Constants.ObjectiveCLibrary)] static extern SizeF cgsize_objc_msgSend_IntPtr_float_int ( IntPtr target, IntPtr selector, IntPtr font, float width, UILineBreakMode mode); ``` Once declared, we can invoke it once we have the appropriate parameters: ``` csharp NSString target = ... Selector selector = new Selector ("sizeWithFont:forWidth:lineBreakMode:"); UIFont font = ... float width = ... UILineBreakMode mode = ...   SizeF size = cgsize_objc_msgSend_IntPtr_float_int( target.Handle, selector.Handle, font == null ? IntPtr.Zero : font.Handle, width, mode); ``` Invoking a Selector ------------------- Invoking a selector has three steps: 1. Get the selector target. 2. Get the selector name. 3. Call objc_msgSend() with the appropriate arguments. ### Selector Targets A selector target is either an object instance or an Objective-C class. If the target is an instance and came from a bound MonoTouch type, use the [MonoTouch.ObjCRuntime.INativeObject.Handle](http://docs.go-mono.com/monodoc.ashx?link=P%3aMonoTouch.ObjCRuntime.INativeObject.Handle) property. If the target is a class, use [MonoTouch.ObjCRuntime.Class](http://docs.go-mono.com/monodoc.ashx?link=T%3aMonoTouch.ObjCRuntime.Class) to get a reference to the class instance, then use the [Class.Handle](http://docs.go-mono.com/monodoc.ashx?link=P%3aMonoTouch.ObjCRuntime.Class.Handle) property. ### Selector Names Selector names are listed within Apple's documentation. For example, the [http://developer.apple.com/iphone/library/documentation/UIKit/Reference/NSString_UIKit_Additions/Reference/Reference.html](http://developer.apple.com/iphone/library/documentation/UIKit/Reference/NSString_UIKit_Additions/Reference/Reference.html) UIKit NSString extension methods] include [sizeWithFont:](http://developer.apple.com/iphone/library/documentation/UIKit/Reference/NSString_UIKit_Additions/Reference/Reference.html#//apple_ref/occ/instm/NSString/sizeWithFont:) and [sizeWithFont:forWidth:lineBreakMode:](http://developer.apple.com/iphone/library/documentation/UIKit/Reference/NSString_UIKit_Additions/Reference/Reference.html#//apple_ref/occ/instm/NSString/sizeWithFont:forWidth:lineBreakMode:). The embedded and trailing colons are important, and are part of the selector name. Once you have a selector name, you can create a [MonoTouch.ObjCRuntime.Selector](http://docs.go-mono.com/monodoc.ashx?link=T%3aMonoTouch.ObjCRuntime.Selector) instance for it. ### Calling objc_msgSend() When invoking objc_msgSend(), you must pass the selector target (an instance or class handle), the selector, and any arguments required by the selector. To do so, you use a normal P/Invoke declaration for objc_msgSend(). The instance and selector arguments must be System.IntPtr, and all remaining arguments must match the type the selector expects. Objective-C types (e.g. NSString, NSDictionary, UIView, anything that has NSObject as an eventual base type) are passed as System.IntPtr. A set of pre-made objc_msgSend() declarations can be found in [MonoTouch.ObjCRuntime.Messaging](http://docs.go-mono.com/monodoc.ashx?link=T%3aMonoTouch.ObjCRuntime.Messaging%2f*).