iOS Tutorial [Tool] Swifter - Inline Swift code support

Here you can find a new (experimental) tool called Swifter (v. 1.0 beta) which allows you to add Swift code to your B4i Project.

How to use?
  • Open Swifter and enter the B4i installation path
  • enter the path of the project in which you want to use Swift
  • Click on Activate and restart B4i (if it was open)
That's all concerning the tool. Now we can add Swift code to our project:
  • In every project, you want to use Swift, you need this code snippet:
B4X:
Private Swifter As NativeObject
Sub CallSwift(MethodName As String, ParamNames() As List, Params() As Object) As NativeObject
    If Not(Swifter.IsInitialized) Then
        Swifter = Me
        Swifter = Swifter.RunMethod("InitSwifter",Null)
    End If

    If Not(ParamNames = Null) Then
        Dim ArgsStr As String
        For Each Arg As String In ParamNames
            If ArgsStr = "" Then ArgsStr ="With"
            If Arg.Length > 1 Then
                ArgsStr = ArgsStr & Arg.SubString2(0,1).ToUpperCase & Arg.SubString(1) & ":"
            Else
                ArgsStr = ArgsStr & Arg.ToUpperCase & ":"
            End If
        Next
    End If

    Return Swifter.RunMethod(MethodName & ArgsStr,Params)
End Sub

#if objc
#import "B4iProject-Swift.h"
-(Swifter*)InitSwifter{
    Swifter* SW = [[Swifter alloc] init];
    [SW setSwifterWithB: self.bi];
    return SW;
}
#End If

  • so just copy the snippet to your project
  • now you can add you swift code (inside a condition block):
B4X:
#if swift
func GetString() -> NSString{
    return "Your text"
}
#End If

  • Call the functions with the CallSwift method, in this case:
    B4X:
    Dim GetString As String = CallSwift("GetString",Null,Null).AsString
That's it. Now you can use Swift code in your project ;)

Important notes:
  • Because of this problem, you will need to comment the "TAB" property line in the iCore.h file (you will find the file in the Libs folder of your builder server). --> Workaround for the missing TAB property:
    B4X:
    Dim TABU As String = Chr(9)
  • This means also that hosted builder users can't use Swifter for now as they don't have access to this file.
  • After you have edited your Swift code it's not enough to just restart you App, you need to rebuild your App completely (same behaviour like inline Objective C code)
  • Everytime you activate or deactivate Swifter you have to restart B4i
  • You shouldn't work on two B4i projects at the same time with an activated Swifter
  • when working on your Swift project, keep Swifter open
  • use Swift code only in the Main module
  • administrator rights are required for editing the Xcode template

B4X:
Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'Public variables can be accessed from all modules.
    Public App As Application
    Public NavControl As NavigationController
    Private Page1 As Page

    Private Swifter As NativeObject
End Sub

Private Sub Application_Start (Nav As NavigationController)
    'SetDebugAutoFlushLogs(True) 'Uncomment if program crashes before all logs are printed.
    NavControl = Nav
    Page1.Initialize("Page1")
    Page1.Title = "Page 1"
    Page1.RootPanel.Color = Colors.White
    NavControl.ShowPage(Page1)

    Dim GetString As String = CallSwift("GetString",Null,Null).AsString
    Log(GetString)
    CallSwift("SetPageColor",Array("Col","Page"),Array(Swifter.ColorToUIColor(Colors.Magenta),Page1.RootPanel))
    CallSwift("RaiseEvent",Null,Null)
End Sub

Sub RaiseMe (Info As String)
    Log("Info: " & Info)
End Sub

Sub CallSwift(MethodName As String, ParamNames() As List, Params() As Object) As NativeObject
    If Not(Swifter.IsInitialized) Then
        Swifter = Me
        Swifter = Swifter.RunMethod("InitSwifter",Null)
    End If

    If Not(ParamNames = Null) Then
        Dim ArgsStr As String
        For Each Arg As String In ParamNames
            If ArgsStr = "" Then ArgsStr ="With"
            If Arg.Length > 1 Then
                ArgsStr = ArgsStr & Arg.SubString2(0,1).ToUpperCase & Arg.SubString(1) & ":"
            Else
                ArgsStr = ArgsStr & Arg.ToUpperCase & ":"
            End If
        Next
    End If

    Return Swifter.RunMethod(MethodName & ArgsStr,Params)
End Sub

#if objc
#import "B4iProject-Swift.h"
-(Swifter*)InitSwifter{
    Swifter* SW = [[Swifter alloc] init];
    [SW setSwifterWithB: self.bi];
    return SW;
}
#End If

#if swift
func GetString() -> NSString{
    return "Your text"
}

func SetPageColor (Col: UIColor, Page: UIView){
    Page.backgroundColor = Col
}

func RaiseEvent() {
    bi!.raiseEvent(nil, event: "raiseme:", params: ["very important"])
}
#End If

Feel free to ask questions ;)
 
Last edited:

imbault

Well-Known Member
Licensed User
Longtime User
Interesting, can you tell a little bit more about this Swifter tool (what it does? how this binary is built (xCode?)...)

Thanks
 

JanPRO

Well-Known Member
Licensed User
Longtime User
Hi,

Swifter was created with B4J.
what it does?
It's really simple:
B4i uses a template for creating the Xcode project on your pc. You can find this template in the installation directory. When you click on the Activate button in Swifter, the template will be modified (new file references, settings ...). Moreover with the help of jFileWatcher (Thank you for this great library @Roycefer), the B4i project file will be observed. When the file was modified, Swifter filters the Swift code and add it's to a Swift class called "Swifter". You can find this class in the Special folder of your Project.
When you click on the Deactivate button, Swifter sets the Xcode template to the old one and stops observing the B4i project.

That's the whole secret of Swifter ;)

Jan
 
Last edited:

tufanv

Expert
Licensed User
Longtime User
Looks like very good. New opportunties may come with swift support ! Thanks Jan As Always !
 

JanPRO

Well-Known Member
Licensed User
Longtime User
New opportunties
Yes, it's also the fact that we have influence on how the Xcode project is build, what gives as a lot of opportunities, e.g. I am sure it's also possible adding support for TodayWidget this way. I am just experimenting a bit and it looks not bad...

Jan
 
Top