iOSプレミアム開発runtimeの件実戦(2)

4262 ワード

classのpropertyプロパティリストの取得

-(void)printPropertyList{
    unsigned int count ;// 
    objc_property_t * methodsVar = class_copyPropertyList([UINavigationController class], &count) ;
    for (int i = 0; i < count; i ++) {
        objc_property_t var = methodsVar[i] ;
        NSString * strName =[NSString stringWithUTF8String:property_getName(var)];
        NSString * str =[NSString stringWithUTF8String:property_getAttributes(var)];
        NSLog(@"  %@      %@",str,strName);
    }
    free(methodsVar);
}

classの名前を取得

-(void)printfClassName{
    Class clas = NSClassFromString(@"NSString");
   printf("%s", class_getName(clas)); // clas  return value  nil
}

 :NSString

クラスの親を取得して出力

-(void)printfClassName:(Class )clas{
   printf("%s", class_getName(clas));
}
-(Class)getSuperClass:(Class)clas{
    return class_getSuperclass(clas);
}

[self printfClassName:[self getSuperClass:NSClassFromString(@"UIView")]];
 :UIResponder

クラスの親の設定

/** 
 * Sets the superclass of a given class.
 * 
 * @param cls The class whose superclass you want to set.
 * @param newSuper The new superclass for cls.
 * 
 * @return The old superclass for cls.
 * 
 * @warning You should not use this function.  
 */
OBJC_EXPORT Class class_setSuperclass(Class cls, Class newSuper) 
     __OSX_AVAILABLE_BUT_DEPRECATED(__MAC_10_5,__MAC_10_5, __IPHONE_2_0,__IPHONE_2_0);
     
    [self printfClassName:[self getSuperClass:NSClassFromString(@"FY")]]; NSObjec
    [self setClass:NSClassFromString(@"FY") newSuperClass:NSClassFromString(@"UIImageView")];// 
    [self printfClassName:[self getSuperClass:NSClassFromString(@"FY")]];// UIImageView  
    

-(void)printfClassName:(Class )clas{
   printf("%s
", class_getName(clas)); } -(Class)getSuperClass:(Class)clas{ return class_getSuperclass(clas); } -(Class)setClass:(Class)clas newSuperClass:(Class)superClas{ return class_setSuperclass(clas, superClas); }

オブジェクトとクラスの区分

-(void)isMetaClass{
    NSMutableArray *arr = [[NSMutableArray alloc] init];
    
    [arr addObject:[NSObject class]];
    [arr addObject:[NSValue class]];
    [arr addObject:[NSNumber class]];
    [arr addObject:[NSPredicate class]];
    [arr addObject:@"not a class object"];
    
    for (int i; i

クラスが占めるバイトのサイズを取得

size_t size = class_getInstanceSize(NSClassFromString(@"UIView"));
    printf("%zu",size);

クラスのプロパティとそのプロパティのタイプを取得

-(void)ivarList{
    unsigned int count;
    Ivar * vars = class_copyIvarList(NSClassFromString(@"UIViewController"), &count)//ivar     name,offset,type 。
    ;
    for (int i = 0; i < count; i ++) {
        Ivar  var = vars[i];
        [self printIvar:var];
    }
    free(vars);
}
-(void)printIvar:(Ivar)var{// 
    const  char * name = ivar_getName(var);
    long  offset = ivar_getOffset(var);
    const  char * type = ivar_getTypeEncoding(var);
    printf("%s %ld %s
",name,offset,type); } : _storyboard 152 @"UIStoryboard" _externalObjectsTableForViewLoading 160 @"NSDictionary" _topLevelObjectsToKeepAliveFromStoryboard 168 @"NSArray" _savedHeaderSuperview 176 @"UIView" _savedFooterSuperview 184 @"UIView"

これらはapple Objectice-C Runtime Referenceで、具体的にはこのサイトでもっと見られます.
前編で述べた方法名はvoid method_exchangeImplementations(Method m1, Method m2)です.この交換方法は1回しか実行できないので、交換を2回解決したのは、交換していないことに相当します.具体的なコード:
static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{

        void (^__method_swizzling)(Class, SEL, SEL) = ^(Class cls, SEL sel, SEL _sel) {
            Method  method = class_getInstanceMethod(cls, sel);
            Method _method = class_getInstanceMethod(cls, _sel);
            method_exchangeImplementations(method, _method);
        };
      }

ここではこの方法をc関数にカプセル化し,一度しか実行できないことを保証し,このdispatch+ load関数に入れ,ロード回数の減少を保証したほうがよい.その他のブログはwww.fgyong.cnが表示されます.