是否OBJC_ASSOCIATION_RETAIN_NONATOMIC在的关联对象行为的Objective-C运行参考,呼吁release对相关对象引用的旧值赋给和保留新的前值?
我正在尝试动态确定Objective-C中属性的类型.根据我在本网站和其他地方的内容,我相信我做的是正确的.但是,我的代码无效.
下面的代码片段演示了这个问题.尝试获取"backgroundColor"和"frame"的属性信息(两者都是UIView的有效属性)失败(class_getProperty()返回NULL):
id type = [UIView class];
objc_property_t backgroundColorProperty = class_getProperty(type, "backgroundColor");
fprintf(stdout, "backgroundColorProperty = %d\n", (int)backgroundColorProperty); // prints 0
objc_property_t frameProperty = class_getProperty(type, "frame");
fprintf(stdout, "frameProperty = %d\n", (int)frameProperty); // prints 0
Run Code Online (Sandbox Code Playgroud)
描述枚举的属性在这里没有产生预期的结果,无论是.以下代码:
NSLog(@"Properties for %@", type);
unsigned int outCount, i;
objc_property_t *properties = class_copyPropertyList(type, &outCount);
for (i = 0; i < outCount; i++) {
objc_property_t property = properties[i];
fprintf(stdout, "%s %s\n", property_getName(property), property_getAttributes(property));
}
Run Code Online (Sandbox Code Playgroud)
生成此输出:
2012-03-09 13:18:39.108 IOSTest[2921:f803] Properties for UIView
caretRect T{CGRect={CGPoint=ff}{CGSize=ff}},R,N,G_caretRect
gesturesEnabled Tc,N
deliversTouchesForGesturesToSuperview …Run Code Online (Sandbox Code Playgroud) 这是我想要做的比较操作:
// foobar is the name of an ivar on some class
// i.e. NSDate *foobar;
const char *ivarType = [self getTypeForInstanceVariableWithName:@"foobar"];
const char *objType = @encode(NSDate);
if (strcmp(ivarType, objType) == 0) {
//set value
}
NSLog(@"comparing %s with %s", ivarType, objType);
Run Code Online (Sandbox Code Playgroud)
辅助方法:
- (const char*)getTypeForInstanceVariableWithName:(NSString *)name {
return ivar_getTypeEncoding(class_getInstanceVariable([self class], [name cStringUsingEncoding:NSUTF8StringEncoding]));
}
Run Code Online (Sandbox Code Playgroud)
NSLog结果:
comparing @"NSDate" with {NSDate=#}
Run Code Online (Sandbox Code Playgroud)
为什么@encode会返回与ivar_getTypeEncoding()不同的类型语法?有没有更好的方法来完成这种类型的决定?我必须在这里遗漏一些东西......谢谢!
我试图在运行时获取一个方法,然后使用其数据结构来调用它的实现.只是为了澄清,这是出于学习目的,而不是出于任何实际原因.所以这是我的代码.
#import <Foundation/Foundation.h>
#import <stdio.h>
#import <objc/runtime.h>
@interface Test : NSObject
-(void)method;
@end
@implementation Test
-(void)method {
puts("this is a method");
}
@end
int main(int argc, char *argv[]) {
struct objc_method *t = (struct objc_method*) class_getInstanceMethod([Test class], @selector(method));
Test *ztest = [Test new];
(t->method_imp)(ztest, t->method_name);
[ztest release];
return 0;
}
Run Code Online (Sandbox Code Playgroud)
定义struct objc_method如下(在objc/runtime.h中定义)
typedef struct objc_method *Method;
....
struct objc_method {
SEL method_name OBJC2_UNAVAILABLE;
char *method_types OBJC2_UNAVAILABLE;
IMP method_imp OBJC2_UNAVAILABLE;
} OBJC2_UNAVAILABLE;
Run Code Online (Sandbox Code Playgroud)
但是当我尝试编译我的代码时,我得到了这个错误.
error: dereferencing pointer to incomplete type …
是否有相反的运营商@encode?
例如,当你这样做时@encode(int),你得到了"i".我希望能够这样做:@decode("i") myInt = 5;
这可能吗?是否存在操作员来处理此问题?
基于此处描述的技术,我使用ivar_getOffset()方法在对象实例中设置ivars.
现在我的情况是ivar是一个NSString*:
NSString* _name;
Run Code Online (Sandbox Code Playgroud)
更新:
我在错误的轨道上(在这种情况下不能使用ivar_getOffset),我应该使用:
object_setIvar(target, _ivar, [stringValue copy]);
Run Code Online (Sandbox Code Playgroud)
将对象值分配给ivars.
我的问题仍然存在:在ARC下这样做是否安全?ARC的现有物体是否会被ARC正确释放?
我担心ARC可能无法正确释放ivar在作业之前设置的任何字符串.虽然我对此表示怀疑,否则编译器不会让我喜欢object_setInstanceVariable("在自动引用计数模式下不可用") - 对吗?
objective-c variable-assignment objective-c-runtime ivar automatic-ref-counting
调用object_getClass(obj)和[obj class]时,我得到两个不同的对象实例.知道为什么吗?
Class cls = object_getClass(obj);
Class cls2 = [obj class];
(lldb) po cls
$0 = 0x0003ca00 Test
(lldb) po cls2
$1 = 0x0003ca14 Test
(lldb)
Run Code Online (Sandbox Code Playgroud) 我知道当一个对象在堆上实例化时,至少分配足够的内存来保存对象的ivars.我的问题是编译器如何存储方法.内存中只有一个方法代码实例吗?或者代码是在内存中生成对象的固有部分,与ivars连续存储并执行?
似乎后者就是这种情况,即使像NSStrings这样的小事也需要(相对)大量的内存(也NSString从中继承方法NSObject).
或者该方法是在内存中存储一次并将指针传递给拥有它的对象?
我的理解是,对象和类在Objective-C的只是结构.
他们分别只是:
struct objc_class *
Run Code Online (Sandbox Code Playgroud)
和:
struct objc_object *
Run Code Online (Sandbox Code Playgroud)
问题#1:
objc_msgSend(id self, SEL _cmd);
Run Code Online (Sandbox Code Playgroud)
id 据我所知是类型 struct objc_object *
但是当我们调用类方法时,类是一个类struct objc_class *,
我希望它会引起问题或者喊出某种警告,例如"嘿,这里的错误类型,我的朋友".
但事实并非如此.
这只是为了满足我的好奇心,因为即使没有完全理解这一点,它似乎也没有给我带来任何麻烦(到目前为止).但我想深入挖掘并学习基本原理/"特点".
问题2:
由于根据我的经验没有警告(与问题#1有关),因此我不太确定它们可以互换使用.
能struct objc_class *和struct objc_object * 真正使用互换?
如是:
你能告诉我一个场景和样本何时/如何/为什么我们需要互换使用这些?
什么是好处(如果有的话),缺点(如果有的话)和" 陷阱 "(需要注意的事项;如果有的话)这样做?
我试图搜索以防止我当前库中的方法Swizzle,但我或多或少发现每个文档或博客文章是关于如何实现Swizzling.关于Method swizzling,我有几个问题,我无法找到所有问题.
我知道方法调整的危险,并且已经在这里查看了相关的帖子,但是找不到相关信息来阻止它.
如果上述主题中有任何文档或博客文章,我将非常感谢您的帮助.
objective-c ×10
ios ×4
methods ×2
associative ×1
cocoa-touch ×1
encoding ×1
ipad ×1
iphone ×1
ivar ×1
properties ×1
struct ×1
types ×1