On Mon, Nov 21, 2016 at 10:46 AM, Jeff Kelley via swift-users < swift-users@swift.org> wrote:
The type comes from XCTest. I’m trying to enumerate Objective-C methods in
order to use them with XCTest in the open-source Swift version of XCTest,
which needs the tests to be supplied as this type:
/// This is a compound type used by `XCTMain` to represent tests to run. It combines an
/// `XCTestCase` subclass type with the list of test case methods to invoke on the class.
/// This type is intended to be produced by the `testCase` helper function.
/// - seealso: `testCase`
/// - seealso: `XCTMain`
public typealias XCTestCaseEntry = (testCaseClass: XCTestCase.Type, allTests: [(String, (XCTestCase) throws -> Void)])
Jeff Kelley
SlaunchaMan@gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan> |
jeffkelley.org
On Nov 21, 2016, at 1:13 AM, Jacob Bandes-Storch <jtbandes@gmail.com> > wrote:
"throws" is the part that's not representable in Obj-C. Why are you using
it? If you're interacting with method_getImplementation, you need to think
like the Obj-C runtime.
https://developer.apple.com/library/content/documentation/
Cocoa/Conceptual/ObjCRuntimeGuide/Articles/ocrtHowMessagingWorks.html#//
apple_ref/doc/uid/TP40008048-CH104-SW1
This works:
typealias DescriptionMethod = @convention(c) (NSObject, Selector) ->
NSString
let fn = unsafeBitCast(method_getImplementation(class_
getInstanceMethod(NSObject.self, "description")), DescriptionMethod.self)
fn(NSObject(), "description") as String
Jacob
On Sun, Nov 20, 2016 at 9:41 PM, Jeff Kelley <slaunchaman@gmail.com> > wrote:
Still trying on this (copied the code directly, Foo is actually
XCTestCase):
typealias TestMethod = @convention(c) (XCTestCase) throws -> Void
This seagulls the compiler with “error: '(XCTestCase) throws -> Void' is
not representable in Objective-C, so it cannot be used with '@convention(c)
’”. I’m trying to use it here:
let testMethod: IMP = method_getImplementation(method)
let test: TestMethod = unsafeBitCast(testMethod,
to: TestMethod.self)
testMethods.append((methodName as String, test))
If I try to put the type directly in the call to unsafeBitCast(), the
compiler gives me an error:
Attribute can only be applied to types, not declarations
Thanks for your suggestions! I hadn’t seen @convention() before.
Jeff Kelley
SlaunchaMan@gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan> |
jeffkelley.org
On Nov 21, 2016, at 12:08 AM, Jacob Bandes-Storch <jtbandes@gmail.com> >> wrote:
For a function such as bar() above, the type you want to cast the IMP to
would probably be "@convention(c) (Foo, Selector) -> ()".
On Sun, Nov 20, 2016 at 9:05 PM, Jeff Kelley <slaunchaman@gmail.com> >> wrote:
Thanks Jacob! I tried using unsafeBitCast, but it fails with the
following: “fatal error: can't unsafeBitCast between types of different
sizes”. I considered wrapping every call in a closure that calls
objc_msgSend(), but alas, that’s not exposed to Swift. I have another
approach in mind, so I’ll try that next.
Jeff Kelley
SlaunchaMan@gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan>
> jeffkelley.org
On Nov 19, 2016, at 1:58 AM, Jacob Bandes-Storch <jtbandes@gmail.com> >>> wrote:
I imagine unsafeBitCast would be the way to go here. But are you
assuming that all of the instance methods have type "(Foo) throws -> Void"
? Or do you somehow want to dynamically use the type information?
Jacob
On Fri, Nov 18, 2016 at 10:37 PM, Jeff Kelley via swift-users < >>> swift-users@swift.org> wrote:
Hello,
I’m trying to enumerate the methods of a class in Swift using the
Objective-C runtime. Everything is working fine so far, except for the very
last step. Suppose I have a Swift class like this:
class Foo: SomeSuperclass {
@objc func bar() {
print("Hello, World!")
}
}
Using the Objective-C runtime methods, I can get the method with
class_copyMethodList and then get to the method’s implementation using
method_getImplementation. However, what I need to do next is to stick
this into a tuple that looks like this:
typealias FooEntry = (fooClass: SomeSuperclass.Type, methods: [(String,
(Foo) throws -> Void)])
For now, the workaround is to make a static variable that returns all
of the entries:
static var allEntries = {
return [
("bar", bar),
]
}
Is there any way to go from the raw IMP that I get back from the
runtime to the Swift type so I can construct this list dynamically?
Jeff Kelley
SlaunchaMan@gmail.com | @SlaunchaMan <https://twitter.com/SlaunchaMan>
> jeffkelley.org
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users
_______________________________________________
swift-users mailing list
swift-users@swift.org
https://lists.swift.org/mailman/listinfo/swift-users