最近のアクセス:
iOS で GeneXus のイベントをトリガーする外部オブジェクトを作成する方法

はじめに

ここでは、オフラインコードおよびオンラインコードからの呼び出しが可能で、GeneXus イベントをトリガーできる外部オブジェクトの作成方法を説明します。

はじめに

iOS 用の外部オブジェクトの作成方法に関する基本事項をまとめたドキュメントをまだ読んでいない場合は、先にそのドキュメントに目を通してください。
オフライン実装とともに、ユーザーイベントによる呼び出しが可能な実装を提供する必要があるため、そちらから開始します。その後、このサンプルで使用されている拡張ライブラリの作成方法を確認してください。

Swift でタイマーを実装します。このタイマーは秒数とメッセージを受け取るメソッドを持つ外部オブジェクトで、指定された時間が経過すると、GeneXus イベントを呼び出し、このイベントにメッセージを渡します。
次のものが必要です:
  • GeneXus での定義 (外部オブジェクト)
  • 生成されたコードから呼び出すオフライン実装
  • オフラインコードから呼び出すハンドラー

外部オブジェクトの定義

この外部オブジェクトは次のように定義されています:
イメージ:26937.png
Start メソッドと Completed イベントを必ず "static" としてマークしてください。

オフライン

実装を開始する前に、外部オブジェクトの定義に関する情報を提供する必要があります。
イメージ:38518.gif
また、Start メソッドを次のようにします:
イメージ:38519.gif

実装

これで準備が整いました。それでは実装に取りかかりましょう。
まず、TimerEO クラスを作成します:

TimerEO.swift

import Foundation
import GXStandardClasses

class TimerEO: GXExternalObjectBase {

    private static let gxServerSideEvent = "Completed"

    private var message: String = ""
    
    init(message: String) {
        self.message = message
        super.init()
    }

    static func startTimerWithSeconds( _ seconds: Int, _ message: String) {
        TimerEO(message: message).startTimer(seconds: seconds)
    }
        
    func startTimer(seconds: Int) {
        gx_dispatch_sync_on_main_queue({() -> Void in
            Timer.scheduledTimer(timeInterval: TimeInterval(seconds), target: self, selector: #selector(self.timerDidFinish), userInfo: nil, repeats: false)
        })
    }

    open override var externalObjectName: String {
        return "TimerEO"
    }
    
    // マーク - GeneXus イベント

    @objc func timerDidFinish(timer: Timer) {
        self.dispatchExteralObjectEvent(TimerEO.gxServerSideEvent, withParameters:  [ self.message ] )
    }
}

備考:

  1. 簡略化のため、このコードにはエラーハンドリングが含まれていません。startTimer メソッドでは、パラメータータイプのチェックは行われません。また、タイマーが正しくスケジューリングされているかを確かめる方法はありません。実際にこの外部オブジェクトを実装する場合は、エラーチェックを追加する必要があります。
  2. startTimer(seconds:) メソッドは、main スレッドにタイマーを作成します。これは、設定時間が来る前に、完了するバックグラウンドスレッドで呼び出される可能性があるからです。その場合、イベントはトリガーされません。
    独自の外部オブジェクトを実装するときには、main スレッドに多少の追加が必要になるかもしれませんが、本当に必要な場合を除いて、何もしない方がいいでしょう。
  3. 外部オブジェクトが何らかの GeneXus イベントをトリガーする場合、externalObjectName は必須です。また、GeneXus で定義されている外部オブジェクト名を返す必要があります。
  4. Completed GeneXus イベントのトリガーには、ベースクラスで定義されている dispatchExteralObjectEvent メソッドを使用します。
これで完了です。オフラインアプリケーションで TimerEO から Start メソッドを使用すると、生成されたコードによって静的関数 startTimerWithSeconds が直接呼び出されます。

オンラインセクション

「オンライン」とは、呼び出し側のオブジェクトがオンラインかオフラインかに関係なく、ユーザーイベントから呼び出すことができる外部オブジェクトです。
iOS デバイス用の外部オブジェクト」で説明されているとおり、"mapper" クラス (TimerEOLibrary.swift) とハンドラー (TimerEOActionHandler.swift) の実装を提供する必要があります。

実装

コードは次のようになります:

TimerEOLibrary.swift

import GXCoreBL

@objc(TimerEOLibrary)
public class TimerEOLibrary: NSObject, GXExtensionLibraryProtocol {

    public func initializeExtensionLibrary(withContext context: GXExtensionLibraryContext) {

        GXActionExternalObjectHandler.register(TimerEOActionHandler.self, forExternalObjectName:TimerEOActionHandler.classIdentifier)

    }
}

TimerEOActionHandler.swift

import Foundation
import GXCoreBL

@objc(TimerEOActionHandler)
public class TimerEOActionHandler: GXActionExternalObjectHandler {

    public static let classIdentifier = "TimerEO"

    override public class func handleActionExecutionUsingMethodHandlerSelectorNamePrefix() -> Bool {
        return true
    }
    
    // マーク - 外部オブジェクトのメソッド
    
    @objc public func gxActionExObjMethodHandler_Start() {
        let (secs, msg) = self.readParameters()
        if (secs == nil) {
            let error = NSError.wrongNumberOfParametersDeveloperError(forMethod: self.actionExObjDesc.actionExternalObjectMethod)
            self.onFinishedExecutingWithError(error)
            return
        }
        self.handleStartTimerAction(seconds: secs!, message: msg!)
        self.onFinishedExecutingWithSuccess()
    }

    //マーク: - プライベート
    
    private func readParameters() -> (Int?, String?){
        guard let actionParameterArray = self.actionExObjDesc.actionParametersDescriptor??.actionParametersDescriptors,
            actionParameterArray.count == 2 else {
            return (nil, nil)
        }
        let seconds = self.readStringParameter(actionParameterArray [ 0 ] , from: self.contextEntityData())
        let msg = self.readStringParameter(actionParameterArray [ 1 ] , from: self.contextEntityData())
        return (GXUtilities.integerNumber(fromValue: seconds) as? Int, GXUtilities.nonEmptyString(from: msg))
    }
        
    private func handleStartTimerAction(seconds: Int, message: String) {
        // タイマーを開始し、ユーザーイベントをトリガー
        TimerEO.startTimerWithSeconds(seconds, message)
        self.onFinishedExecutingWithSuccess()
    }
}
オンラインコードでは、gxActionExObjMethodHandler_Start 関数が使用されています。この関数は、パラメーターを取得して、前述の TimerEO 実装を使用する handleStartTimerAction 関数を呼び出します。

GeneXus テストオブジェクト

実装をテストするために、次のオブジェクトを作成しました。

MainTimer (Dashboard)

プロパティ

Main program: True
Connectivity Support: Offline

イベント

Event TimerEO.Completed(&message)
    msg(&message)
EndEvent

Event 'StartTimer'
    TimerEO.Start(5, "ユーザーコードからの TimerEO")    
Endevent

Event 'StartTimerProc'
    StartTimerProc()
EndEvent

StartTimerProc (Procedure)

ソース

TimerEO.Start(5, "オフラインコードからの TimerEO")

ソースコード

こちらにあるサンプルからソースコードをダウンロードできます。
注: ソースコードをダウンロードするには、SVN クライアントが必要です。または、前述のリンクからオンラインで閲覧することもできます。

インストール

GeneXus 15 Upgrade 9 以上で、TimerEO フォルダを "GeneXusInstallDir\Libraries\" にコピーする必要があります。





サブページ
Created: 17/05/30 17:30 by Admin Last update: 21/05/21 03:34 by Admin
カテゴリ
Powered by GXwiki 3.0