标签: objective-c-runtime

实现Objective-C的根类需要什么?

我试过这段代码:

// 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)

class objective-c objective-c-runtime llvm-clang

5
推荐指数
1
解决办法
3632
查看次数

使用objc_disposeClassPair()

运行时API中有一个未记录的函数,该函数似乎(根据一些玩具程序而定)按照其名称的含义执行操作:

OBJC_EXPORT void objc_disposeClassPair(Class cls) 
     AVAILABLE_MAC_OS_X_VERSION_10_5_AND_LATER;
Run Code Online (Sandbox Code Playgroud)

但是,详细信息在地面上很少。因此,与其说是一个问题,不如说是更多相关问题的集合:

  • 是否有任何关于它的好文章/博客文章,或者有人有使用它的经验(一个快速的Google建议PyObjC开发人员至少在某一时刻考虑使用它)?
  • 是否完全释放了处置的类(经常创建和删除类的应用程序会泄漏内存吗?)
  • 除了未公开的API以外,是否还有其他需要牢记的陷阱?
  • 苹果在哪里使用(可能使用)?NSBundle正在卸载?KVO?

cocoa objective-c objective-c-runtime

5
推荐指数
1
解决办法
497
查看次数

Cocoa/Objective-C插件碰撞

我的应用程序有一个插件系统,允许我的用户编写自己的插件,这些插件在运行时加载.通常这很好,但在某些情况下,两个插件使用相同的库,这将导致这两个插件之间的冲突.

例:

插件A想要使用TouchJSON来处理JSON,因此创建者将TouchJSON代码添加到插件源中,并将其编译并链接到插件二进制文件中.后来插件B也希望使用相同的库并完全相同.现在,当我的应用程序加载这两个不同的插件时,它会检测到这个并发出如下警告:

类CJSONScanner在[path_to_plugin_a]和[path_to_plugin_b]中实现.将使用两者之一.哪一个未定义.

由于我的应用程序只是加载插件并确保它们符合某个协议,我无法控制加载哪些插件以及两个或多个插件使用相同的库.

只要两个插件使用完全相同的库版本,这可能会起作用,但只要API在一个插件中发生更改,就会出现一堆问题.

我能做些什么吗?

cocoa objective-c objective-c-runtime

5
推荐指数
1
解决办法
180
查看次数

参数isKindOfClass:[NSNumber class] - 理智的方式检查这个?

所以我玩的是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

5
推荐指数
1
解决办法
3926
查看次数

NSObject类现在是Objective-C运行时库的一部分(而不是Foundation组件)吗?

看一下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

cocoa objective-c objective-c-runtime foundation nsobject

5
推荐指数
1
解决办法
703
查看次数

调用具有可变参数的方法并转发消息 - Bad Access

我正在实现一个"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

5
推荐指数
1
解决办法
2130
查看次数

Log Objective-c消息在设备上发送

在模拟器中运行iOS应用程序时,会有一个环境变量NSObjCMessageLoggingEnabled导致所有objc_msgSend调用都记录到文件中.(详细说明).

我试图找出我的应用程序中发送的所有消息,但我无法在模拟器中运行它.它必须在物理设备上,因为我通过闪电连接器与硬件进行交互.出于同样的原因,我无法将调试器附加到进程.

将日志写入磁盘(如使用创建的日志)NSObjCMessageLoggingEnabled,但在我的应用程序的Documents目录中将其写入本地或类似日志会很有帮助.

这可能吗?

iphone objective-c objective-c-runtime ios

5
推荐指数
1
解决办法
856
查看次数

如何在swift中使用objective-c-runtime的object_getIvar和object_setIvar?

有没有人知道我为什么在使用以下代码获取和设置我的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-runtime swift

5
推荐指数
1
解决办法
1127
查看次数

在ObjectiveC中设置UITextField的限制

我正在使用Objective C创建登录屏幕,我想在其中实现用户名(电子邮件)和密码的验证.如何以非常简单的方式实现这一点.

xcode objective-c-runtime ios

5
推荐指数
1
解决办法
4555
查看次数

Swift运行时 - 调用超类方法

我正在运行时创建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-runtime swift

5
推荐指数
1
解决办法
265
查看次数