Skip to content

Commit 83c9859

Browse files
authored
allows static method calls on JNIObject (#14)
* allow calling static methods on JNIObjects * reindent * deprecate init with explicit className * implement private classInstances cache * use static getter for classinstances
1 parent 41ee464 commit 83c9859

File tree

1 file changed

+53
-14
lines changed

1 file changed

+53
-14
lines changed

Sources/JNI/JNIObjects.swift

Lines changed: 53 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,23 +1,42 @@
11
import CJNI
2+
import Dispatch
23

34
/// Designed to simplify calling a constructor and methods on a JavaClass
45
/// Subclass this and add the methods appropriate to the object you are constructing.
56
open class JNIObject {
6-
public let javaClass: JavaClass
7+
open class var className: String {
8+
return "java.lang.object"
9+
}
10+
11+
private static var classInstances = [String: JavaClass]()
12+
13+
public static var javaClass: JavaClass {
14+
return DispatchQueue.main.sync {
15+
if let classInstance = classInstances[className] {
16+
return classInstance
17+
}
18+
19+
let javaClassLocalRef = try! jni.FindClass(name: className.replacingFullstopsWithSlashes())
20+
try! checkAndThrowOnJNIError()
21+
let classInstance = jni.NewGlobalRef(javaClassLocalRef)!
22+
classInstances[className] = classInstance
23+
24+
return classInstance
25+
}
26+
}
27+
728
public let instance: JavaObject
829

930
required public init(_ instance: JavaObject) throws {
1031
guard let globalInstanceRef = jni.NewGlobalRef(instance) else {
1132
throw Error.couldntCreateGlobalRef
1233
}
1334

14-
let javaClassLocalRef = try jni.GetObjectClass(obj: instance)
15-
let javaClass = jni.NewGlobalRef(javaClassLocalRef)
1635
try checkAndThrowOnJNIError()
17-
self.javaClass = javaClass!
1836
self.instance = globalInstanceRef
1937
}
2038

39+
@available(*, deprecated, message: "Override Self.className instead and use the initializers that don't take className as an argument")
2140
convenience public init(_ className: String, arguments: [JavaParameterConvertible] = []) throws {
2241
let className = className.replacingFullstopsWithSlashes()
2342
let javaClassLocalRef = try jni.FindClass(name: className)
@@ -29,22 +48,39 @@ open class JNIObject {
2948
try self.init(instanceLocalRef)
3049
}
3150

51+
convenience public init(arguments: JavaParameterConvertible...) throws {
52+
guard let instanceLocalRef = try jni.callConstructor(on: type(of: self).javaClass, arguments: arguments) else {
53+
throw Error.couldntCallConstructor
54+
}
55+
56+
try self.init(instanceLocalRef)
57+
}
58+
3259
deinit {
3360
jni.DeleteGlobalRef(instance)
34-
jni.DeleteGlobalRef(javaClass)
3561
}
3662

3763
public func call(methodName: String, arguments: [JavaParameterConvertible] = []) throws {
3864
try jni.call(methodName, on: self.instance, arguments: arguments)
3965
}
4066

41-
public func call<T: JavaInitializableFromMethod & JavaParameterConvertible>(methodName: String, arguments: [JavaParameterConvertible] = []) throws -> T {
67+
public func call<T: JavaInitializableFromMethod & JavaParameterConvertible>(
68+
methodName: String,
69+
arguments: [JavaParameterConvertible] = []
70+
) throws -> T {
4271
return try jni.call(methodName, on: self.instance, arguments: arguments)
4372
}
4473

45-
public func callStatic(methodName: String, arguments: [JavaParameterConvertible] = []) throws {
74+
public static func callStatic(methodName: String, arguments: [JavaParameterConvertible] = []) throws {
4675
try jni.callStatic(methodName, on: self.javaClass, arguments: arguments)
4776
}
77+
78+
public static func callStatic<T: JavaInitializableFromMethod & JavaParameterConvertible>(
79+
methodName: String,
80+
arguments: [JavaParameterConvertible] = []
81+
) throws -> T {
82+
return try jni.callStatic(methodName, on: self.javaClass, arguments: arguments)
83+
}
4884
}
4985

5086
extension JNIObject {
@@ -55,7 +91,10 @@ extension JNIObject {
5591
}
5692

5793
extension JNI {
58-
func callConstructor(on targetClass: JavaClass, arguments: [JavaParameterConvertible] = []) throws -> JavaObject? {
94+
func callConstructor(
95+
on targetClass: JavaClass,
96+
arguments: [JavaParameterConvertible] = []
97+
) throws -> JavaObject? {
5998
let methodID = _env.pointee.pointee.GetMethodID(_env, targetClass, "<init>", arguments.methodSignature(returnType: nil))
6099
try checkAndThrowOnJNIError()
61100

@@ -64,19 +103,19 @@ extension JNI {
64103
}
65104

66105
public extension JNI {
67-
public func NewObject(targetClass: JavaClass, _ methodID: JavaMethodID, _ args: [JavaParameter]) throws -> JavaObject? {
68-
let env = self._env
106+
func NewObject(targetClass: JavaClass, _ methodID: JavaMethodID, _ args: [JavaParameter]) throws -> JavaObject? {
107+
let env = self._env
69108
var mutableArgs = args
70109
let newObject = env.pointee.pointee.NewObject(env, targetClass, methodID, &mutableArgs)
71110
try checkAndThrowOnJNIError()
72111

73112
return newObject
74-
}
113+
}
75114

76-
public func GetObjectClass(obj: JavaObject) throws -> JavaClass {
77-
let env = self._env
115+
func GetObjectClass(obj: JavaObject) throws -> JavaClass {
116+
let env = self._env
78117
let result = env.pointee.pointee.GetObjectClass(env, obj)
79118
try checkAndThrowOnJNIError()
80119
return result!
81-
}
120+
}
82121
}

0 commit comments

Comments
 (0)