diff --git a/Source/AppleFetcher/Implement/AppleAdsAttributionTokenFetcher.swift b/Source/AppleFetcher/Implement/AppleAdsAttributionTokenFetcher.swift index 3084051..8c956d1 100644 --- a/Source/AppleFetcher/Implement/AppleAdsAttributionTokenFetcher.swift +++ b/Source/AppleFetcher/Implement/AppleAdsAttributionTokenFetcher.swift @@ -56,24 +56,24 @@ private final class ClassAAAttribution { let error = UnsafeMutablePointer.allocate(capacity: 1) defer { error.deallocate() } - let result = classAAAttribution.call( - methodAttributionTokenWithError, - with: OpaquePointer(error), - return: .reference - ) + let result = { + let function = unsafeBitCast( + methodAttributionTokenWithError.implementation, + to: (@convention(c)(AnyClass, Selector, OpaquePointer)->String).self + ) + return function( + methodAttributionTokenWithError.anyClass, + methodAttributionTokenWithError.selector, + OpaquePointer(error) + ) + }() + if let error = error.pointee { throw error } - guard let result = result as? String else { - throw AppleAdsAttributionTokenFetcherError.attributionTokenIsNotString - } return result } } -public enum AppleAdsAttributionTokenFetcherError: Error { - case attributionTokenIsNotString -} - #endif diff --git a/Source/AppleObjectiveCReflection/NSObjectClassMethod.swift b/Source/AppleObjectiveCReflection/NSObjectClassMethod.swift index 8762dd8..1f79e55 100644 --- a/Source/AppleObjectiveCReflection/NSObjectClassMethod.swift +++ b/Source/AppleObjectiveCReflection/NSObjectClassMethod.swift @@ -15,229 +15,36 @@ extension NSObjectClass { } } +/// Class method of NSObject +/// 1. Class: use Any or ActualType (Example: NSString\*) +/// 2. Value: use ActualType (Using Any can lead crash) (Example: int) +/// 3. Pointer: use OpaquePointer (Using Any can lead crash) (Example: NSError\*\*) +/// ```swift +/// let result = { +/// let function = unsafeBitCast( +/// classMethod.implementation, +/// to: (@convention(c)(AnyClass, Selector, ...)->...).self +/// ) +/// return function( +/// classMethod.anyClass, +/// classMethod.selector, +/// ... +/// ) +/// }() +/// ``` public final class NSObjectClassMethod { - let anyClass: AnyClass - let selector: Selector - let method: Method + public let anyClass: AnyClass + public let selector: Selector + public let implementation: IMP fileprivate init?(anyClass: AnyClass, name: String) { let selector = NSSelectorFromString(name) guard let method = class_getClassMethod(anyClass, selector) else { return nil } + let implementation = method_getImplementation(method) self.anyClass = anyClass self.selector = selector - self.method = method - } -} - -extension NSObjectClass { - /// Call class method with reflection - @discardableResult - public func call( - _ classMethod: NSObjectClassMethod, - return: NSObjectReturn = .void - ) -> Return? { - guard anyClass == classMethod.anyClass else { return nil } - - let implementation = method_getImplementation(classMethod.method) - - switch `return` { - case .reference: - typealias Function = @convention(c)(AnyClass, Selector)->Any? - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(anyClass, classMethod.selector) - return result as? Return - case .value(let type): - typealias Function = @convention(c)(AnyClass, Selector)->Unmanaged - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(anyClass, classMethod.selector) - return cast(result, to: type) - case .void: - typealias Function = @convention(c)(AnyClass, Selector)->Void - let function = unsafeBitCast(implementation, to: Function.self) - function(anyClass, classMethod.selector) - return () as? Return - } - } - - /// Call class method with reflection - @discardableResult - public func call( - _ classMethod: NSObjectClassMethod, - with argument0: Any?, - return: NSObjectReturn = .void - ) -> Return? { - guard anyClass == classMethod.anyClass else { return nil } - - let implementation = method_getImplementation(classMethod.method) - - switch `return` { - case .reference: - typealias Function = @convention(c)(AnyClass, Selector, Any?)->Any? - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(anyClass, classMethod.selector, argument0) - return result as? Return - case .value(let type): - typealias Function = @convention(c)(AnyClass, Selector, Any?)->Unmanaged - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(anyClass, classMethod.selector, argument0) - return cast(result, to: type) - case .void: - typealias Function = @convention(c)(AnyClass, Selector, Any?)->Void - let function = unsafeBitCast(implementation, to: Function.self) - function(anyClass, classMethod.selector, argument0) - return () as? Return - } - } - - /// Call class method with reflection - @discardableResult - public func call( - _ classMethod: NSObjectClassMethod, - with argument0: Any?, - with argument1: Any?, - return: NSObjectReturn = .void - ) -> Return? { - guard anyClass == classMethod.anyClass else { return nil } - - let implementation = method_getImplementation(classMethod.method) - - switch `return` { - case .reference: - typealias Function = @convention(c)(AnyClass, Selector, Any?, Any?)->Any? - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(anyClass, classMethod.selector, argument0, argument1) - return result as? Return - case .value(let type): - typealias Function = @convention(c)(AnyClass, Selector, Any?, Any?)->Unmanaged - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(anyClass, classMethod.selector, argument0, argument1) - return cast(result, to: type) - case .void: - typealias Function = @convention(c)(AnyClass, Selector, Any?, Any?)->Void - let function = unsafeBitCast(implementation, to: Function.self) - function(anyClass, classMethod.selector, argument0, argument1) - return () as? Return - } - } - - /// Call class method with reflection - @discardableResult - public func call( - _ classMethod: NSObjectClassMethod, - with argument0: Any?, - with argument1: Any?, - with argument2: Any?, - return: NSObjectReturn = .void - ) -> Return? { - guard anyClass == classMethod.anyClass else { return nil } - - let implementation = method_getImplementation(classMethod.method) - - switch `return` { - case .reference: - typealias Function = @convention(c)(AnyClass, Selector, Any?, Any?, Any?)->Any? - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(anyClass, classMethod.selector, argument0, argument1, argument2) - return result as? Return - case .value(let type): - typealias Function = @convention(c)(AnyClass, Selector, Any?, Any?, Any?)->Unmanaged - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(anyClass, classMethod.selector, argument0, argument1, argument2) - return cast(result, to: type) - case .void: - typealias Function = @convention(c)(AnyClass, Selector, Any?, Any?, Any?)->Void - let function = unsafeBitCast(implementation, to: Function.self) - function(anyClass, classMethod.selector, argument0, argument1, argument2) - return () as? Return - } - } - - /// Call class method with reflection - @discardableResult - public func call( - _ classMethod: NSObjectClassMethod, - with argument0: Any?, - with argument1: Any?, - with argument2: Any?, - with argument3: Any?, - return: NSObjectReturn = .void - ) -> Return? { - guard anyClass == classMethod.anyClass else { return nil } - - let implementation = method_getImplementation(classMethod.method) - - switch `return` { - case .reference: - typealias Function = @convention(c)(AnyClass, Selector, Any?, Any?, Any?, Any?)->Any? - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(anyClass, classMethod.selector, argument0, argument1, argument2, argument3) - return result as? Return - case .value(let type): - typealias Function = @convention(c)(AnyClass, Selector, Any?, Any?, Any?, Any?)->Unmanaged - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(anyClass, classMethod.selector, argument0, argument1, argument2, argument3) - return cast(result, to: type) - case .void: - typealias Function = @convention(c)(AnyClass, Selector, Any?, Any?, Any?, Any?)->Void - let function = unsafeBitCast(implementation, to: Function.self) - function(anyClass, classMethod.selector, argument0, argument1, argument2, argument3) - return () as? Return - } - } - - /// Call class method with reflection - @discardableResult - public func call( - _ classMethod: NSObjectClassMethod, - with argument0: Any?, - with argument1: Any?, - with argument2: Any?, - with argument3: Any?, - with argument4: Any?, - return: NSObjectReturn = .void - ) -> Return? { - guard anyClass == classMethod.anyClass else { return nil } - - let implementation = method_getImplementation(classMethod.method) - - switch `return` { - case .reference: - typealias Function = @convention(c)(AnyClass, Selector, Any?, Any?, Any?, Any?, Any?)->Any? - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(anyClass, classMethod.selector, argument0, argument1, argument2, argument3, argument4) - return result as? Return - case .value(let type): - typealias Function = @convention(c)(AnyClass, Selector, Any?, Any?, Any?, Any?, Any?)->Unmanaged - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(anyClass, classMethod.selector, argument0, argument1, argument2, argument3, argument4) - return cast(result, to: type) - case .void: - typealias Function = @convention(c)(AnyClass, Selector, Any?, Any?, Any?, Any?, Any?)->Void - let function = unsafeBitCast(implementation, to: Function.self) - function(anyClass, classMethod.selector, argument0, argument1, argument2, argument3, argument4) - return () as? Return - } - } -} - -extension NSObjectClass { - private func cast( - _ value: Unmanaged, - to type: Actual.Type - ) -> Actual { - let raw = unsafeBitCast(value, to: Int.self) - - switch MemoryLayout.size { - case 1: - return unsafeBitCast(Int8(raw), to: type) - case 2: - return unsafeBitCast(Int16(raw), to: type) - case 4: - return unsafeBitCast(Int32(raw), to: type) - default: - return unsafeBitCast(Int64(raw), to: type) - } + self.implementation = implementation } } diff --git a/Source/AppleObjectiveCReflection/NSObjectInstanceMethod.swift b/Source/AppleObjectiveCReflection/NSObjectInstanceMethod.swift index 3b57c97..d26c75d 100644 --- a/Source/AppleObjectiveCReflection/NSObjectInstanceMethod.swift +++ b/Source/AppleObjectiveCReflection/NSObjectInstanceMethod.swift @@ -15,229 +15,36 @@ extension NSObjectInstance { } } +/// Instance method of NSObject +/// 1. Class: use Any or ActualType (Example: NSString\*) +/// 2. Value: use ActualType (Using Any can lead crash) (Example: int) +/// 3. Pointer: use OpaquePointer (Using Any can lead crash) (Example: NSError\*\*) +/// ```swift +/// let result = { +/// let function = unsafeBitCast( +/// method.implementation, +/// to: (@convention(c)(NSObject, Selector, ...)->...).self +/// ) +/// return function( +/// method.object, +/// method.selector, +/// ... +/// ) +/// }() +/// ``` public final class NSObjectInstanceMethod { - let object: NSObject - let selector: Selector - let method: Method + public let object: NSObject + public let selector: Selector + public let implementation: Method fileprivate init?(object: NSObject, name: String) { let selector = NSSelectorFromString(name) guard let method = class_getInstanceMethod(type(of: object), selector) else { return nil } + let implementation = method_getImplementation(method) self.object = object self.selector = selector - self.method = method - } -} - -extension NSObjectInstance { - /// Call class method with reflection - @discardableResult - public func call( - _ instanceMethod: NSObjectInstanceMethod, - return: NSObjectReturn = .void - ) -> Return? { - guard object == instanceMethod.object else { return nil } - - let implementation = method_getImplementation(instanceMethod.method) - - switch `return` { - case .reference: - typealias Function = @convention(c)(NSObject, Selector)->Any? - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(object, instanceMethod.selector) - return result as? Return - case .value(let type): - typealias Function = @convention(c)(NSObject, Selector)->Unmanaged - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(object, instanceMethod.selector) - return cast(result, to: type) - case .void: - typealias Function = @convention(c)(NSObject, Selector)->Void - let function = unsafeBitCast(implementation, to: Function.self) - function(object, instanceMethod.selector) - return () as? Return - } - } - - /// Call class method with reflection - @discardableResult - public func call( - _ instanceMethod: NSObjectInstanceMethod, - with argument0: Any?, - return: NSObjectReturn = .void - ) -> Return? { - guard object == instanceMethod.object else { return nil } - - let implementation = method_getImplementation(instanceMethod.method) - - switch `return` { - case .reference: - typealias Function = @convention(c)(NSObject, Selector, Any?)->Any? - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(object, instanceMethod.selector, argument0) - return result as? Return - case .value(let type): - typealias Function = @convention(c)(NSObject, Selector, Any?)->Unmanaged - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(object, instanceMethod.selector, argument0) - return cast(result, to: type) - case .void: - typealias Function = @convention(c)(NSObject, Selector, Any?)->Void - let function = unsafeBitCast(implementation, to: Function.self) - function(object, instanceMethod.selector, argument0) - return () as? Return - } - } - - /// Call class method with reflection - @discardableResult - public func call( - _ instanceMethod: NSObjectInstanceMethod, - with argument0: Any?, - with argument1: Any?, - return: NSObjectReturn = .void - ) -> Return? { - guard object == instanceMethod.object else { return nil } - - let implementation = method_getImplementation(instanceMethod.method) - - switch `return` { - case .reference: - typealias Function = @convention(c)(NSObject, Selector, Any?, Any?)->Any? - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(object, instanceMethod.selector, argument0, argument1) - return result as? Return - case .value(let type): - typealias Function = @convention(c)(NSObject, Selector, Any?, Any?)->Unmanaged - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(object, instanceMethod.selector, argument0, argument1) - return cast(result, to: type) - case .void: - typealias Function = @convention(c)(NSObject, Selector, Any?, Any?)->Void - let function = unsafeBitCast(implementation, to: Function.self) - function(object, instanceMethod.selector, argument0, argument1) - return () as? Return - } - } - - /// Call class method with reflection - @discardableResult - public func call( - _ instanceMethod: NSObjectInstanceMethod, - with argument0: Any?, - with argument1: Any?, - with argument2: Any?, - return: NSObjectReturn = .void - ) -> Return? { - guard object == instanceMethod.object else { return nil } - - let implementation = method_getImplementation(instanceMethod.method) - - switch `return` { - case .reference: - typealias Function = @convention(c)(NSObject, Selector, Any?, Any?, Any?)->Any? - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(object, instanceMethod.selector, argument0, argument1, argument2) - return result as? Return - case .value(let type): - typealias Function = @convention(c)(NSObject, Selector, Any?, Any?, Any?)->Unmanaged - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(object, instanceMethod.selector, argument0, argument1, argument2) - return cast(result, to: type) - case .void: - typealias Function = @convention(c)(NSObject, Selector, Any?, Any?, Any?)->Void - let function = unsafeBitCast(implementation, to: Function.self) - function(object, instanceMethod.selector, argument0, argument1, argument2) - return () as? Return - } - } - - /// Call class method with reflection - @discardableResult - public func call( - _ instanceMethod: NSObjectInstanceMethod, - with argument0: Any?, - with argument1: Any?, - with argument2: Any?, - with argument3: Any?, - return: NSObjectReturn = .void - ) -> Return? { - guard object == instanceMethod.object else { return nil } - - let implementation = method_getImplementation(instanceMethod.method) - - switch `return` { - case .reference: - typealias Function = @convention(c)(NSObject, Selector, Any?, Any?, Any?, Any?)->Any? - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(object, instanceMethod.selector, argument0, argument1, argument2, argument3) - return result as? Return - case .value(let type): - typealias Function = @convention(c)(NSObject, Selector, Any?, Any?, Any?, Any?)->Unmanaged - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(object, instanceMethod.selector, argument0, argument1, argument2, argument3) - return cast(result, to: type) - case .void: - typealias Function = @convention(c)(NSObject, Selector, Any?, Any?, Any?, Any?)->Void - let function = unsafeBitCast(implementation, to: Function.self) - function(object, instanceMethod.selector, argument0, argument1, argument2, argument3) - return () as? Return - } - } - - /// Call class method with reflection - @discardableResult - public func call( - _ instanceMethod: NSObjectInstanceMethod, - with argument0: Any?, - with argument1: Any?, - with argument2: Any?, - with argument3: Any?, - with argument4: Any?, - return: NSObjectReturn = .void - ) -> Return? { - guard object == instanceMethod.object else { return nil } - - let implementation = method_getImplementation(instanceMethod.method) - - switch `return` { - case .reference: - typealias Function = @convention(c)(NSObject, Selector, Any?, Any?, Any?, Any?, Any?)->Any? - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(object, instanceMethod.selector, argument0, argument1, argument2, argument3, argument4) - return result as? Return - case .value(let type): - typealias Function = @convention(c)(NSObject, Selector, Any?, Any?, Any?, Any?, Any?)->Unmanaged - let function = unsafeBitCast(implementation, to: Function.self) - let result = function(object, instanceMethod.selector, argument0, argument1, argument2, argument3, argument4) - return cast(result, to: type) - case .void: - typealias Function = @convention(c)(NSObject, Selector, Any?, Any?, Any?, Any?, Any?)->Void - let function = unsafeBitCast(implementation, to: Function.self) - function(object, instanceMethod.selector, argument0, argument1, argument2, argument3, argument4) - return () as? Return - } - } -} - -extension NSObjectInstance { - private func cast( - _ value: Unmanaged, - to type: Actual.Type - ) -> Actual { - let raw = unsafeBitCast(value, to: Int.self) - - switch MemoryLayout.size { - case 1: - return unsafeBitCast(Int8(raw), to: type) - case 2: - return unsafeBitCast(Int16(raw), to: type) - case 4: - return unsafeBitCast(Int32(raw), to: type) - default: - return unsafeBitCast(Int64(raw), to: type) - } + self.implementation = implementation } } diff --git a/Source/AppleTracker/Implement/IdentifierForAdvertiserTracker.swift b/Source/AppleTracker/Implement/IdentifierForAdvertiserTracker.swift index c6e8884..85c7bb1 100644 --- a/Source/AppleTracker/Implement/IdentifierForAdvertiserTracker.swift +++ b/Source/AppleTracker/Implement/IdentifierForAdvertiserTracker.swift @@ -53,7 +53,16 @@ private final class TrackerReflection { classTracker.method(name: "sharedManager") ), let instanceTracker = ( - classTracker.instance(object: classTracker.call(methodShared, return: .reference)) + classTracker.instance(object: { + let function = unsafeBitCast( + methodShared.implementation, + to: (@convention(c)(AnyClass, Selector)->Any?).self + ) + return function( + methodShared.anyClass, + methodShared.selector + ) + }()) ), let methodTrackIdentifier = ( instanceTracker.method(name: "advertisingIdentifier") @@ -74,8 +83,26 @@ private final class TrackerReflection { func track() throws -> IdentifierForAdvertiser { guard - let limitAdTracking = instanceTracker.call(methodTrackLimitAdTracking, return: .value(Bool.self)), - let identifier = instanceTracker.call(methodTrackIdentifier, return: .reference(UUID.self)) + let limitAdTracking = { + let function = unsafeBitCast( + methodTrackLimitAdTracking.implementation, + to: (@convention(c)(NSObject, Selector)->Bool).self + ) + return function( + methodTrackLimitAdTracking.object, + methodTrackLimitAdTracking.selector + ) + }(), + let identifier = { + let function = unsafeBitCast( + methodTrackIdentifier.implementation, + to: (@convention(c)(NSObject, Selector)->UUID).self + ) + return function( + methodTrackIdentifier.object, + methodTrackIdentifier.selector + ) + }() else { throw IdentifierForAdvertiserTrackerError.unmatchedType } diff --git a/Source/AppleTracker/Implement/TrackingAuthorizationTracker.swift b/Source/AppleTracker/Implement/TrackingAuthorizationTracker.swift index cd90c18..ad86c1b 100644 --- a/Source/AppleTracker/Implement/TrackingAuthorizationTracker.swift +++ b/Source/AppleTracker/Implement/TrackingAuthorizationTracker.swift @@ -61,7 +61,16 @@ private final class TrackerReflection { func track() throws -> TrackingAuthorization { guard - let code = classTracker.call(methodTrackCode, return: .value(UInt.self)), + let code = { + let function = unsafeBitCast( + methodTrackCode.implementation, + to: (@convention(c)(AnyClass, Selector)->UInt).self + ) + return function( + methodTrackCode.anyClass, + methodTrackCode.selector + ) + }(), let trackingAuthorization = TrackingAuthorization(rawValue: code) else { throw TrackingAuthorizationTrackerError.unmatchedType diff --git a/Test/AppleObjectiveCReflection/NSObjectClassMethodTest.swift b/Test/AppleObjectiveCReflection/NSObjectClassMethodTest.swift index 7edfba7..c0ad7dc 100644 --- a/Test/AppleObjectiveCReflection/NSObjectClassMethodTest.swift +++ b/Test/AppleObjectiveCReflection/NSObjectClassMethodTest.swift @@ -21,12 +21,18 @@ final class NSObjectClassMethodTest: XCTestCase { let classNSDictionary = NSObjectClass(name: "NSDictionary")! let methodDictionaryWithValuesForKeys = classNSDictionary.method(name: "dictionaryWithObjects:forKeys:")! - let dictionary = classNSDictionary.call( - methodDictionaryWithValuesForKeys, - with: ["1", "2", "3"], - with: ["a", "b", "c"], - return: .reference(NSDictionary.self) - )! + let dictionary = { + let function = unsafeBitCast( + methodDictionaryWithValuesForKeys.implementation, + to: (@convention(c)(AnyClass, Selector, [String], [String])->[String: String]).self + ) + return function( + methodDictionaryWithValuesForKeys.anyClass, + methodDictionaryWithValuesForKeys.selector, + ["1", "2", "3"], + ["a", "b", "c"] + ) + }() XCTAssertEqual(dictionary, ["a":"1","b":"2","c":"3"]) } @@ -35,10 +41,16 @@ final class NSObjectClassMethodTest: XCTestCase { let classNSDictionary = NSObjectClass(name: "NSDictionary")! let methodIsProxy = classNSDictionary.method(name: "isProxy")! - let isProxy = classNSDictionary.call( - methodIsProxy, - return: .value(Bool.self) - )! + let isProxy = { + let function = unsafeBitCast( + methodIsProxy.implementation, + to: (@convention(c)(AnyClass, Selector)->Bool).self + ) + return function( + methodIsProxy.anyClass, + methodIsProxy.selector + ) + }() XCTAssertEqual(isProxy, false) } diff --git a/Test/AppleObjectiveCReflection/NSObjectInstanceMethodTest.swift b/Test/AppleObjectiveCReflection/NSObjectInstanceMethodTest.swift index dbeaffe..da13aa5 100644 --- a/Test/AppleObjectiveCReflection/NSObjectInstanceMethodTest.swift +++ b/Test/AppleObjectiveCReflection/NSObjectInstanceMethodTest.swift @@ -13,7 +13,18 @@ final class NSObjectInstanceMethodTest: XCTestCase { let classNSDictionary = NSObjectClass(name: "NSDictionary")! let methodDictionaryWithValuesForKeys = classNSDictionary.method(name: "dictionaryWithObjects:forKeys:")! let instance = classNSDictionary.instance( - object: classNSDictionary.call(methodDictionaryWithValuesForKeys, with: ["1"], with: ["a"], return: .reference) + object: { + let function = unsafeBitCast( + methodDictionaryWithValuesForKeys.implementation, + to: (@convention(c)(AnyClass, Selector, [String], [String])->[String: String]).self + ) + return function( + methodDictionaryWithValuesForKeys.anyClass, + methodDictionaryWithValuesForKeys.selector, + ["1"], + ["a"] + ) + }() )! XCTAssertNotNil(instance.method(name: "objectForKey:")) @@ -25,21 +36,62 @@ final class NSObjectInstanceMethodTest: XCTestCase { let classNSDictionary = NSObjectClass(name: "NSDictionary")! let methodDictionaryWithValuesForKeys = classNSDictionary.method(name: "dictionaryWithObjects:forKeys:")! let instance = classNSDictionary.instance( - object: classNSDictionary.call(methodDictionaryWithValuesForKeys, with: ["1"], with: ["a"], return: .reference) + object: { + let function = unsafeBitCast( + methodDictionaryWithValuesForKeys.implementation, + to: (@convention(c)(AnyClass, Selector, [String], [String])->[String: String]).self + ) + return function( + methodDictionaryWithValuesForKeys.anyClass, + methodDictionaryWithValuesForKeys.selector, + ["1"], + ["a"] + ) + }() )! let methodObjectForKey = instance.method(name: "objectForKey:")! - XCTAssertEqual(instance.call(methodObjectForKey, with: "a", return: .reference(String.self))!, "1") + XCTAssertEqual({ + let function = unsafeBitCast( + methodObjectForKey.implementation, + to: (@convention(c)(NSObject, Selector, String)->String).self + ) + return function( + methodObjectForKey.object, + methodObjectForKey.selector, + "a" + ) + }(), "1") } func test__call_return_value() { let classNSDictionary = NSObjectClass(name: "NSDictionary")! let methodDictionaryWithValuesForKeys = classNSDictionary.method(name: "dictionaryWithObjects:forKeys:")! let instance = classNSDictionary.instance( - object: classNSDictionary.call(methodDictionaryWithValuesForKeys, with: ["1"], with: ["a"], return: .reference) + object: { + let function = unsafeBitCast( + methodDictionaryWithValuesForKeys.implementation, + to: (@convention(c)(AnyClass, Selector, [String], [String])->[String: String]).self + ) + return function( + methodDictionaryWithValuesForKeys.anyClass, + methodDictionaryWithValuesForKeys.selector, + ["1"], + ["a"] + ) + }() )! let methodCount = instance.method(name: "count")! - XCTAssertEqual(instance.call(methodCount, return: .value(Int.self))!, 1) + XCTAssertEqual({ + let function = unsafeBitCast( + methodCount.implementation, + to: (@convention(c)(NSObject, Selector)->Int).self + ) + return function( + methodCount.object, + methodCount.selector + ) + }(), 1) } } diff --git a/Test/AppleObjectiveCReflection/NSObjectInstanceTest.swift b/Test/AppleObjectiveCReflection/NSObjectInstanceTest.swift index 7d6270c..6ed57b2 100644 --- a/Test/AppleObjectiveCReflection/NSObjectInstanceTest.swift +++ b/Test/AppleObjectiveCReflection/NSObjectInstanceTest.swift @@ -10,12 +10,23 @@ import XCTest final class NSObjectInstanceTest: XCTestCase { func test__init_instance() { - let NSDictionary = NSObjectClass(name: "NSDictionary")! - let dictionaryWithValuesForKeys = NSDictionary.method(name: "dictionaryWithObjects:forKeys:")! - let instance = NSDictionary.instance( - object: NSDictionary.call(dictionaryWithValuesForKeys, with: ["1"], with: ["a"], return: .reference) + let classNSDictionary = NSObjectClass(name: "NSDictionary")! + let dictionaryWithValuesForKeys = classNSDictionary.method(name: "dictionaryWithObjects:forKeys:")! + let instance = classNSDictionary.instance( + object: { + let function = unsafeBitCast( + dictionaryWithValuesForKeys.implementation, + to: (@convention(c)(AnyClass, Selector, [String], [String])->[String: String]).self + ) + return function( + dictionaryWithValuesForKeys.anyClass, + dictionaryWithValuesForKeys.selector, + ["1"], + ["a"] + ) + }() )! - XCTAssertTrue(instance.object.isKind(of: NSDictionary.anyClass)) + XCTAssertTrue(instance.object.isKind(of: classNSDictionary.anyClass)) } }