-
-
Save cprovatas/98ff940140c8744c4d1f3bcce7ba4543 to your computer and use it in GitHub Desktop.
// | |
// BlockBasedSelector.h | |
// | |
// Created by Charlton Provatas on 11/2/17. | |
// Copyright © 2017 CharltonProvatas. All rights reserved. | |
// | |
#import <Foundation/Foundation.h> | |
@interface BlockBasedSelector : NSObject | |
@end | |
typedef void (^OBJCBlock)(id _Selector); | |
typedef void (^OBJCBlockWithSender)(id _Selector, id sender); | |
void class_addMethodWithBlock(Class class, SEL newSelector, OBJCBlock block); | |
void class_addMethodWithBlockAndSender(Class class, SEL newSelector, OBJCBlockWithSender block); |
// | |
// BlockBasedSelector.m | |
// | |
// Created by Charlton Provatas on 11/2/17. | |
// Copyright © 2017 CharltonProvatas. All rights reserved. | |
// | |
#import "BlockBasedSelector.h" | |
#import <objc/runtime.h> | |
@implementation BlockBasedSelector | |
@end | |
void class_addMethodWithBlock(Class class, SEL newSelector, OBJCBlock block) | |
{ | |
IMP newImplementation = imp_implementationWithBlock(block); | |
Method method = class_getInstanceMethod(class, newSelector); | |
class_addMethod(class, newSelector, newImplementation, method_getTypeEncoding(method)); | |
} | |
void class_addMethodWithBlockAndSender(Class class, SEL newSelector, OBJCBlockWithSender block) | |
{ | |
IMP newImplementation = imp_implementationWithBlock(block); | |
Method method = class_getInstanceMethod(class, newSelector); | |
class_addMethod(class, newSelector, newImplementation, method_getTypeEncoding(method)); | |
} |
// | |
// BlockBasedSelector.swift | |
// Parking | |
// | |
// Created by Charlton Provatas on 11/9/17. | |
// Copyright © 2017 Charlton Provatas. All rights reserved. | |
// | |
import Foundation | |
// swiftlint:disable identifier_name | |
func Selector(_ block: @escaping () -> Void) -> Selector { | |
let selector = NSSelectorFromString("\(CFAbsoluteTimeGetCurrent())") | |
class_addMethodWithBlock(_Selector.self, selector) { _ in block() } | |
return selector | |
} | |
/// used w/ callback if you need to get sender argument | |
func Selector(_ block: @escaping (Any?) -> Void) -> Selector { | |
let selector = NSSelectorFromString("\(CFAbsoluteTimeGetCurrent())") | |
class_addMethodWithBlockAndSender(_Selector.self, selector) { (_, sender) in block(sender) } | |
return selector | |
} | |
// swiftlint:disable identifier_name | |
let Selector = _Selector.shared | |
@objc class _Selector: NSObject { | |
static let shared = _Selector() | |
} |
It leaks memory in swift 5, can you please help me
@cprovatas I converted your obj-c code into swift, but sadly I am getting
nil
fromclass_getInstanceMethod
func class_addMethodWithBlock(class c: AnyClass, newSelector: Selector, block: @escaping @convention(block) () -> Void) { let imp = imp_implementationWithBlock(block) guard let method = class_getInstanceMethod(c, newSelector) else { fatalError("class_getInstanceMethod") } class_addMethod(c, newSelector, imp, method_getTypeEncoding(method)) } func class_addMethodWithBlockAndSender(class c: AnyClass, newSelector: Selector, block: @escaping @convention(block) (Any?) -> Void) { let imp = imp_implementationWithBlock(block) guard let method = class_getInstanceMethod(c, newSelector) else { fatalError("class_getInstanceMethod") } class_addMethod(c, newSelector, imp, method_getTypeEncoding(method)) }
Me too return me nil, There is an updated version of the code in swift?
You have to import that class as an objective-c class as there are some issues with how the blocks are bridged into Swift. Just import 'BlockBasedSelector.h' into your bridging header file and everything should work as expected.
There is no license information. Can this be made available for consumption in a commercial application with a good open license? Or is ther any other way to license this for such use?
@lukya yes feel free to use it. this snippet was written independently by myself and isn't the IP of any other entity
Hi maybe you can help me. I take an error when I run method Selector : unrecognized selector sent to instance 0x10dd44ce0'
@cprovatas I converted your obj-c code into swift, but sadly I am getting
nil
fromclass_getInstanceMethod