Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 6 additions & 0 deletions .changes/mobile-plugin-get-args.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
---
"tauri": patch:enhance
---

Added `getArgs` and `getRawArgs` methods to the plugin `Invoke` class (Kotlin and Swift),
which lets you parse the arguments manually instead of through the `parseArgs` method.
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,14 @@ class Invoke(
private val argsJson: String,
private val jsonMapper: ObjectMapper
) {
fun getRawArgs(): String {
return argsJson
}

fun getArgs(): JSObject {
return JSObject(argsJson)
}

fun<T> parseArgs(cls: Class<T>): T {
return jsonMapper.readValue(argsJson, cls)
}
Expand Down
11 changes: 11 additions & 0 deletions core/tauri/mobile/ios-api/Sources/Tauri/Invoke.swift
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,17 @@ import UIKit
self.sendChannelData = sendChannelData
}

public func getRawArgs() -> String {
return self.data
}

public func getArgs() throws -> JSObject {
let jsonData = self.data.data(using: .utf8)!
let data = try JSONSerialization.jsonObject(with: jsonData, options: [])
return JSTypes.coerceDictionaryToJSObject(
(data as! NSDictionary), formattingDatesAsStrings: true)!
}

public func parseArgs<T: Decodable>(_ type: T.Type) throws -> T {
let jsonData = self.data.data(using: .utf8)!
let decoder = JSONDecoder()
Expand Down
101 changes: 101 additions & 0 deletions core/tauri/mobile/ios-api/Sources/Tauri/JSTypes.swift
Original file line number Diff line number Diff line change
Expand Up @@ -20,3 +20,104 @@ extension Dictionary: JSValue where Key == String, Value == JSValue {}
// convenience aliases
public typealias JSObject = [String: JSValue]
public typealias JSArray = [JSValue]

extension Dictionary where Key == String, Value == JSValue {
public func getValue(_ key: String) -> JSValue? {
return self[key]
}

public func getString(_ key: String) -> String? {
return self[key] as? String
}

public func getBool(_ key: String) -> Bool? {
return self[key] as? Bool
}

public func getInt(_ key: String) -> Int? {
return self[key] as? Int
}

public func getFloat(_ key: String) -> Float? {
if let floatValue = self[key] as? Float {
return floatValue
} else if let doubleValue = self[key] as? Double {
return Float(doubleValue)
}
return nil
}

public func getDouble(_ key: String) -> Double? {
return self[key] as? Double
}

public func getArray(_ key: String) -> JSArray? {
return self[key] as? JSArray
}

public func getObject(_ key: String) -> JSObject? {
return self[key] as? JSObject
}
}

/*
Simply casting objects from foundation class clusters (such as __NSArrayM)
doesn't work with the JSValue protocol and will always fail. So we need to
recursively and explicitly convert each value in the dictionary.
*/
public enum JSTypes {}
extension JSTypes {
public static func coerceDictionaryToJSObject(
_ dictionary: NSDictionary?, formattingDatesAsStrings: Bool = false
) -> JSObject? {
return coerceToJSValue(dictionary, formattingDates: formattingDatesAsStrings) as? JSObject
}

public static func coerceDictionaryToJSObject(
_ dictionary: [AnyHashable: Any]?, formattingDatesAsStrings: Bool = false
) -> JSObject? {
return coerceToJSValue(dictionary, formattingDates: formattingDatesAsStrings) as? JSObject
}
}

private let dateStringFormatter = ISO8601DateFormatter()

// We need a large switch statement because we have a lot of types.
// swiftlint:disable:next cyclomatic_complexity
private func coerceToJSValue(_ value: Any?, formattingDates: Bool) -> JSValue? {
guard let value = value else {
return nil
}
switch value {
case let stringValue as String:
return stringValue
case let numberValue as NSNumber:
return numberValue
case let boolValue as Bool:
return boolValue
case let intValue as Int:
return intValue
case let floatValue as Float:
return floatValue
case let doubleValue as Double:
return doubleValue
case let dateValue as Date:
if formattingDates {
return dateStringFormatter.string(from: dateValue)
}
return dateValue
case let nullValue as NSNull:
return nullValue
case let arrayValue as NSArray:
return arrayValue.compactMap { coerceToJSValue($0, formattingDates: formattingDates) }
case let dictionaryValue as NSDictionary:
let keys = dictionaryValue.allKeys.compactMap { $0 as? String }
var result: JSObject = [:]
for key in keys {
result[key] = coerceToJSValue(dictionaryValue[key], formattingDates: formattingDates)
}
return result
default:
return nil
}
}