最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

objc方法聲明和實現(xiàn)由于參數(shù)類型不一致所引發(fā)的崩潰

 更新時間:2023年03月31日 14:16:43   作者:布多  
這篇文章主要為大家介紹了objc方法聲明和實現(xiàn)由于參數(shù)類型不一致所引發(fā)的崩潰詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪

正文

你有注意過objc方法聲明處和方法實現(xiàn)處參數(shù)類型不一致的情況嗎,就像這樣:

@interface Person : NSObject
- (void)frothTime:(NSInteger)regionTime value1:(BOOL)value;
@end
@implementation Person
- (void)frothTime:(NSInteger)regionTime value1:(NSString *)value;
@end

這2個方法除了第2個參數(shù)的類型不一樣,其它都一樣,但一旦調(diào)用這個方法就會產(chǎn)生一個壞內(nèi)存訪問的崩潰,這是為什么呢?

這是我在真實項目中遇到的1個很有意思的問題,只要調(diào)用分類中的某個方法就百分百崩潰,而且控制臺沒有任何有用的報錯信息,被調(diào)用的方法里面的代碼也都沒有執(zhí)行,非常難調(diào)試,我花了一些時間才弄懂了其中的原理,整理后分享出來,希望能幫到你,崩潰如下圖所示:

以下是我簡寫后的代碼,它是一份完整的代碼并且可以直接運行。

@interface Person : NSObject
- (void)frothTime:(NSInteger)regionTime value1:(BOOL)value;
@end
@interface Person (Category)
- (void)frothTime:(NSInteger)regionTime;
- (void)frothTime:(NSInteger)regionTime value1:(NSString *)value;
@end
@implementation Person
- (void)frothTime:(NSInteger)regionTime value1:(BOOL)value {
    NSLog(@"%s", __func__);
}
@end
@implementation Person (Category)
- (void)frothTime:(NSInteger)regionTime {
    [self frothTime:regionTime value1:@"111"];
}
- (void)frothTime:(NSInteger)regionTime value1:(NSString *)value {
    NSLog(@"%s", __func__);
}
@end
int main(int argc, const char * argv[]) {
    Person *p = [[Person alloc] init];
    [p frothTime:123];
    return 0;
}

分析

運行代碼后,會在 - (void)frothTime:(NSInteger)regionTime value1:(NSString *)value 這行代碼處產(chǎn)生一條 EXC_BAD_ACCESS 崩潰問題,通過打印和斷點,可以看出方法內(nèi)的代碼并沒有執(zhí)行,說明是調(diào)用這個方法時發(fā)生的崩潰,所以可以排除是方法內(nèi)的代碼問題。

崩潰前的代碼位置是 [self frothTime:regionTime value1:@"111"];,這行代碼從表面上看沒有任何問題,如果你把示例代碼粘貼到 xcode 中,編譯器可能會在這行代碼后面給出1個警告: "Incompatible pointer to integer conversion sending 'NSString *' to parameter of type 'BOOL' (aka 'signed char')",意思是說方法接收的是一個 BOOL 類型的參數(shù),而你傳了一個 NSString * 類型。

仔細看一下代碼,你會發(fā)現(xiàn) Person 類中聲明了 - (void)frothTime:(NSInteger)regionTime value1:(BOOL)value;,而且分類中也有一個類似的聲明 - (void)frothTime:(NSInteger)regionTime value1:(NSString *)value;,它們除了第2個參數(shù)類型不一樣,其它都是一樣的;熟悉objc的同學(xué)應(yīng)該都知道,objc是沒有方法重載的概念,也就是說分類中的方法其實和類中的方法,它們的方法簽名都是 frothTime:value1:。

現(xiàn)在有2個同名的方法實現(xiàn),那么 [self frothTime:regionTime value1:@"111"]; 到底調(diào)用哪個方法呢?按照 xcode 給出的提示,似乎是調(diào)用 - (void)frothTime:(NSInteger)regionTime value1:(BOOL)value; 這個方法,因為編譯器提示第2個參數(shù)類型不一致。

有些同學(xué)在這里或許有一個疑問,明明有2個方法,而且分類中的方法明顯更適合調(diào)用方,為什么編譯器認為我們調(diào)用的是類中的方法而不是分類中的方法;有2點原因,第1是因為objc沒有方法重載的概念,所以這2個方法對編譯器來說其實都是一樣的;第2是因為objc的分類是運行時加載的,編譯器在編譯時并不知道分類以及分類方法的存在。

和其它語言不一樣,objc的方法聲明和實現(xiàn)可以重復(fù),只是不能在一個作用域中重復(fù),例如在 @interface 和 @end 就不能同時存在 - (void)frothTime:(NSInteger)regionTime value1:(BOOL)value;- (void)frothTime:(NSInteger)regionTime value1:(NSString *)value;,即使它們的參數(shù)類型并不是完全一樣;但是可以在分類中寫出和類中一樣的方法聲明或?qū)崿F(xiàn),即使你在分類中寫出 - (void)frothTime:(NSInteger)regionTime value1:(BOOL)value; 這種和類中的方法完全一模一樣的方法也不會有任何報錯信息,如果你不小心在分類中實現(xiàn)了和類中同名的方法,那么運行時會永遠調(diào)用分類中的方法實現(xiàn),不清楚為什么的同學(xué)自行上網(wǎng)尋找答案。

現(xiàn)在我們弄明白了為什么編譯器會給出警告,也知道了實際調(diào)用的其實是分類中的方法實現(xiàn),但分類中的方法參數(shù)類型和我們傳遞的參數(shù)類型明明是一致的,那為什么還會崩潰呢?

原因在于編譯器在對代碼進行編譯時對 @"111" 這個參數(shù)是按照 BOOL 類型而不是 NSString 類型處理的,請看下圖:

使用 xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc 文件路徑 -o 輸出的文件路徑.cpp 將objc代碼編譯為C++代碼。

可以看到編譯器把參數(shù)強轉(zhuǎn)成了 bool 類型,但是方法實現(xiàn)處卻是按照 NSString 類型進行接收的,按照 NSString 類型去訪問一個 bool 類型的內(nèi)存,這就是崩潰的真正原因

補充

如果你嘗試將 - (void)frothTime:(NSInteger)regionTime value1:(BOOL)value; 修改為 - (void)frothTime:(NSInteger)regionTime value1:(NSObject *)value;(其實可以把value的參數(shù)類型修改為任意objc對象類型,只要不是基礎(chǔ)數(shù)據(jù)類型就行),注意:這里我只修改了方法聲明處的參數(shù)類型,并沒有修改方法實現(xiàn)處的參數(shù)類型;然后運行項目;正常運行并輸出;編譯后的代碼截圖如下:

從截圖中可以看到參數(shù)雖然還是被強轉(zhuǎn)成了 NSObjet 類型,但是據(jù)我觀察,只要是objc對象都沒關(guān)系,你可以把它改為 NSArray 等任何 objc 對象類型,雖然有編譯警告,但是并不影響運行。

另外,你也可以將 [self frothTime:regionTime value1:@"111"]; 修改為 [self performSelector:@selector(frothTime:value1:) withObject:@(regionTime) withObject:@"111"];,項目也可以正常運行,原因和上面一樣,因為 withObject 的參數(shù)類型是 id。

總結(jié)

  • 從上面的例子可以看出來,objc是一門非常動態(tài)的語言,這有很多好處,但也有很多坑,如果你不了解這些細節(jié),那么就很可能會遇到各種奇奇怪怪的問題。
  • 由于 objc 沒有方法重載的概念,所以在分類中寫方法時一定一定一定要加前綴(即使方法的參數(shù)類型不一樣也不行),因為你不知道它會不會覆蓋類中的私有方法。
  • objc編譯器會自動將傳遞的參數(shù)強轉(zhuǎn)為方法聲明中的參數(shù)類型,如果方法實現(xiàn)處聲明處的參數(shù)類型不一致,編譯器會以方法聲明中的參數(shù)類型為準,但是運行時會以方法實現(xiàn)處的參數(shù)類型進行接收。

以上就是objc方法聲明和實現(xiàn)由于參數(shù)類型不一致所引發(fā)的崩潰的詳細內(nèi)容,更多關(guān)于objc方法聲明參數(shù)類型引發(fā)崩潰的資料請關(guān)注腳本之家其它相關(guān)文章!

相關(guān)文章

  • iOS中UIScrollView嵌套UITableView的實踐教程

    iOS中UIScrollView嵌套UITableView的實踐教程

    在UIScrollView嵌套UITableView的問題相信大家都遇到過,小編最近在工作中就遇到了這個問題,所以這篇文章主要介紹了iOS中UIScrollView嵌套UITableView的相關(guān)資料,文中介紹的方法是通過自己的實踐所得來的,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-05-05
  • iOS自定義相機功能

    iOS自定義相機功能

    這篇文章主要為大家詳細介紹了iOS自定義相機功能,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-07-07
  • IOS上實現(xiàn)的自定義儀表盤示例

    IOS上實現(xiàn)的自定義儀表盤示例

    本篇文章主要介紹了IOS上實現(xiàn)的自定義儀表盤示例,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧
    2017-01-01
  • 開發(fā)繪圖、手勢綜合App注意點

    開發(fā)繪圖、手勢綜合App注意點

    本篇文章主要給大家詳細講述了在IOS開發(fā)繪圖、手勢綜合App容易遇到的坑以及注意事項等內(nèi)容,有興趣的朋友參考下吧。
    2018-02-02
  • iOS中設(shè)置圓角的幾種方法示例

    iOS中設(shè)置圓角的幾種方法示例

    這篇文章主要介紹了iOS中設(shè)置圓角的三種方法,其中包括使用layer屬性、使用繪圖設(shè)置圓角以及通過另一張mask圖創(chuàng)建新圖,需要的朋友可以參考借鑒,下面來一起看看吧。
    2017-03-03
  • iOS runtime知識梳理

    iOS runtime知識梳理

    本文主要對iOS runtime的知識進行梳理。具有一定的參考價值,下面跟著小編一起來看下吧
    2017-01-01
  • 詳解iOS開發(fā)中的轉(zhuǎn)場動畫和組動畫以及UIView封裝動畫

    詳解iOS開發(fā)中的轉(zhuǎn)場動畫和組動畫以及UIView封裝動畫

    這篇文章主要介紹了iOS開發(fā)中的轉(zhuǎn)場動畫和組動畫以及UIView封裝動畫,主要用到了CAAnimation類和UIView類,需要的朋友可以參考下
    2015-11-11
  • iOS8調(diào)用相機報警告Snapshotting a view的解決方法

    iOS8調(diào)用相機報警告Snapshotting a view的解決方法

    這篇文章主要介紹了iOS8調(diào)用相機報警告Snapshotting a view……的解決方法 ,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2016-11-11
  • iOS中UIActivityIndicatorView的用法及齒輪等待動畫實例

    iOS中UIActivityIndicatorView的用法及齒輪等待動畫實例

    UIActivityIndicatorView活動指示器最常見的用法便是用來制作那個程序中的齒輪轉(zhuǎn)動的等待效果,接下來我們回來簡單整理iOS中UIActivityIndicatorView的用法及齒輪等待動畫實例:
    2016-05-05
  • iOS的XMPPFramework簡單介紹(實現(xiàn)及時通信)

    iOS的XMPPFramework簡單介紹(實現(xiàn)及時通信)

    這篇文章主要介紹了iOS的XMPPFramework簡單介紹(實現(xiàn)及時通信),實現(xiàn)了基于XMPP協(xié)議通信的開發(fā),有需要的朋友可以了解一下。
    2016-11-11

最新評論

海口市| 沙坪坝区| 合阳县| 镇原县| 泰州市| 小金县| 昌平区| 平阳县| 禹州市| 乡城县| 辛集市| 南汇区| 金门县| 西吉县| 汾阳市| 海盐县| 凤台县| 铁岭市| 周宁县| 镇赉县| 光山县| 霍山县| 丽水市| 黎城县| 玛纳斯县| 绥滨县| 滁州市| 耿马| 长岭县| 岳普湖县| 金川县| 漳州市| 太谷县| 锦屏县| 启东市| 玛曲县| 龙胜| 社会| 海口市| 蚌埠市| 丘北县|