我试过这段代码:
// main.m
#import <stdio.h>
@interface Test
+ (void)test;
@end
@implementation Test
+ (void)test
{
printf("test");
}
@end
int main()
{
[Test test];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
如果没有任何框架的LLVM/Clang,它不会编译与此错误:
Undefined symbols:
"_objc_msgSend", referenced from:
_main in main.o
ld: symbol(s) not found
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Run Code Online (Sandbox Code Playgroud)
所以我补充道libobjc.dylib.代码已编译,但抛出了此运行时异常:
objc[13896]: Test: Does not recognize selector forward::
Program received signal: “EXC_BAD_INSTRUCTION”.
#0 0x9932a4b4 in _objc_error
#1 0x9932a4ea in __objc_error
#2 0x993212b6 in _objc_msgForward
#3 …Run Code Online (Sandbox Code Playgroud) 运行时API中有一个未记录的函数,该函数似乎(根据一些玩具程序而定)按照其名称的含义执行操作:
OBJC_EXPORT void objc_disposeClassPair(Class cls)
AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
Run Code Online (Sandbox Code Playgroud)
但是,详细信息在地面上很少。因此,与其说是一个问题,不如说是更多相关问题的集合:
我的应用程序有一个插件系统,允许我的用户编写自己的插件,这些插件在运行时加载.通常这很好,但在某些情况下,两个插件使用相同的库,这将导致这两个插件之间的冲突.
例:
插件A想要使用TouchJSON来处理JSON,因此创建者将TouchJSON代码添加到插件源中,并将其编译并链接到插件二进制文件中.后来插件B也希望使用相同的库并完全相同.现在,当我的应用程序加载这两个不同的插件时,它会检测到这个并发出如下警告:
类CJSONScanner在[path_to_plugin_a]和[path_to_plugin_b]中实现.将使用两者之一.哪一个未定义.
由于我的应用程序只是加载插件并确保它们符合某个协议,我无法控制加载哪些插件以及两个或多个插件使用相同的库.
只要两个插件使用完全相同的库版本,这可能会起作用,但只要API在一个插件中发生更改,就会出现一堆问题.
我能做些什么吗?
所以我玩的是arg的类类型在运行时未知的东西.像这样:
- (NSNumber *)doWhatever:(id)arg
{
// this ALWAYS FAILS
if ([arg isKindOfClass:[NSNumber class]]) {
return arg;
}
else {
// what was it???
NSLog("arg klass=%@", [arg class]); // prints NSCFNumber
}
// This check works correctly.
if ([arg isKindOfClass:[NSArray class]]) {
for (id x in arg) {
NSNumber *result = [self doWhatever:x];
if (result) {
return result;
}
}
}
return nil;
}
- (void)someMethod
{
NSArray *myArray = [NSArray arrayFromObjects:[NSNumber numberWithInt:3], nil]];
NSNumber *myNum = [self doWhatever:myArray];
NSLog(@"myNum=%@", myNum); …Run Code Online (Sandbox Code Playgroud) types objective-c objective-c-runtime dynamic-typing nsnumber
看一下Mac OS X 10.8版本的Objective-C运行时库源代码,我注意到它有一个NSObject.mm文件.顾名思义,它有NSObject类实现,以及内置自动释放池和保留计数实现.
但是,Mountain Lion之前的ObjC运行时库的版本没有实现NSObject该类(它们没有NSObject.mm文件,正如您可以在Mac OS X 10.7的Objective-C运行时库源代码中看到的那样,例如).
那么这是否真的意味着NSObject该类现在是Objective-C运行时库的一部分而不是作为Foundation库组件?如果是,为什么?是否要-framework Foundation在子类化时避免与整个Foundation库(with )链接NSObject?
我正在实现一个"Code Injector Class",通过方法调配可以让你做到这样的事情:
FLCodeInjector *injector = [FLCodeInjector injectorForClass:[self class]];
[injector injectCodeBeforeSelector:@selector(aSelector:) code:^{
NSLog(@"This code should be injected");
}];
Run Code Online (Sandbox Code Playgroud)
aSelector可以是具有可变数量的参数和变量返回类型的方法.参数/和返回类型可以是对象或基本类型.
首先,我附上代码,injectCodeBeforeSelector:让你了解我在做什么(我删除了代码的有趣部分):
- (void)injectCodeBeforeSelector:(SEL)method code:(void (^)())completionBlock
{
NSString *selector = NSStringFromSelector(method);
[self.dictionaryOfBlocks setObject:completionBlock forKey:selector];
NSString *swizzleSelector = [NSString stringWithFormat:@"SWZ%@", selector];
// add a new method to the swizzled class
Method origMethod = class_getInstanceMethod(self.mainClass, NSSelectorFromString(selector));
const char *encoding = method_getTypeEncoding(origMethod);
[self addSelector:NSSelectorFromString(swizzleSelector) toClass:self.mainClass methodTypeEncoding:encoding];
SwizzleMe(self.mainClass, NSSelectorFromString(selector), NSSelectorFromString(swizzleSelector));
}
-(void)addSelector:(SEL)selector toClass:(Class)aClass methodTypeEncoding:(const char *)encoding
{
class_addMethod(aClass,
selector,
(IMP)genericFunction, encoding);
}
Run Code Online (Sandbox Code Playgroud)
基本上,我使用class_addMethod将伪/ …
objective-c variadic-functions objective-c-runtime swizzling ios
在模拟器中运行iOS应用程序时,会有一个环境变量NSObjCMessageLoggingEnabled导致所有objc_msgSend调用都记录到文件中.(详细说明).
我试图找出我的应用程序中发送的所有消息,但我无法在模拟器中运行它.它必须在物理设备上,因为我通过闪电连接器与硬件进行交互.出于同样的原因,我无法将调试器附加到进程.
将日志写入磁盘(如使用创建的日志)NSObjCMessageLoggingEnabled,但在我的应用程序的Documents目录中将其写入本地或类似日志会很有帮助.
这可能吗?
有没有人知道我为什么在使用以下代码获取和设置我的iVars时获得BAD_ACCESS?
class myClass: NSObject {
var model = "Unspecified"
override init() {
super.init()
var key: NSString = "model"
var aClass : AnyClass? = self
var ivar: Ivar = class_getInstanceVariable(aClass, key.UTF8String)
// Set
object_setIvar(aClass, ivar, "R56")
// Get
var value: AnyObject = object_getIvar(aClass, ivar)
}
}
myClass()
Run Code Online (Sandbox Code Playgroud) 我正在使用Objective C创建登录屏幕,我想在其中实现用户名(电子邮件)和密码的验证.如何以非常简单的方式实现这一点.
我正在运行时创建UIView的子类,并layoutSubviews为它提供我的方法实现.我需要做的一件重要事情就是表演super.layoutSubviews().在Objective-C中,我可以使用以下objc_msgSendSuper函数:
Class objectClass = object_getClass(object);
Class superclass = class_getSuperclass(objectClass);
struct objc_super superInfo;
superInfo.receiver = object;
superInfo.super_class = superclass;
typedef void *(*ObjCMsgSendSuperReturnVoid)(struct objc_super *, SEL);
ObjCMsgSendSuperReturnVoid sendMsgReturnVoid = (ObjCMsgSendSuperReturnVoid)objc_msgSendSuper;
sendMsgReturnVoid(&superInfo, @selector(layoutSubviews));
Run Code Online (Sandbox Code Playgroud)
但objc_msgSendSuper方法在Swift中不可用.我应该用什么来做同样的事情?
objective-c ×7
cocoa ×3
ios ×3
swift ×2
class ×1
foundation ×1
iphone ×1
llvm-clang ×1
nsnumber ×1
nsobject ×1
swizzling ×1
types ×1
xcode ×1