執行時(runtime)-方法交換
1> 建立一個 Person 類,並定義兩個方法 study 和 run,分別實現
#import "Person.h"
@implementation Person
- (void)study {
NSLog(@"study");
}
- (void)run {
NSLog(@"run");
}
@end
2> 正常呼叫方法
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc] init];
[p study];
[p run];
}
執行程式,結果如下:
3> 交換方法實現
int main(int argc, const char * argv[]) {
@autoreleasepool {
Person *p = [[Person alloc] init];
[p study];
[p run];
// 交換方法實現
Method m1 = class_getInstanceMethod(objc_getClass("Person"), @selector(study));
Method m2 = class_getInstanceMethod(objc_getClass("Person" ), @selector(run));
method_exchangeImplementations(m1, m2);
[p study];
[p run];
}
return 0;
}
執行程式,結果如下:
由執行結果可知:study 方法和 run 方法的實現的確被交換了。
4. 交換系統自帶的方法
在實際開發中,交換方法最大的應用場景是`替換系統自帶的方法。
4.1 舉例分析
舉個例子:從iOS6到iOS7,蘋果的介面風格由 ‘擬物化’ 轉變為 ‘扁平化’。
‘怎麼快速適配?’
1> 設定圖片是通過系統的 imageNamed 方法來實現的。
2> 如果要進行iOS7之後版本的適配,首先需要平面設計師做出一套扁平化的圖片,然後對系統版本(systemVersion)進行判斷: 大於7.0就是用扁平化圖片。
3> 如果專案中很多地方都有設定圖片的程式碼,就要在每一處都新增判斷系統版本的程式碼,工作量十分龐大,很不現實。這個時候,就可以考慮使用執行時交換方法來解決問題。
‘解決思路’
1> 假設舊圖片的圖片名為 ‘xxx.png’,可以讓平面設計師將新圖片的圖片名命名為’xxx_ios7.png’
2> 自定義一個 ‘xfq_imageNamed’ 方法,在該方法中進行系統版本判斷,如果大於7.0就使用’xxx_ios7.png’的圖片。
3> 交換自定義的 ‘xfq_imageNamed’ 方法 和 系統的 ‘imageNamed’ 方法的實現
4.2 程式碼實現
1> 自定義 UIImage+Extension 分類
UIImage+Extension.m
#import "UIImage+Extension.h"
#import <objc/runtime.h>
@implementation UIImage (Extension)
/**
當某個類或者分類載入到記憶體的時候,會呼叫1次
*/
+ (void)load {
Method m1 = class_getClassMethod(objc_getClass("UIImage"), @selector(imageNamed:));
Method m2 = class_getClassMethod(objc_getClass("UIImage"), @selector(xfq_imageNamed:));
method_exchangeImplementations(m1, m2);
}
+ (UIImage *)xfq_imageNamed:(NSString *)name {
// 獲取當前裝置的系統版本號
float version = [[UIDevice currentDevice].systemVersion floatValue];
// 判斷版本號,如果 >= 7.0,在圖片名後面拼接 "_ios7"
if (version >= 7.0) {
name = [name stringByAppendingString:@"_ios7"];
}
// 這裡需要特別注意: return的時候,使用的是自定義的方法,這個時候由於已經交換了方法,實際上呼叫的是系統的imageNamed方法'
return [UIImage xfq_imageNamed:name];
}
// 注意: 在分類中重寫系統方法,不能滿足要求
// 這種方式會導致系統原來的方法無法使用
//+ (UIImage *)imageNamed:(NSString *)name {
//
// float version = [[UIDevice currentDevice].systemVersion floatValue];
// if (version >= 7.0) {
// name = [name stringByAppendingString:@"_ios7"];
// }
// // 會死迴圈
// return [self imageNamed:name];
//}
@end
2> 控制器中呼叫
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIImageView *imageView;
@end
@implementation ViewController
/**
iOS6 -> iOS7
擬物化 -> 扁平化
*/
- (void)viewDidLoad {
[super viewDidLoad];
// 正是因為交換了方法的實現,所以這裡的程式碼不用做任何修改,就可以實現想要的效果
self.imageView.image = [UIImage imageNamed:@"open"];
}
@end
相關推薦
執行時(runtime)-方法交換
1> 建立一個 Person 類,並定義兩個方法 study 和 run,分別實現 #import "Person.h" @implementation Person - (void)study { NSLog(@"study"); } -
Objective C執行時(runtime)
前言: Objective C的runtime技術功能非常強大,能夠在執行時獲取並修改類的各種資訊,包括獲取方法列表、屬性列表、變數列表,修改方法、屬性,增加方法,屬性等等,本文對相關的幾個要點做了一個小結。 目錄: (6) 總結 (1)在執行時對函式進行動態替換 :
Objective C執行時(runtime)技術的幾個要點總結
前言: Objective C的runtime技術功能非常強大,能夠在執行時獲取並修改類的各種資訊,包括獲取方法列表、屬性列表、變數列表,修改方法、屬性,增加方法,屬性等等,本文對相關的幾個要點做了一個小結。 目錄: (6) 總結 (1)在執行時對函式進行動態替換 : cl
Java 執行時(RUNTIME)註解詳解
整理測試後並附上完整程式碼 註解定義 註解(Annotation),也叫元資料。一種程式碼級別的說明。它是JDK1.5及以後版本引入的一個特性,與類、介面、列舉是在同一個層次。它可以宣告在包、類、欄位、方法、區域性變數、方法引數等的前面,用來對這些元
iOS執行時(runtime)探究一:重要概念
iOS執行時簡介 因為Objc是一門動態語言,所以它總是想辦法把一些決定工作從編譯連線推遲到執行時。也就是說只有編譯器是不夠的,還需要一個執行時系統 (runtime system) 來執行編譯後的程式碼。這就是 Objective-C Runtime 系統存
Go 運行時(runtime)
垃圾 .com map cgo 一個 也不會 bsp 部分 targe 盡管 Go 編譯器產生的是本地可執行代碼,這些代碼仍舊運行在 Go 的 runtime(這部分的代碼可以在 runtime 包中找到)當中。這個 runtime 類似 Java 和 .NET 語言所用到
Kubernetes容器執行時(CRI)簡介
Kubernetes節點的底層由一個叫做“容器執行時”的軟體進行支撐,它負責比如啟停容器這樣的事情。最廣為人知的容器執行時當屬Docker,但它不是唯一的。事實上,容器執行時這個領域發展迅速。為了使Kubernetes的擴充套件變得更容易,我們一直在打磨支援容器
iOS學習筆記56(Runtime)-Objective-C Runtime 執行時之三:方法與訊息
前面我們討論了Runtime中對類和物件的處理,及對成員變數與屬性的處理。這一章,我們就要開始討論Runtime中最有意思的一部分:訊息處理機制。我們將詳細討論訊息的傳送及訊息的轉發。不過在討論訊息之前,我們先來了解一下與方法相關的一些內容。 基礎資料型別 SEL
執行時許可權的處理方法(以打電話為例 Api 23,24)
Android中危險許可權共9組24個許可權 group:android.permission-group.CONTACTS permission:android.permission.WRITE_CONTACTS permission:android
剖析執行時(讓你看懂執行時)
init ont get tle pre art details ddc down 執行時機制:比較高級的特性,純C語言 實際上我們平時寫的OC代碼。都是轉成C語言的執行時代碼,執行時代碼的效率更高,更直接 Person.h @inter
一個類,有新增元素(add)和獲取元素數量(size)方法。 啟動兩個線程。線程1向容器中新增數據。線程2監聽容器元素數量,當容器元素數量為5時,線程2輸出信息並終止
override tac trace add syn countdown print import 數據 方式一: /** * 兩個線程要是可見的所以要加上votalile */public class Test_01 { public static void
Java多執行緒(四)java中的Sleep方法
點我跳過黑哥的卑鄙廣告行為,進入正文。 Java多執行緒系列更新中~ 正式篇: Java多執行緒(一) 什麼是執行緒 Java多執行緒(二)關於多執行緒的CPU密集型和IO密集型這件事 Java多執行緒(三)如何建立執行緒 Java多執行緒(四)java中的Sleep方法
Web應用啟動時,後臺自動啟動一個執行緒(轉)
原文:http://blog.sina.com.cn/s/blog_6810dfc20101ipzq.html Web應用啟動時,後臺自動啟動一個執行緒 (1)前言 前幾天,manager問道一個問題:能不能實現類似於cro
java day25 多執行緒(下) 單例類(Runtime,Timer
25.01_多執行緒(單例設計模式)(掌握) 單例設計模式:保證類在記憶體中只有一個物件。 如何保證類在記憶體中只有一個物件呢? (1)控制類的建立,不讓其他類來建立本類的物件。private (2)在本類中定義一個本類的物件。Singl
執行緒(九)join方法的簡單介紹:
1、join方法的實現原理: join方法原理就是利用執行緒的wait方法等待操作: A執行緒中呼叫了B執行緒的join方法,則相當於在A執行緒中呼叫了B執行緒的wait方法,當B執行緒執行完(或者
Java 多執行緒(三)—— 執行緒的生命週期及方法
這篇部落格介紹執行緒的生命週期。 執行緒是一個動態執行的過程,它也有從建立到死亡的過程。 執行緒的幾種狀態 在 Thread 類中,有一個列舉內部類: 上面的資訊以圖片表示如下: 第一張圖: 第二張圖:把等待、計時等待、阻塞看成阻塞一個狀態了 1、新建狀態(ne
多執行緒——停止執行緒(結束run方法)
package com.qianfeng.demo01; /** * 停止執行緒: * 1.stop():已過時,這種方法有固有的不安全性,強制停止執行緒,不論處於什麼狀態都會停止,就會導致執行緒
Unity在執行時(程式碼中)設定材質的渲染模式(RenderingMode)
public enum RenderingMode { Opaque, Cutout, Fade, Transparent, } public static void SetMaterialRenderingMode (Material material, Render
[面試] C/C++ 語法(六)—— RTTI(執行時型別資訊)
RTTI(RunTime Type Information),顧名思義,物件執行時型別資訊,以便在執行時進行型別識別。 C++ 的物件識別可通過以下三個技術得以實現: (1)dynamic_cast 運算子(型別安全的向下轉型) 向下轉型是不安全的,多型
Objective-C Runtime 執行時之三:方法與訊息
前面我們討論了Runtime中對類和物件的處理,及對成員變數與屬性的處理。這一章,我們就要開始討論Runtime中最有意思的一部分:訊息處理機制。我們將詳細討論訊息的傳送及訊息的轉發。不過在討論訊息之前,我們先來了解一下與方法相關的一些內容。 基礎資料型別 SEL