One plus开发入门(七)— 在App Store上揭破程序

详解objc_msgSend

先后终于编纂好了,那1次介绍应用程序的公告流程。通过 App Store
将协调的先后向全世界公开。

详解objc_msgSend

准备干活

向 App Store 注册本身的顺序在此之前,须要准备以下的事物。

  • 57×57像素的ICON
  • 512×512像素的ICON (JPEG或TIFF格式)
  • 荧屏截图

 一、为了品质,objc_msgSend用汇编写成。存在于objc-msg-x86_64.s中。

制作ICON

此间的多个图标分别是装备上意味着这几个应用程序的图标(57×伍7)和在iTunes的App
Store上象征的图标(51二×512)。比如下边那七个图标。

起名 1

急需专注的是,小的图标(伍7x伍柒)能够是PNG格式的,而在App
Store上用的大的图标(51二x51二)必须是JPEG或然TIFF的格式。个中型小型的图标在编写翻译程序的时候作为程序财富已经包括到程序文件中了,而大的图标供给通过别的方法登录到App
Store上。

  起名 2

设置程序中运用的ICON

先是来设置程序中选择的小图标。那里图标文件的称呼为「Icon.png」。
打开程序的Xcode项目后,拖动该图标文件到左手的「Resources」目录。

起名 3

在弹出的对话框中,选用方面包车型客车「拷贝到目标组文件夹(要求的气象下)」,并认可下边包车型客车「添加到目的」被选上了。点击添加。

起名 4

图标添加到工程中后,须要设定其为应用程序的ICON。点击Resources文件夹下的「Info.plist」,在「Icon
file」表中输入图标名称「Icon.png」。

起名 5

如此这般,就完了了先后中图标的装置,编写翻译未来就能够来得出来呀。

 2、在上海教室代码中得以看来,objc_msgSend被分为2个过程:1)在cache中寻找SEL。2)在MethodTable寻找SEL。

抓屏

荧屏截图可以通过Xcode的organizer来抓取。设备连接下的情状,从organizer选取「Screenshot」标签。

起名 6

点击右下角的「Capture」,就会活动截取连接中装备的显示屏。所以在应用程序运行的时候点击那些按钮就足以了。抓取后可以将图片拖动到适当的地方保存。格式选拔JPEG。

起名 7

 三、CacheLookup中,不断地拿SEL与cache中的缓存比较,比较战败,则跳转到 LCacheMiss标签继续在MethodTable中找找。

给程序起名

给程序起个好名字是很关键的。改名字会被展现在主画面包车型地铁次第图标上边。名字绝不太长,不然会被省略掉。语言是克罗地亚共和国(Republika Hrvatska)语依然粤语未有关联。

起名 8

  起名 9

更改名字

缺省状态下程序的名号与类型的名号一致。须求改变的时候,编辑刚才设置图标时的Info.plist,在那之中的「Bundle
displayname」正是应用程序的称呼。

起名 10

  假诺想手动查找cache,则需求调用_cache_getimp函数(汇编完成),此函数是个对外接口层,用于保存与准备条件。

其余的设定

再来看看Info.plist中仍是能够设置什么样新闻。

  • 依据程序的界面语言选用那种语言的App Store,使用「Localization native
    development region」。那里选择「Japan」。
  • 为了分歧不相同团体,小编开发的应用程序,使用「Bundle
    identifier」中的「com.yourcompany」,采用不一样的KeyWord。尽量选拔与自身非凡的剧情。
  • 「Bundle
    version」中装置程序的版本音讯,比如最初公布的时候是「一.0」。

起名 11

  起名 12

创建 distribution build

颁发在App Store的顺序与前边开发中在 金立或许模拟器中测试的先后是见仁见智的。须要用叫做 distribution build
的不二等秘书籍来编写翻译。与事先的编写翻译格局相同的是也必要创造Provisioning。

  _cache_getImp在头文件中objc-private.h中,链接后objc/c代码能够直接调用。

创建 Provisioning

上一回成立Provisioning的章程同样,由中兴Dev Center跳到Program Portal页面,按上面包车型地铁各样来安装。

  起名 13

注册证件

选料左侧的「Certificates」,双击「Distribution」。

起名 14

上一回挂号设备的证书一样的一1,接纳文件后注册。停止未来下载表明书。

 四、MethodTableLookup
是个接口层宏,首要用来保存环境与准备参数,来调用 __class_lookupMethodAndLoadCache3函数(此函数实现于objc-class.mm)。

创建 Provisioning Profile

上一回介绍的同等,选拔左侧的「Provisioning」后,双击「Distribution」。「Distribution
Method」设置为「App
Store」,然后输入上一回设置的始末,点击Submit,下载安装创立好的Provisioning
Profile。

起名 15

  起名 16

品类设定

为了成立 distribution build,需求向工程中添加新的编译指标。由 Xcode
的菜谱点击「项目」→「项目设定」中的「构成」标签。

起名 17

慎选表中的「Release」,并点击在下的「複製」,生成「Release的正片」后,将其名称改为「Distribution」。结束后点击「编写翻译」标签,选拔「Distribution」。

起名 18

最终,须要在「Any 索尼爱立信 OS Device」项目上选用刚刚安装的Provisioning
Profile。

 5、__class_lookupMethodAndLoadCache三函数也是个接口层(C编写),此函数提供相应参数配置,实际效用在lookUpMethod函数中。

编译

归来 Xcode
的主窗口,Active的SDK选拔「Device」,Active的构成选拔「Distribution」。因为用distribution
build编写翻译的公文不能够直接在设施上应用,所以大家无法选择「编写翻译并实施」,而是只是点击Xcode的「编写翻译」菜单下的「编写翻译」按钮。

起名 19

编写翻译介绍今后,在档次目录下的「build」文件夹下会转变「Distribution-iphoneos」目录。后缀名称叫app的文书正是编写翻译好的次第文件。在文件上点击右键,采取「压缩为”(项目名).app”」。

起名 20

而后,就会在相同目录下转移后缀名称叫zip的压缩文件。

  起名 21

发表程序到 App Store

为了将应用程序发布到 App Store 上,必要选拔 iTunes Connect。

 陆、lookUpMethod函数实现遍历method_list_t,从子类早先,一贯遍历到根类。此函数代码较大,不贴图了。文件在objc-class中。

连接 iTunes Connect

选拔 Program Portal 中的「Distribution」→「App Store」标签。点击 App
Store 项目中的「Learn More」,然后点击当中的「Go to iTunes
Connect」连接。

起名 22

Cache Of lookUpMethod

公布程序

起名 23

在下左侧的「Manage Your Application」。在接下去的镜头上点击「Add New
Application」。

假定是第二回披露温馨的主次,供给安装程序的语言和开发者的名称。开发者的名目是指用iTunes
Connect连接App
Store的时候,在右上角代表的名字,那么些名字能够是商行的称号,卡发团队的称号,可能是您所付出顺序的无比的品牌。那四个设置现在无法更改的,所以需求郑重。接下来的镜头确认你的次序是或不是必要加密,一般选用「No」。在接下去的镜头「Overview」中输入程序的其他新闻,加粗的字体是必须的类型。

  • Application Name – 程序名称
  • Application Description – 程序表达
  • Device – 对应装备。选用相应的设备
  • Primary Category – 程序的归类
  • Copyright – 作品权,开发者的名字等音信
  • Version Number – 在App
    Store上意味着的顺序版本。壹般与程序中装置的版本相同
  • SKU Number – 产品号码。要是你付出了多少个程序,不要与其余程序重复
  • Support URL – 在App Store上代表的技术协助的地点链接
  • Support Email Address – 邮箱地址

在接下去的镜头「Upload」中上传事先准备好的公文。

  • Application – 编写翻译好的应用程序文件(压缩文件,后缀名称为zip的格外)
  • Large 51二x51二 Icon – 51二×512像素的图标文件
  • Primary Screenshot – 荧屏截图文件

挑选好后,点击下一步。

在接下去的「Pricing」画面,设置程序的公告日期,以及发表的国家。

  • Availability Date – 应用程序的宣布日期。假如不知底,缺省为上传的日期
  • Price Tier – 应用程序的价格。即使是免费的取舍「Free」

那里,设定发表日期的时候须要留意一件事情。因为上传的程序实体无法马上发表到
App Store 上,需求中间检查实验职员的评定审查,惟有经过的才能确实地上传到 App
Store
上。这些评定审查的时日大体是1个星期左右。而上传的新闻等会依据你设定的公布日期来呈现。所以,固然你设置公布日期为上传的日子,那么广告打出去了(App
Store上的首页中显得),而实质上的先后却无法下载。到了真正能下载的时候,你的广告已经落的老后了,减少了被点击的概率。所以一般设置公布的日子都比上传的日期中午2/3周为宜。

接下去,在「Localization」页面中能够安装有个别缺省语言意外的程序表明。

持有都安装截至后,最终在「Review」页面中肯定,若是没难点就上传吧。之后,会再次回到到「Manage
Your
Application」页面,你能够肯定程序是不是被添加到列表中。假设Status是「In
Review」代表你的次第正在被查处,审查实现后等候发卖的时候状态会化为「Ready
for Sale」,到了如今设定的公告日期,会自动地公布出来。

假诺 Status 是「Pending Contract」表示报名 华为 Developer Program
中的帐号手续时存在难题,要是该情状一贯不断着,你能够联系ADC,询问具体原因。

  To speed the messaging process, the runtime system caches the
selectors and addresses of methods as they are used. There’s a separate
cache for each class, and it can contain selectors for inherited
methods as well as for methods defined in the class
. Before searching
the dispatch tables, the messaging routine first checks the cache of the
receiving object’s class (on the theory that a method that was used once
may likely be used again). If the method selector is in the cache,
messaging is only slightly slower than a function call. Once a program
has been running long enough to “warm up” its caches, almost all the
messages it sends find a cached method. Caches grow dynamically to
accommodate new messages as the program runs.

HTC开发的大家

到此截止 OPPO开发入门 类别已经八9不离10尾声了。倘若想要成为HUAWEI开发领域的专家那么还索要很短的路来走。但是大家曾经学会了最起码的环境搭建,简单地先后支付,以及Objective-C语言的底子。对于索爱上的一个好程序(赚钱的程序)来说,有时并不须求你有多高的顺序开发基础,就像是第一回自己提到的那么,首要的是要有好的新意。

接下去自个儿还会越来越刻画入微地介绍BlackBerry开发进度中的技巧,知识等。希望获得你的关切。

#import <objc/runtime.h>
void setBeingRemoved(id __self, SEL _cmd)
{
    NSLog(@"------------UNSELECT BY INVOKE.");
}

//    Then these two lines:

    Class __class = NSClassFromString(@"WebActionDisablingCALayerDelegate");
    class_addMethod(__class,
                    @selector(willBeRemoved),
                    (IMP)setBeingRemoved,
                    NULL);

    class_addMethod(__class,
                    @selector(removeFromSuperview),
                    (IMP)setBeingRemoved,
                    NULL);

  

 class_addMethod的详解

Obj-C用起来真是各样happy,比如现在有诸如此类一种状态:有三个类,大家盼望它能响应多少个新闻(message),不过这几个类没有相应的章程(method),而你又偏偏不能够重写/继承这几个类。那时大家大概会想到,能或不可能动态地给类添加贰个方法吗?谢谢Obj-C,仅需简单几步就能促成。

先看一段代码

#if TARGET_IPHONE_SIMULATOR 
#import  
#else #import  
 #import  
#endif   
@interface EmptyClass:NSObject   
 @end   

 @implementation EmptyClass   
@end   

void sayHello(id self, SEL _cmd) 
 { NSLog(@"Hello"); }   

- (void)addMethod 
 { 
     class_addMethod([EmptyClass class], @selector(sayHello2), (IMP)sayHello, "v@:");   
     // Test Method 
    EmptyClass *instance = [[EmptyClass alloc] init]; [instance sayHello2];
    [instance release];   
}

我们率先定义了二个EmptyClass,继承NSObject,未有其它自带方法,接着定义了3个函数。那里提一句,Obj-C的艺术(method)就是一个至少需求八个参数(self,_cmd)的C函数,那些函数仅仅输出一句Hello。接下来在addMethod方法中,大家调用class_addMethod()为EmptyClass添加方法,class_addMethod()是如此定义的:

BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)

参数表明:

cls:被加上方法的类

name:能够领略为艺术名,这几个貌似随便起名,比如大家那边叫sayHello二

imp:实现这么些格局的函数

types:二个定义该函数重回值类型和参数类型的字符串,那么些具体会在前面讲

跟着成立EmptyClass的实例,调用sayHello二,运维,输出Hello,添加艺术成功。

吸收来说一下types参数,
譬如说我们要添加二个如此的措施:-(int)say:(NSString *)str;
相应的贯彻函数就相应是如此:

int say(id self, SEL _cmd, NSString *str) 
{ 
    NSLog(@"%@", str); 
    return 100;//随便返回个值 
 } 

class_addMethod那句就活该这么写:

1
class_addMethod([EmptyClass class], @selector(say:), (IMP)say, "i@:@");

内部types参数为”i@:@“,按梯次分别表示:

i:重返值类型int,借使v则表示void

@:参数id(self)

::SEL(_cmd)

@:id(str)

这一个代表方法都是概念好的(Type Encodings),关于Type
Encodings的别的类型定义请参见合法文书档案

最终调用say:方法:

 
int a = [instance say:@"something"]; NSLog(@"%d", a);

输出something和100。

有关本文所提到内容的详细消息请参见Objective-C Runtime
Reference

本文参考了:

推荐介绍去看望


 

Fun with Objective-C

Cool and crazy things you can do with Objective-C and the Cocoa/Cocoa
Touch frameworks.

ArchiveAsk

Search

7 October 2010 @
8:08PM

Dynamic Subclassing

 

 

If you’ve seen my github.com page or my portfolio link, you’re probably
aware of a project of mine
called CHLayoutManager.
CHLayoutManager, for those of you not in-the-know, is a way to define
the layout of a user interface on the Mac via constraints (as opposed to
autoresizing masks). For example, if you have two buttons “A” and “B”,
you can say “I want the right edge of button ‘A’ to always stay 10
points to the left of the left edge of button ‘B’”. Then, as button “B”
moves around (via autoresizing masks or positioning it
programmatically), button “A” automatically moves as well. If you do a
lot of programmatic UI layouting, this can be insanely useful. In fact,
a couple forthcoming products from Mozy will be
using CHLayoutManager in them.

Internally, there’s a singleton object called the CHLayoutManager. This
object is the one responsible for noticing when a view changes its
frame, and then also determining if any other views need to change
because of it. This layout manager also has an NSMapTable for storing
all of the constraint information related to views. The key of the map
table is the view itself, and the value is a container for storing the
constraints and the layout name. Because this is supposed to operate
silently in the background, the map table maintains a weak reference on
the view, and a strong reference to the constraint container. That means
if you’re using garbage collection and a view is deallocated, the
garbage collector will automatically clean up the entry in the map
table, and all will be well in the world.

However, if you’re not using garbage collection, some interesting
behavior can crop up. For example, let’s say the map table contains a
number of key-value pairs, and some of the keys point to views that have
been deallocated (ie, the pointers are invalid). At some point in the
future, when you attempt to add a constraint to a new view, the map
table will need to resize itself. This means that it will reorganize its
contents. Part of this step involves invoking -hash on each key.

But wait. Some of the keys are invalid pointers. If you try to send a
message to a deallocated object, you’re (almost definitely) going to
crash. Herein lies the crux of the problem: how can we ensure that each
view automatically gets cleaned up from the map table without requiring
the programmer to do it manually, and without relying on garbage
collection?

The answer: dynamic subclassing.

When the user adds a constraint to a view, the layout manager is going
to introspect this view and see if the view needs to be altered. If it
does, then the manager is going to create a new class that’s a subclass
of the view’s class. To this new class gets added a new method: a
custom -dealloc method. This method performs the cleanup of the view’s
constraints (and other layout information), then
invokes [super dealloc]. Once we’ve created this subclass, we simply
change the class of the view, and we’re good to go.

What does this look like? Like this:

- (void) dynamicallySubclassView:(NSView *)view {
  const char * prefix = "CHLayoutAutoremove_";
  Class viewClass = [view class];
  NSString * className = NSStringFromClass(viewClass);
  if (strncmp(prefix, [className UTF8String], strlen(prefix)) == 0) { return; }

  NSString * subclassName = [NSString stringWithFormat:@"%s%@", prefix, className];
  Class subclass = NSClassFromString(subclassName);

  if (subclass == nil) {
    subclass = objc_allocateClassPair(viewClass, [subclassName UTF8String], 0);
    if (subclass != nil) {
      IMP dealloc = class_getMethodImplementation([self class], @selector(dynamicDealloc));

      class_addMethod(subclass, @selector(dealloc), dealloc, "v@:");
      objc_registerClassPair(subclass);
    }
  }

  if (subclass != nil) {
    object_setClass(view, subclass);
  }
}

Here you can see what’s going on:

  1. Extract the view’s class
  2. See if the name of this class begins with the prefix used to
    indicate one of these dynamic subclasses
  3. If it doesn’t have the prefix, then build the name of the new class
    (+[NSString stringWithFormat:])
  4. Look in the runtime to see if a class of this name already exists
  5. If it doesn’t exist, create the class
    using objc_allocateClassPair()
  6. Add the custom -dealloc method to the new subclass
  7. Register the class with the runtime
  8. If everything went well, set the class of the view to the new
    subclass

So if you have an NSPopUpButton and add some constraints to it, it’s
actually going to be an CHLayoutAutoremove_NSPopUpButton.

This is, incidentally, how Key-Value Observing is implemented in Cocoa
and Cocoa Touch.

Isn’t Objective-C fun?

 

  1. 起名 24funwithobjc posted
    this

4
notes
#runtime

Short URL for this post: http://tmblr.co/Zt522y1OOOZz


 

Objective C运转时(runtime)技术的多少个要点计算

 

前言:

         Objective
C的runtime技术功用卓殊强大,能够在运转时获得并修改类的各样新闻,包涵获取格局列表、属性列表、变量列表,修章、属性,扩展方法,属性等等,本文对有关的多少个要点做了贰个总括。

目录:

(1)使用class_replaceMethod/class_addMethod函数在运行时对函数实行动态替换或追加新函数

(2)重载forwardingTargetForSelector,将不或然处理的selector转载给别的对象

(3)重载resolveInstanceMethod,从而在不能够处理有个别selector时,动态增进三个selector

(4)使用class_copyPropertyList及property_getName获取类的性质列表及种种属性的称号

  (5) 使用class_copyMethodList获取类的富有办法列表

  (6)
总结

 

(1)在运维时对函数进行动态替换 : class_replaceMethod

     
使用该函数能够在运行时动态替换有个别类的函数实现,那样做有啥用吧?最起码,能够达成类似windows上hook效果,即截获系统类的某部实例函数,然后塞壹些投机的事物进去,比如打个log什么的。

以身作则代码:

起名 25

IMP orginIMP;
NSString * MyUppercaseString(id SELF, SEL _cmd)
{
    NSLog(@"begin uppercaseString");
    NSString *str = orginIMP (SELF, _cmd);(3)
    NSLog(@"end uppercaseString");
    return str;
}
-(void)testReplaceMethod
{
      Class strcls = [NSString class];
      SEL  oriUppercaseString = @selector(uppercaseString);
      orginIMP = [NSStringinstanceMethodForSelector:oriUppercaseString];  (1)  
      IMP imp2 = class_replaceMethod(strcls,oriUppercaseString,(IMP)MyUppercaseString,NULL);(2)
      NSString *s = "hello world";
      NSLog(@"%@",[s uppercaseString]];
}

起名 26

实施结果为:

begin uppercaseString

end uppercaseString

HELLO WORLD

那段代码的效应正是

(壹)获得uppercaseString那几个函数的函数指针存到变量orginIMP中

(二)将NSString类中的uppercaseString函数的兑现替换为协调定义的MyUppercaseString

(3)在MyUppercaseString中,先进行了协调的log代码,然后再调用在此以前封存的uppercaseString的系列贯彻,那样就在系统函数执行在此以前参与本身的事物,前面每一次对NSString调用uppercaseString的时候,都会打印出log来

 与class_replaceMethod相仿,class_addMethod能够在运作时为类增添3个函数。

(二)当有个别对象不可能经受有个别selector时,将对该selector的调用转载给另叁个目的:- (id)forwardingTargetForSelector:(SEL)aSelector

   
 forwardingTargetForSelector是NSObject的函数,用户能够在派生类中对其重载,从而将不能够处理的selector转载给另2个对象。照旧以上边的uppercaseString为例,假诺用户本身定义的CA类的靶子a,未有uppercaseString那样多个实例函数,那么在不调用respondSelector的气象下,直接实施[a
performSelector:@selector”uppercaseString”],那么执行时肯定会crash,此时,假若CA完成了forwardingTargetForSelector函数,并重临2个NSString对象,那么就绝对于对该NSString对象执行了uppercaseString函数,此时就不会crash了。当然达成那几个函数的目标并不仅是为着程序不crash那么简单,在促成装饰者方式时,也得以采用该函数举行新闻转发。

以身作则代码:

起名 27

 1 @interface CA : NSObject
 3 -(void)f;
 4 
 5 @end
 6 
 7 @implementation CA
 8 
 9 - (id)forwardingTargetForSelector:(SEL)aSelector
11 {
13     if (aSelector == @selector(uppercaseString))
15     {
17         return@"hello world";
19     }
21 }

起名 28

 

测试代码:

CA *a = [CA new];

 NSString * s = [a performSelector:@selector(uppercaseString)];

NSLog(@"%@",s);

 

测试代码的出口为:HELLO WO猎豹CS陆LD 

 ps:那里有个难点,CA类的靶子不能够接到@selector(uppercaseString),那么壹旦自身在forwardingTargetForSelector函数中用class_addMethod给CA类扩展3个uppercaseString函数,然后回到self,可行呢?经过试验,那样会crash,此时CA类其实已经有了uppercaseString函数,不过不了然干什么不可能调用,就算那时候new贰个CA类的靶子,并回到,是能够成功的。

(叁)当有个别对象不可能接受有个别selector时,向目的所属的类动态添加所需的selector

+ (BOOL) resolveInstanceMethod:(SEL)aSEL 

   
 那个函数与forwardingTargetForSelector类似,都会在目的不可能承受某个selector时接触,执行起来略大有差异。前者的目标关键在于给客户多个机遇来向该对象添加所需的selector,后者的意在允许用户将selector转载给另一个目的。其余触发时机也互不相同,该函数是个类函数,在先后刚运营,界面尚未彰显出时,就会被调用。

     在类不可能处理有个别selector的动静下,假如类重载了该函数,并选取class_addMethod添加了相应的selector,并重回YES,那么后边forwardingTargetForSelector就不会被调用,固然在该函数中尚无拉长相应的selector,那么不论是重临什么,前面都会持续调用forwardingTargetForSelector,假如在forwardingTargetForSelector并未有重回能承受该selector的指标,那么resolveInstanceMethod会再一次被触发,那3次,假设如故不添加selector,程序就会报相当

起名 29

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
代码示例一:
 
 @implementation CA
 void dynamicMethodIMP(id selfSEL _cmd)
 5 {   
 7      printf("SEL %s did not exist\n",sel_getName(_cmd));
 9 }
10
11 + (BOOL) resolveInstanceMethod:(SEL)aSEL
13 {
15     if (aSEL == @selector(t))
17     {
19         class_addMethod([selfclass], aSEL, (IMP) dynamicMethodIMP, "v@:");
21         return YES;
23     }
25     return [superresolveInstanceMethod:aSEL];
27 }
28
29 @end
  
 
测试代码:
 
  CA * ca = [CA new]
 
  [ca performSelector:@selector(t)]; 

起名 30

  

 

实施结果

   SEL t did not exist

 

起名 31

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
示例代码二:
 
@implementation CA
 
void dynamicMethodIMP(id selfSEL _cmd)
{
    printf("SEL %s did not exist\n",sel_getName(_cmd));
}
 
+ (BOOL) resolveInstanceMethod:(SEL)aSEL
{
    return  YES;
}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
    if (aSelector == @selector(uppercaseString))
    {
        return @"hello world";
    }
}
测试代码 :
 
 a = [[CA alloc]init];
 NSLog(@"%@",[a performSelector:@selector(uppercaseString)];

起名 32

  

该测试代码的输出为:HELLO WOLX570LD 

对于该测试代码,由于a未有uppercaseString函数,因而会触发resolveInstanceMethod,然而由于该函数并从未添加selector,因而运维时意识找不到该函数,会接触

forwardingTargetForSelector函数,在forwardingTargetForSelector函数中,重临了二个NSString “hello
world”,由此会由该string来实施uppercaseString函数,最终回到大写的hello
world。

 

起名 33

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
示例代码三:
 
@implementation CA
 
+ (BOOL) resolveInstanceMethod:(SEL)aSEL
{
    return  YES;
}
- (id)forwardingTargetForSelector:(SEL)aSelector
{
    return nil;
  }
 测试代码:
 
1  a = [[CA alloc]init];
2  NSLog(@"%@",[a performSelector:@selector(uppercaseString)];

  

起名 34

  

这段代码的执行各类为:

 (1):首先在程序刚实施,AppDelegate都还未曾出去时,resolveInstanceMethod就被触发,

起名 35

 

(二)等测试代码执行时,forwardingTargetForSelector被调用

起名 36

(三)由于forwardingTargetForSelector重回了nil,因而运行时照旧找不到uppercaseString
selector,这时又会触发resolveInstanceMethod,由于依旧不曾进入selector,于是会crash。

起名 37

 

(4)
使用class_copyPropertyList及property_getName获取类的质量列表及各样属性的称谓

  

起名 38

u_int               count;
objc_property_t*    properties= class_copyPropertyList([UIView class], &count);
for (int i = 0; i < count ; i++)
{
    const char* propertyName = property_getName(properties[i]);
    NSString *strName = [NSString  stringWithCString:propertyName encoding:NSUTF8StringEncoding];
    NSLog(@"%@",strName);
}

起名 39

 以上代码获取了UIView的有所属性并打字与印刷属性名称, 输出结果为:

起名 40

skipsSubviewEnumeration
viewTraversalMark
viewDelegate
monitorsSubtree
backgroundColorSystemColorName
gesturesEnabled
deliversTouchesForGesturesToSuperview
userInteractionEnabled
tag
layer
_boundsWidthVariable
_boundsHeightVariable
_minXVariable
_minYVariable
_internalConstraints
_dependentConstraints
_constraintsExceptingSubviewAutoresizingConstraints
_shouldArchiveUIAppearanceTags

起名 41

 

 

(5) 使用class_copyMethodList获取类的拥有办法列表

   
获取到的数目是3个Method数组,Method数据结构中包括了函数的称呼、参数、再次来到值等消息,以下代码以博得名为例:

起名 42

u_int               count;
Method*    methods= class_copyMethodList([UIView class], &count);
for (int i = 0; i < count ; i++)
{
    SEL name = method_getName(methods[i]);
    NSString *strName = [NSString  stringWithCString:sel_getName(name) encoding:NSUTF8StringEncoding];
    NSLog(@"%@",strName);
}

起名 43

  代码执行后将输出UIView全数函数的名号,具体结果略。

     别的1些辅车相依函数:

起名,    

起名 44

1.SEL method_getName(Method m) 由Method得到SEL
2.IMP method_getImplementation(Method m)  由Method得到IMP函数指针
3.const char *method_getTypeEncoding(Method m)  由Method得到类型编码信息
4.unsigned int method_getNumberOfArguments(Method m)获取参数个数
5.char *method_copyReturnType(Method m)  得到返回值类型名称
6.IMP method_setImplementation(Method m, IMP imp)  为该方法设置一个新的实现

起名 45

 

(6)总结

       简单的说,使用runtime技术能做些什么业务呢?

     
 能够在运维时,在不继续也不category的状态下,为各档次(包罗系统的类)做过多操作,具体包涵:

  •    增加
增加函数:class_addMethod
增加实例变量:class_addIvar
增加属性:@dynamic标签,或者class_addMethod,因为属性其实就是由getter和setter函数组成
增加Protocol:class_addProtocol (说实话我真不知道动态增加一个protocol有什么用,-_-!!)
  •    获取  
获取函数列表及每个函数的信息(函数指针、函数名等等):class_getClassMethod method_getName ...
获取属性列表及每个属性的信息:class_copyPropertyList property_getName
获取类本身的信息,如类名等:class_getName class_getInstanceSize
获取变量列表及变量信息:class_copyIvarList
获取变量的值
  •    替换
将实例替换成另一个类:object_setClass
将函数替换成一个函数实现:class_replaceMethod
直接通过char *格式的名称来修改变量的值,而不是通过变量

  

    

   参考资料:(壹)Objective-C Runtime
Reference

             
 (2)深远浅出Cocoa之新闻   

               (3)objective-c 编程计算(第肆篇)运转时操作 –
方法调换

                (4)Runtime of
Objective-C

 

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图