Objective-c tutorial/guide ?

Hi everyone,

I think the majority coding for OSX and iOS is using declares to squeeze the last bit out or even
to implement features which aren’t existing in the Xojo framework.
I honestly do it a lot to make the app more custom looking and support controls function which aren’t provided
by Xojo but sometimes I get stuck in the obj-c especially when it comes down to overriding function or subclassing things.

Is there a good tutorial (no MacOSLib) which explains how to work with subclassing/overriding stuff in obj-c and for
xojo controls ?

None that I really know of, I put my stuff together from a variety of resources. If you have any detailed question, maybe I can give a hint.

Yeah that’s what I am doing too.

I am trying to change the TextField vertical alignment to center,top,bottom. As far as I know you need
to subclass NSCell and override a couple of methods. Sound like a lot of work for it…yes it is.
I kind of think this isn’t possible or or too much work. Anyway, I am stuck here and the methods doesn’t get called.

[code]Private Sub setUpCell(t as TextField)
dim cls as ptr = NSClassFromString(“XOJOCell”)
if cls=nil then
cls = objc_allocateClassPair( NSClassFromString(“NSCell”), “XOJOCell”,0)
if cls<>nil then
if class_addMethod( cls, NSSelectorFromString(“drawingRectForBounds:”), AddressOf drawingRect, “{NSRect=ffff}@:{NSRect=ffff}”) then
if class_addMethod( cls, NSSelectorFromString(“editWithFrame:inView:editor:delegate:event:”), AddressOf editWithFrame, “v@:{NSRect=ffff}@@@@”) then
if class_addMethod( cls, NSSelectorFromString(“selectWithFrame:inView:editor:delegate:start:length:”), AddressOf selectWithFrame, “v@:{NSRect=ffff}@@@ii”) then
objc_registerClassPair(cls)
end if
end if
end if
end if
end if

self.cellRef = init(alloc(cls))

declare sub setCell lib Cocoa selector “setCell:” (obj as ptr, cell as ptr)
setCell( ptr(t.Handle), self.cellRef)

End Sub

[/code]

You need to look at the Objective C Runtime. This is a library with a C API, not an Objective C one. You will have to look at:

  • objc_lookUpClass to test if a class is already registered in the Objective C Runtime
  • objc_allocateClassPair to allocate memory for a new class (and its meta class, hence “class pair”)
  • class_addMethod to register a method and thereby override one from the super class (use AddressOf to redirect to a Xojo method, this Xojo method must be either in a module or it must be a shared method of a class)
  • objc_registerClassPair to register the class and the meta class in the Objective C Runtime
  • objc_msgSendSuper and struct objc_super if you need to call the parent method in your Xojo method which overrides a method in the super class.

An example for implementing a protocol (NSTableViewDataSourceDelegate, subclassing NSObject):

If objc_lookUpClass("myDelegate") = Nil Then Dim cls As Ptr = objc_allocateClassPair(NSClassFromString("NSObject"), "myDelegate", 0) Call class_addMethod(cls, sel_registerName("numberOfRowsInTableView:"), _ AddressOf numberOfRowsInTableView_, "") Call class_addMethod(cls, sel_registerName("tableView:objectValueForTableColumn:row:"), _ AddressOf tableView_objectValueForTableColumn_row_, "") objc_registerClassPair(cls) End setDataSource(mTableView, alloc(NSClassFromString("myDelegate")))

Thanks Eli. Those are the basics which are important to know.

You don’t need to add type encodings for methods you override or for methods from a protocol as the Objective C Runtime already knows them.

Make sure that the methods are shared methods (drawingRect, editWithFrame, selectWithFrame) on your class – or put them in a module.

For a TextArea it would be (don’t know about TextField):

[code]#if TargetCocoa

Declare Sub setTextContainerInset Lib “AppKit” Selector “setTextContainerInset:” (NSTextView As Ptr,
inset As NSSize)
Declare Function documentView Lib “AppKit” Selector “documentView” (NSScrollView As Ptr) As Ptr

Dim size As NSSize
size.width = -2
size.height = 2

Dim scrollView As Ptr = Ptr(Handle)
Dim textView As Ptr = documentView(scrollView)
setTextContainerInset(textView, size)

#endif[/code]