runtime獲取屬性列表,修改屬性值,新增並修改私有方法的呼叫
用了兩天好好的研究了一下runtime,之前初涉runtime。懵懵懂懂的瞭解runtime的強大,但是如何的強大,只是在demo中引用MJExtension的時候自動生成model,瞭解了一些。
經過一天半的研究,首先溫習了之前的獲取屬性列表。
今天想說的具體功能如題所述。主要涉及的就是獲取並修改屬性。新增並修改私有方法。
好了,首先說一下如何獲取屬性值。如果需要獲取某個屬性,我們最先需要知道你想獲取的類的名字。如果我們只有某一個類的字串,同樣可以達到目的,這也就是runtime的神奇之處。
(1)例如我們想要得到UserInfo這個類下的所有屬性。但是現在只有字串[email protected]
,我們可以用最常見的runtime語句去獲取到class。如下:Class UserInfo = NSClassFromString(className);
這時候我們就得到了這個類。但是這時的UserInfo相當於沒有alloc的類。
(2)我們在網上有兩種方式可以獲取到屬性的name,type以及value。第一種方式如下:
- (NSArray*)getAllPropertyName//runtime獲取model所有屬性
{
NSMutableArray* nameArray = [NSMutableArray array];
unsigned int count = 0;
objc_property_t *property_t = class_copyPropertyList([UserInfo class], &count);
for (int i=0; i<count; i++) {
objc_property_t propert = property_t[i];
const char * propertyName = property_getName(propert);
[nameArray addObject:[NSString stringWithUTF8String:propertyName]];
}
free(property_t);
return nameArray;
}
上面只是獲取到屬性名,如果想要獲取其它的東西,也可以自行查詢方法。不過目前只有這個有點用。
第二種方法如下:
unsigned int countNum = 0;
Ivar *members = class_copyIvarList([self.panoramView class], &countNum);
for (int i=0; i<countNum; i++) {
Ivar var = members[i];
const char *memberName = ivar_getName(var);
//屬性描述
NSString *memberStr = [NSString stringWithFormat:@"%s",memberName];
if ([memberStr isEqualToString:@"_advsObject"]) {
const char * type = ivar_getTypeEncoding(var);
}
}
上面的方法獲取到的屬性是C的格式,需要轉變成OC,所以中間寫了一個memberStr作為媒介。
以上就是獲取屬性的方法,下面說下如何修改屬性內容。
(3)其實修改屬性的方法,很簡單,就一句話,一共有三個引數。object_setIvar(id obj, Ivar ivar, id value)
*@param obj The object containing the instance variable whose value you want to set.
* @param ivar The Ivar describing the instance variable whose value you want to set.
* @param value The new value for the instance variable.*這是官方給的解釋。
我們根據以上的三個引數,對其進行賦值,如下:object_setIvar(self.userInfo, var, @"改過的內容");
到此:屬性的修改就結束了。今天寫這篇文章,主要是為了記錄如何修改私有方法的。所以接下來才是重頭戲。
如果我們要修改某一個類庫的私有方法,當然,通過runtime都是為了修改私有方法的,畢竟非私有方法,又何必用runtime這個繁瑣的東西呢。我這裡的需求說起來還是被第三方深惡痛絕的,但是對一些技術還處在一個瓶頸,無法越過的同學們是一個福音。
我的需求就是,下載的第三方,為了防止我們濫用他們的勞動成果,也或者為了獲得一定的報酬,所以才在程式碼中封裝一個明顯的lable或者context等控制元件懸浮在view上。我就是要把他懸浮的這個控制元件遮蔽掉,或者隱藏或者remove掉,期初想用KVO,直接setvalue:hidden的,但是由於這個控制元件是私有變數,所以無法直接使用KVO訪問的。最終選擇了使用runtime修改私有方法即可。
(4)同樣我們需要知道要修改的類的名字,然後獲取該類下的所有方法。程式碼如下:
-(NSArray *)getAllMethods
{
unsigned int count_f =0;
//獲取方法連結串列
Method* methodList_f = class_copyMethodList([UserInfo class],&count_f);
NSMutableArray *methodsArray = [NSMutableArray arrayWithCapacity:count_f];
for(int i=0;i<count_f;i++)
{
Method temp_f = methodList_f[i];
//方法的呼叫地址
IMP imp_f = method_getImplementation(temp_f);
//方法
SEL name_f = method_getName(temp_f);
//方法名字串
const char* name_s =sel_getName(method_getName(temp_f));
//引數數量
int arguments = method_getNumberOfArguments(temp_f);
//返回方法的引數和返回值的描述的字串
const char* encoding =method_getTypeEncoding(temp_f);
NSLog(@"方法名:%@,引數個數:%d,編碼方式:%@",[NSString stringWithUTF8String:name_s],
arguments,[NSString stringWithUTF8String:encoding]);
NSString *methodStr = NSStringFromSelector(name_f);
[methodsArray addObject:methodStr];
}
free(methodList_f);
return methodsArray;
}
以上就是獲取的該類下的所有方法,這個時候我們就該猜了,這是一個痛苦的過程,因為我們不知道到底哪個方法是我們需要修改的。但是一般開發者命名的時候是會根據需要做的意思而命名的,我們只能這樣縮小範圍了,但是如果真的碰到了加密的方法,或者說命名方法沒有規律的,那我真的沒辦法了。只能一個一個試試了。
(5)如果我們搜尋到了方法名為:setUserName:
我們需要新增方法,然後再修改這個私有方法的回撥。
-(void)laodNewMethod
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
Class class = [UserInfo class];
//原來的方法
SEL originalSelector = @selector(setUserName:);
//新方法
SEL swizzledSelector = @selector(setNewUserName:);
//原來的Method
Method originalMethod = class_getInstanceMethod(class, originalSelector);
//新Method
Method swizzledMethod = class_getInstanceMethod([self class], swizzledSelector);
//新增到runtime新方法
BOOL didAddMethod =class_addMethod(class,originalSelector,method_getImplementation(swizzledMethod),method_getTypeEncoding(swizzledMethod));
if (didAddMethod) {
class_replaceMethod([self class],swizzledSelector,method_getImplementation(originalMethod),method_getTypeEncoding(originalMethod));
} else {
method_exchangeImplementations(originalMethod, swizzledMethod);
}
});
}
-(void)setNewUserName:(NSString *)newUserName
{
NSlog("這裡就是修改後的方法,每次執行都會自動跳到這裡呼叫這個方法了。")
}
以上就是所有今天關於runtime的內容
相關推薦
runtime獲取屬性列表,修改屬性值,新增並修改私有方法的呼叫
用了兩天好好的研究了一下runtime,之前初涉runtime。懵懵懂懂的瞭解runtime的強大,但是如何的強大,只是在demo中引用MJExtension的時候自動生成model,瞭解了一些。 經過一天半的研究,首先溫習了之前的獲取屬性列表。 今天想說的
遍歷物件的屬性,判斷屬性的值,並且賦值,用來替代三元運算
public Object getQueryCriteria1(Object fullProcessDetail) throws NoSuchMethodException, InvocationTa
jQuery批量修改Name值,批量增加name後綴,非each(不需要循環)
jquery 批量修改name背景表單字段,配置where屬性自動刷新到可查詢區域,查詢字段需增加_where後綴,響應後臺規則問題批量設置的查詢字段,必須批量增加_where後綴方可正常查詢。each循環有點麻煩,有沒有更方便的批量修改方法。調查方向就是jquery批量修改name,整個互聯網充斥的都是.a
python 字典合並,字典取值,列表轉字典
就是 nbsp 2.7 fault font ... 3.5 bsp 轉化 1、字典的合並 # 第一種 用Python的內置方法,dict與**解包的方式 >>> a = {‘name‘:1,‘b‘:2} >>> b = {‘name‘
繼續對上一頁的ecah進行 優化,求一個數組的和,最大值,最小值,獲取陣列中的元素,3
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <title></title> <style t
在Activity中獲取AsyncTask中更新progress的值,可用在檔案的上傳和下載同步顯示進度
public class MyAsyncTask extends AsyncTask<String, Integer, Void>{ public AsyncResponse mAsyncResponse = null; @Over
ajax非同步問題導致資料出錯(為什麼已經修改了值,下方程式碼卻得到的是未修改過的值)
看兩段程式碼://填充推薦人資訊 $('#recommenderCode').bind('blur' , function(){//焦點觸發方法 if(idnoBlurFlag){ //填充推薦人資訊
小程式系列課程之6事件繫結獲取元素ID,頁面傳值,獲取資料
根據在頁面需要實現不同的跳轉和不同的頁面傳值,梳理了以下情況情況一:在小程式的開發過程中會用到動態傳參,比如根據某一個頁面傳參不同,載入不同的新的頁面(一般會用到wx:for迴圈顯示陣列,實現的功能是點選不同的元素進入不同的頁面,比如在另一個頁面載入某個元素的詳細資訊。)情況
jquery獲取ajax成功請求的返回值,並返回給其他函式使用
//利用回撥函式把請求返回值獲取 function getAjaxVal(cb){ $.get(url,function(data){ cb(data); }) } getAjaxVal(function(data){ return data; });
在一組資料中獲取最大值,最小值,平均值的js寫法
function refreshPrice() { var rows = $("#detailDataGrid").datagrid("getRows"); //獲取當前頁的所有行 //宣告平均值、最小值、最大值 var sum = 0; var min = rows[
修改一個值,讓ScrollView、ListView充滿彈性
android預設的ScrollView、ListView在最頂端下拉或者最底端上拉的時候,都不會帶有反彈效果,很生硬的讓你不能繼續拖動,記得不像iOS那樣可以回彈,個人認為,iOS的互動還是略好一
獲取list中的最大值,最小值
方法一:int max = List.get(0); int min = List.get(0); for (int i = 0; i < List.size(); i++){ if(min
循環獲取數據庫中的值,並存儲到集合中
red .exe class ring dst 集合 next 新的 result package com.zdy.getxxx;import java.sql.Connection;import java.sql.PreparedStatement;import java
C++筆記(11):拷貝控制(拷貝移動,構造賦值,析構)
con 對象 構造函數 col let 拷貝控制 支持 運算符 () 控制對象拷貝,賦值,析構 拷貝構造函數,移動構造函數 拷貝賦值運算符,移動賦值運算符 析構函數 -----------------------------------------------
最大值,最小值,平均值,標準差的計算
ray num 最大值 標準差 bsp div clas min 2.0 用numpy函數可實現快速計算 n [23]: import numpy as np In [24]: data = [1, 2, 3] In [25]: np.mean(data) Out[2
愛一款微信編輯器,始於顏值,忠於人品,陷於才華
優秀 操作 尋找 模式 吸引力 現在 自己的 nag 聊天 現如今,隨著科技的進步,互聯網的發展,手機 成了人手必備的交流溝通工具,而微信自然而然的占據了較大的使用率。我們使用微信聊天,看訂閱號。訂閱號裏面吸引人眼球的當屬於那些題目有吸引力,圖片精美,內容有深度的文章。 現
浮點數的最大值,最小值,精度以及儲存位元組
#include <stdio.h> #include <float.h> int main() { printf("float 儲存最大位元組數 : %lu \n", sizeof(float)); printf("float 最小值: %E\n", FLT
課堂練習--計算陣列的最大值,最小值,平均值,標準差,中位數;numpy.random模組提供了產生各種分佈隨機數的陣列;正態分佈;Matplotlib
#計算陣列的最大值,最小值,平均值,標準差,中位數 import numpy as np a=np.array([1, 4, 2, 5, 3, 7, 9, 0]) print(a) a1=np.max(a) #最大值 print(a1) a2=np.min(a) #最小值 print(a2) a3
JAVA——計算陣列的最大值,最小值,陣列值的和,數組合並,陣列擷取
1,計算陣列的最大值 2,計算陣列的最小值 3,計算陣列和 4,合併陣列 5,擷取陣列 public class ArrayEvent{ //1,計算陣列中的最大值 public static int arrMax(int[] arr1){ if(arr1 == null){
當實體類中entity/DTO/VO等類中,有列舉值,應該怎麼輸出?
當實體類中entity/DTO/VO等類中,有列舉值,應該怎麼輸出? 問題: orderStatus 和 payStatus都是列舉類,並且列舉的個數達地10來個,我們不可能在模板頁面(jsp/ftl/html)等頁面進行多大10多項的if判斷,去一個一個的判斷值,假如以後隨著業務的增多,列舉個數越來越多