欧美三级国产三级日韩三级_亚洲熟妇丰满大屁股熟妇_欧美亚洲成人一区二区三区_国产精品久久久久久模特

Objective - 新聞資訊 - 云南小程序開發(fā)|云南軟件開發(fā)|云南網(wǎng)站建設-昆明葵宇信息科技有限公司

159-8711-8523

云南網(wǎng)建設/小程序開發(fā)/軟件開發(fā)

知識

不管是網(wǎng)站,軟件還是小程序,都要直接或間接能為您產(chǎn)生價值,我們在追求其視覺表現(xiàn)的同時,更側重于功能的便捷,營銷的便利,運營的高效,讓網(wǎng)站成為營銷工具,讓軟件能切實提升企業(yè)內(nèi)部管理水平和效率。優(yōu)秀的程序為后期升級提供便捷的支持!

您當前位置>首頁 » 新聞資訊 » 技術分享 >

Objective

發(fā)表時間:2020-10-19

發(fā)布人:葵宇科技

瀏覽次數(shù):41


以前的幾年中出現(xiàn)了大年夜量的Objective-C開辟者。有些是大年夜動態(tài)說話轉過來的,比如Ruby或Python,有些是大年夜強類型說話轉過來的,如Java或C#,當然也有直接以Objective-C作為入門說話的。也就是說有很大年夜一部分開辟者都沒有應用Objective-C太長時光。當你接觸一門新說話時,更多地會存眷基本常識,如語法和特點等。但平日有一些更高等的,更鮮為人知又有強大年夜功能的特點等待你去開辟。
The Runtime
Objective-C是一門簡單的說話,95%是C。只是在說話層面上加了些關鍵字和語法。真正讓Objective-C如斯強大年夜的是它的運行時。它很小但卻很強大年夜。它的核心是消息分發(fā)。
 
Messages
如不雅你是大年夜動態(tài)說話如Ruby或Python轉過來的,可能知道什么是消息,可以直接跳過進入下一節(jié)。那些大年夜其他說話轉過來的,持續(xù)看。
履行一個辦法,有些說話,編譯器會履行一些額外的優(yōu)化和缺點檢查,因為調(diào)用關系很直接也很明顯。但對于消息分發(fā)來說,就不那么明顯了。在發(fā)消息前不必知道某個對象是否可以或許處理消息。你把消息發(fā)給它,它可能會處理,也可能轉給其他的Object來處理。一個消息不必對應一個辦法,一個對象可能實現(xiàn)一個辦法來處理多條消息。
在Objective-C中,消息是經(jīng)由過程objc_msgSend()這個runtime辦法及鄰近的辦法來實現(xiàn)的。這個辦法須要一個target,selector,還有一些參數(shù)。理論上來說,編譯器只是把消息分發(fā)變成objc_msgSend來履行。比如下面這兩行代碼是等價的。
 
[array insertObject:foo atIndex:5];
objc_msgSend(array, @selector(insertObject:atIndex:), foo, 5);

大年夜多半面向?qū)ο蟮恼f話里有 classes 和 objects 的概念。Objects經(jīng)由過程Classes生成。然則在Objective-C中,classes本身也是objects(譯者注:這點跟python很像),也可以處理消息,這也是為什么會有類辦法和實例辦法。具體來說,Objective-C中的Object是一個構造體(struct),第一個成員是isa,指向本身的class。這是在objc/objc.h中定義的。
 
typedef struct objc_object {
    Class isa;
} *id;

object的class保存了辦法列表,還有指向父類的指針。但classes也是objects,也會有isa變量,那么它又指向哪兒呢?這里就引出了第三個類型: metaclasses。一個 metaclass被指向class,class被指向object。它保存了所有實現(xiàn)的辦法列表,以及父類的metaclass。如不雅想更清跋扈地懂得objects,classes以及metaclasses是若何一路工作地,可以瀏覽這篇文┞仿。
 
Methods, Selectors and IMPs
我們知道了運行時會發(fā)消息給對象。我們也知道一個對象的class保存了辦法列表。那么這些消息是若何映射到辦法的,這些辦法又是若何被履行的呢?
第一個問題的謎底很簡單。class的辦法列表其實是一個字典,key為selectors,IMPs為value。一個IMP是指向辦法在內(nèi)存中的實現(xiàn)。很重要的一點是,selector和IMP之間的關系是在運行時才決定的,而不是編譯時。如許我們就能玩出些花樣。
IMP平日是指向辦法的指針,第一個參數(shù)是self,類型為id,第二個參數(shù)是_cmd,類型為SEL,余下的是辦法的參數(shù)。這也是self和_cmd被定義的處所。下面演示了Method和IMP
- (id)doSomethingWithInt:(int)aInt{}
 
id doSomethingWithInt(id self, SEL _cmd, int aInt){}

其他運行時的辦法
 
如今我們知道了objects,classes,selectors,IMPs以及消息分發(fā),那么運行時到底能做什么呢?重要有兩個感化:
1.創(chuàng)建、修改、自省classes和objects
2.消息分發(fā)
之前已經(jīng)提過消息分發(fā),不過這只是一小部分功能。所有的運行時辦法都有特定的前綴。下面是一些有意思的辦法:
 
class
class開首的辦法是用來修改和自省classes。辦法如 class_addIvar、class_addMethod、 class_addProperty和class_addProtocol 許可重建classes。
 
class_copyIvarList、class_copyMethodList、class_copyProtocolList和class_copyPropertyList能拿到一個class的所有內(nèi)容。而class_getClassMethod、class_getClassVariable、 class_getInstanceMethod, class_getInstanceVariable、class_getMethodImplementation 和 class_getProperty 返回單個內(nèi)容。
 
也有一些通用的自省辦法,如class_conformsToProtocol、class_respondsToSelector、 class_getSuperclass。最后,你可以應用class_createInstance來創(chuàng)建一個object。
 
ivar
這些辦法能讓你獲得名字,內(nèi)存地址和Objective-C type encoding。
 
method
這些辦法重要用來自省,比如method_getName, method_getImplementation, method_getReturnType等等。也有一些修改的辦法,包含method_setImplementation和method_exchangeImplementations,這些我們后面會講到。
 
objc
一旦拿到了object,你就可以對它做一些自省和修改。你可以get/set ivar, 應用object_copy和object_dispose來copy和free object的內(nèi)存。最NB的不僅是拿到一個class,而是可以應用object_setClass來改變一個object的class。待會就能看到應用處景。
 
property
屬性保存了很大年夜一部分信息。除了拿到名字,你還可以應用property_getAttributes來發(fā)明property的更多信息,如返回值、是否為atomic、getter/setter名字、是否為dynamic、背后應用的ivar名字、是否為弱引用。
 
protocol
Protocols有點像classes,然則精簡版的,運行時的辦法是一樣的。你可以獲取method, property, protocol列表, 檢查是否實現(xiàn)了其他的protocol。
 
sel
最后我們有一些辦法可以處理 selectors,比如獲取名字,注冊一個selector等等。
 
如今我們對Objective-C的運行時有了大年夜概的懂得,來看看它們能做哪些有趣的工作。
 
Classes And Selectors From Strings
 
比較基本的一個動態(tài)特點是經(jīng)由過程String來生成Classes和Selectors。Cocoa供給了NSClassFromString和NSSelectorFromString辦法,應用起來很簡單:
Class stringclass = NSClassFromString(@"NSString");

于是我們就獲得了一個string class。接下來:
 
NSString *myString = [stringclass stringWithString:@"Hello World"];

為什么要這么做呢?直接應用Class不是更便利?平日情況下是,但有些場景下這個辦法會很有效。起首,可以得知是否存在某個class,NSClassFromString 會返回nil,如不雅運行時不存在該class的話。比如可以檢查NSClassFromString(@"NSRegularExpression")是否為nil來斷定是否為iOS4.0+。
 
另一個應用處景是根據(jù)不合的輸入返回不合的class或method。比如你在解析一些數(shù)據(jù),每個數(shù)據(jù)項都有要解析的字符串以及自身的類型(String,Number,Array)。你可以在一個辦法里搞定則些,也可以應用多個辦法。個一一個辦法是獲取type,然后應用if來調(diào)用匹配的辦法。另一種是根據(jù)type來生成一個selector,然后調(diào)用之。以下是兩種實現(xiàn)方法:
 
- (void)par搜刮引擎優(yōu)化bject:(id)object {
    for (id data in object) {
        if ([[data type] isEqualToString:@"String"]) {
            [self parseString:[data value]]; 
        } else if ([[data type] isEqualToString:@"Number"]) {
            [self parseNumber:[data value]];
        } else if ([[data type] isEqualToString:@"Array"]) {
            [self parseArray:[data value]];
        }
    }
}
- (void)par搜刮引擎優(yōu)化bjectDynamic:(id)object {
    for (id data in object) {
        [self performSelector:NSSelectorFromString([NSString stringWithFormat:@"parse%@:", [data type]]) withObject:[data value]];
    }
}
- (void)parseString:(NSString *)aString {}
- (void)parseNumber:(NSString *)aNumber {}
- (void)parseArray:(NSString *)aArray {}

可一看到,你可以把7行帶if的代碼變成1行。將來如不雅有新的類型,只需增長實現(xiàn)辦法即可,而不消再去添加新的 else if。
 
Method Swizzling
 
之前我們講過,辦法由兩個部分構成。Selector相當于一個辦法的id;IMP是辦法的實現(xiàn)。如許分開的一個便利之處是selector和IMP之間的對應關系可以被改變。比如一個 IMP 可以有多個 selectors 指向它。
 
而 Method Swizzling 可以交換兩個辦法的實現(xiàn)?;蛟S你會問“什么情況下會須要這個呢?”。我們先來看下Objective-C中,兩種擴大class的門路。起首是 subclassing。你可以重寫某個辦法,調(diào)用父類的實現(xiàn),這也意味著你必須應用這個subclass的實例,但如不雅持續(xù)了某個Cocoa class,而Cocoa又返回了本來的class(比如 NSArray)。這種情況下,你會想添加一個辦法到NSArray,也就是應用Category。99%的情況下這是OK的,但如不雅你重寫了某個辦法,就沒有機會再調(diào)用本來的實現(xiàn)了。
 
Method Swizzling 可以搞定則個問題。你可以重寫某個辦法而不消持續(xù),同時還可聲調(diào)用本來的實現(xiàn)。平日的做法是在category中添加一個辦法(當然也可所以一個全新的class)??梢越?jīng)由過程method_exchangeImplementations這個運行時辦法來交換實現(xiàn)。來看一個demo,這個demo演示了若何重寫addObject:辦法來記載每一個新添加的對象。
#import  <objc/runtime.h>
 
@interface NSMutableArray (LoggingAddObject)
- (void)logAddObject:(id)aObject;
@end
 
@implementation NSMutableArray (LoggingAddObject)
 
+ (void)load {
    Method addobject = class_getInstanceMethod(self, @selector(addObject:));
    Method logAddobject = class_getInstanceMethod(self, @selector(logAddObject:));
    method_exchangeImplementations(addObject, logAddObject);
}
 
- (void)logAddObject:(id)aobject {
    [self logAddObject:aObject];
    NSLog(@"Added object %@ to array %@", aObject, self);
}
 
@end

我們把辦法交換放到了load中,這個辦法只會被調(diào)用一次,并且是運行時載入。如不雅指向臨時用一下,可以放到其余處所。留意到一個很明顯的遞歸調(diào)用logAddObject:。這也是Method Swizzling輕易把我們搞混的處所,因為我們已經(jīng)交換了辦法的實現(xiàn),所以其實調(diào)用的是addObject:
 [img]http://img.blog.csdn.net/20150104185959656
動態(tài)持續(xù)、交換
我們可以在運行時創(chuàng)建新的class,這個特點用得不多,但其實它照樣很強大年夜的。你能經(jīng)由過程它創(chuàng)建新的子類,并添加新的辦法。
但如許的一個子類有什么竽暌姑呢?別忘了Objective-C的一個關鍵點:object內(nèi)部有一個叫做isa的變量指向它的class。這個變量可以被改變,而不須要從新創(chuàng)建。然后就可以添加新的ivar和辦法了。可以經(jīng)由過程以下敕令來修改一個object的class
object_setClass(myObject, [MySubclass class]);

這可以用在Key Value Observing。當你開端observing an object時,Cocoa會創(chuàng)建這個object的class的subclass,然后將這個object的isa指向新創(chuàng)建的subclass。點擊這里查看更具體的解釋。
 
動態(tài)辦法處理
今朝為止,我們評論辯論了辦法交換,以及已有辦法的處理。那么當你發(fā)送了一個object無法處理的消息時會產(chǎn)生什么呢?很明顯,”it breaks”。大年夜多半情況下確切如斯,但Cocoa和runtime也供給了一些應對辦法。
起首是動態(tài)辦法處理。平日來說,處理一個辦法,運行時尋找匹配的selector然后履行之。有時,你只想在運行時才創(chuàng)建某個辦法,比如有些信息只有在運行時才能獲得。要實現(xiàn)這個效不雅,你須要重寫+resolveInstanceMethod:和/或 +resolveClassMethod:。如不雅確實袈漩加了一個辦法,記得返回YES。
+ (BOOL)resolveInstanceMethod:(SEL)aSelector {
    if (aSelector == @selector(myDynamicMethod)) {
        class_addMethod(self, aSelector, (IMP)myDynamicIMP, "v@:");
        return YES;
    }
    return [super resolveInstanceMethod:aSelector];
}

那Cocoa在什么場景下會應用這些辦法呢?Core Data用得很多。NSManagedObjects有很多在運行時添加的屬性用來處理get/set屬性和關系。那如不雅Model在運行時被改變了呢?
 
消息轉發(fā)
如不雅 resolve method 返回NO,運行時就進入下一步調(diào):消息轉發(fā)。有兩種常見用例。1) 將消息轉發(fā)到另一個可以處理該消息的object。2) 將多個消息轉發(fā)到同一個辦法。
消息轉發(fā)分兩步。起首,運行時調(diào)用-forwardingTargetForSelector:,如不雅只是想把消息發(fā)送到另一個object,那么就應用這個辦法,因為更高效。如不雅想要修改消息,那么就要應用-forwardInvocation:,運行時將消息打包成NSInvocation,然后返回給你處理。處理完之后,調(diào)用invokeWithTarget:。
Cocoa有幾處處所用到了消息轉發(fā),重要的兩個處所是代勞(Proxies)和響應鏈(Responder Chain)。NSProxy是一個輕量級的class,它的感化就是轉發(fā)消息到另一個object。如不雅想要惰性加載object的某個屬性會很有效。NSUndoManager也有效到,不過是朝長進步消息,之后再履行,而不是轉發(fā)到其他的處所。
響應鏈是關于Cocoa若何處理與發(fā)送事宜與行動到對應的對象。比如說,應用Cmd+C履行了copy敕令,會發(fā)送-copy:到響應鏈。起首是First Responder,平日是當前的UI。如不雅沒有處理該消息,則轉發(fā)到下一-nextResponder。這么一向下去直到找到可以或許處理該消息的object,或者沒有找到,報錯。
 
應用Block作為Method IMP
iOS 4.3帶來了很多新的runtime辦法。除了對properties和protocols的加強,還帶老鏖新的以 imp 開首的辦法。平日一個 IMP 是一個指向辦法實現(xiàn)的指針,頭兩個參數(shù)為 object(self)和selector(_cmd)。iOS 4.0和Mac OS X 10.6 帶來了block,imp_implementationWithBlock() 能讓我們應用block作為 IMP,下面這個代碼片段展示了若何應用block來添加新的辦法。
IMP myIMP = imp_implementationWithBlock(^(id _self, NSString *string) {
    NSLog(@"Hello %@", string);
});
class_addMethod([MYclass class], @selector(sayHello:), myIMP, "v@:@");

如不雅想知道這是若何實現(xiàn)的,可以查看這篇文┞仿
 
可以看到,Objective-C 外面看起來挺簡單,但照樣很靈活的,可以帶來很多可能性。動態(tài)說話的優(yōu)勢在于在不擴大說話本身的情況下做很多很靈活的工作。比如Key Value Observing,供給了優(yōu)雅的API可以與已有的代碼無縫結合,而不須要新增說話級其余特點。我們知道,Objective-C開辟iOS app,不得不質(zhì)疑的是app安然,關于iOS app安然若何進行保護,可以點擊這里查看
 

相關案例查看更多