Custom framework iOS


I hope someone can help. I am following the guide here xojo blog loading 3rd party frameworks in xojo ios to add a custom framework to my iOS project.

I have built a framework for iOS with the following in the PenIOS.h file

[code]+ (PenIOS *)sharedInstance;

  • (NSInteger) Test_Int;
  • (NSString *) FunctionOneString;[/code]

And in the PenIOS.m file

[code]- (NSInteger) Test_Int
return 22;

  • (NSString *) FunctionOneString
    NSLog(@“Returning: Test String”);
    return @“Test String”;
  • (PenIOS *)sharedInstance
    static dispatch_once_t predicate = 0;
    __strong static id sharedObject = nil;
    dispatch_once(&predicate, ^{ sharedObject = [[self alloc] init]; });
    return sharedObject;

PenIOS is an NSObject with a sharedInstance as in the framework used on the blog.

I built the framework and added it to a copy files build phase placed between the Build and Sign phases.

I then added the following to a button but num is always 0 and Label1.Text gets set to blank when clicking the button.

[code]Declare Function dlopen Lib “/usr/lib/libSystem.dylib” (name As CString, flags As Int32) As Ptr
Call dlopen("@executable_path/Penios.framework/Penios", 1 Or 8)

// NOTE: We’re specifically NOT using the actual lib name here.
// This is just to satisfy the Xojo linker. The correct framework will be used at runtime.
Declare Function NSClassFromString Lib “Foundation” (clsName As CFStringRef) As Ptr
Dim pbclass As Ptr = NSClassFromString(“PenIOS”)
Declare Function sharedInstance Lib “Foundation” Selector “sharedInstance” (clsref As Ptr) As Ptr
Dim pbclassShared as Ptr = sharedInstance(pbclass)

Declare Function FunctionOneStr lib “Foundation” Selector “FunctionOneString” (obj as ptr) As CFStringRef
Declare Function Test_Int lib “Foundation” Selector “Test_Int” (obj as ptr) As Integer

Dim num As Integer = Test_Int(pbclassShared)
Label1.Text = FunctionOneStr(pbclassShared)[/code]

Any help would be appreciated.
Thanks in advance

Hi Giles,

First make sure that the copy files build step is setup like this:

[quote]Applies to: Both
Subdirectory: Frameworks
Destination: App Parent Folder[/quote]

Then I would recommend loading the framework in a function instead of doing all code in the button:

[code]Protected Function LoadPenIOS() as Boolean

Declare Function dlopen Lib “/usr/lib/libSystem.dylib” ( path As CString, mode As Int32 ) As Ptr
Declare Function dlerror Lib “/usr/lib/libSystem.dylib” As CString

Const RTLD_LAZY = 1

Dim path As Text

path = “@executable_path/Frameworks/Penios”
// or it might be
"path = “@executable_path/Frameworks/Penios.framework/Penios”

Dim result As ptr = dlopen(path.ToCString(xojo.core.TextEncoding.UTF8), RTLD_LAZY Or RTLD_GLOBAL )

If result = Nil Then
Dim reason As Text
reason = Text.FromCString(dlerror, Xojo.Core.TextEncoding.UTF8)
break //read the reason
Return False
End If

System.DebugLog “framework opened.”
Return True
End Function

The rest of your code looks fine, just add:

If LoadPenIOS then

//Your code here

End If

I’m not sure that the “sharedInstance” you get here is what you looking for…

you are calling the Foundation method, not your lib one…

[quote=446130:@Antonio Rinaldi]I’m not sure that the “sharedInstance” you get here is what you looking for…

you are calling the Foundation method, not your lib one…[/quote]
Actually he’s not. It calls the sharedInstance method of the class that’s passed.

First of all thank you all for your answers and taking time to reply.
I managed to get this working finally today by just building the Framework in an older version of Xcode.

I was building with Xcode 10.2.1 and switching to using 10.1.0 cleaning and rebuilding seems to have resolved the issue.

Thank you again for all the help and have a great week! :smiley: