亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

解決Objective-C命名空間沖突的最佳方法是什么?

解決Objective-C命名空間沖突的最佳方法是什么?

回首憶惘然 2019-08-06 14:07:19
解決Objective-C命名空間沖突的最佳方法是什么?Objective-C沒有名稱空間; 它很像C,一切都在一個全局命名空間內。通常的做法是使用首字母為類添加前綴,例如,如果您在IBM工作,則可以在前面加上“IBM”; 如果你在微軟工作,你可以使用“MS”; 等等。有時首字母引用項目,例如Adium前綴帶有“AI”的類(因為它背后沒有公司,你可以采用縮寫)。Apple使用NS作為前綴類,并說這個前綴僅供Apple使用。到目前為止一切順利。但是在前面添加2到4個字母到一個類名是一個非常非常有限的命名空間。例如,MS或AI可能具有完全不同的含義(例如,AI可能是人工智能),而其他一些開發人員可能決定使用它們并創建一個同名的類。Bang,命名空間沖突。好吧,如果這是你自己的一個類和你正在使用的外部框架之間的沖突,你可以輕松地改變你的類的命名,沒什么大不了的。但是如果你使用兩個外部框架,那么你沒有源代碼的框架和你無法改變的框架呢?您的應用程序與它們都鏈接,并且您會收到名稱沖突。你會如何解決這些問題?以這樣的方式解決它們的最佳方法是什么,你仍然可以使用這兩個類?在C中,您可以通過不直接鏈接到庫來解決這些問題,而是使用dlopen()在運行時加載庫,然后使用dlsym()找到您要查找的符號并將其分配給全局符號(即可以任何你喜歡的方式命名)然后通過這個全局符號訪問它。例如,如果您遇到沖突,因為某個C庫有一個名為open()的函數,您可以定義一個名為myOpen的變量并讓它指向庫的open()函數,因此當您想要使用系統open()時,你只需使用open(),當你想使用另一個時,你可以通過myOpen標識符訪問它。在Objective-C中是否有類似的可能性,如果沒有,是否還有其他聰明,棘手的解決方案可以使用解析命名空間沖突?有任何想法嗎?更新:只是為了澄清這一點:建議如何提前避免命名空間沖突或如何創建更好的命名空間的答案當然是受歡迎的; 但是,我不會接受它們作為答案,因為它們不能解決我的問題。我有兩個庫和它們的類名沖突。我無法改變它們; 我沒有任何一個的來源。碰撞已經存在,如何提前避免它的提示將不再有用。我可以將它們轉發給這些框架的開發人員,并希望他們在未來選擇更好的命名空間,但目前我正在尋找一個解決方案,以便在單個應用程序中使用框架。任何可能的解決方案?
查看完整描述

3 回答

?
郎朗坤

TA貢獻1921條經驗 獲得超9個贊

如果您不需要同時使用兩個框架中的類,并且您的目標是支持NSBundle卸載的平臺(OS X 10.4或更高版本,沒有GNUStep支持),并且性能對您來說確實不是問題,我相信你可以在每次需要使用一個類時加載一個框架,然后在需要使用其他框架時卸載它并加載另一個框架。

我最初的想法是使用NSBundle加載其中一個框架,然后復制或重命名該框架內的類,然后加載另一個框架。這有兩個問題。首先,我找不到復制指向重命名或復制類的數據的函數,而第一個框架中引用重命名類的任何其他類現在將從其他框架引用該類。

如果有方法可以復制IMP指向的數據,則無需復制或重命名類。您可以創建一個新類,然后復制ivars,方法,屬性和類別。還有更多的工作,但這是可能的。但是,您仍然會遇到引用錯誤類的框架中的其他類的問題。

編輯:C和Objective-C運行時之間的根本區別在于,據我所知,當加載庫時,這些庫中的函數包含指向它們引用的任何符號的指針,而在Objective-C中,它們包含字符串表示形式。 thsoe符號的名稱。因此,在您的示例中,您可以使用dlsym在內存中獲取符號的地址并將其附加到另一個符號。庫中的其他代碼仍然有效,因為您沒有更改原始符號的地址。Objective-C使用查找表將類名映射到地址,并且它是1-1映射,因此您不能擁有兩個具有相同名稱的類。因此,要加載這兩個類,其中一個必須更改其名稱。但是,當其他類需要訪問其中一個具有該名稱的類時,


查看完整回答
反對 回復 2019-08-06
?
叮當貓咪

TA貢獻1776條經驗 獲得超12個贊

使用唯一前綴為您的類添加前綴基本上是唯一的選擇,但有幾種方法可以減少繁瑣和丑陋。還有就是選擇一個長時間的討論在這里。我最喜歡的是@compatibility_aliasObjective-C編譯器指令(在此描述)。您可以使用@compatibility_alias“重命名”類,允許您使用FQDN或某些此類前綴命名您的類:


@interface COM_WHATEVER_ClassName : NSObject

@end


@compatibility_alias ClassName COM_WHATEVER_ClassName

// now ClassName is an alias for COM_WHATEVER_ClassName


@implementation ClassName //OK

//blah

@end


ClassName *myClass; //OK

作為完整策略的一部分,您可以為所有類添加前綴,例如FQDN,然后創建一個包含所有內容的標頭@compatibility_alias(我想您可以自動生成所述標頭)。


這樣的前綴的缺點是你必須COM_WHATEVER_ClassName在除編譯器之外的字符串中需要類名的任何東西中輸入真正的類名(例如上面)。值得注意的是,@compatibility_alias是一個編譯器指令,而不是運行時函數,因此NSClassFromString(ClassName)將失敗(返回nil) - 您將不得不使用NSClassFromString(COM_WHATERVER_ClassName)。您可以使用ibtoolvia build階段在Interface Builder nib / xib中修改類名,這樣就不必在Interface Builder中編寫完整的COM_WHATEVER _...


最后的警告:因為這是一個編譯器指令(并且是一個模糊的指令),它可能無法跨編譯器移植。特別是,我不知道它是否適用于LLVM項目的Clang前端,盡管它應該與LLVM-GCC(使用GCC前端的LLVM)一起使用。


查看完整回答
反對 回復 2019-08-06
?
胡子哥哥

TA貢獻1825條經驗 獲得超6個贊

有些人已經分享了一些可能有助于解決問題的棘手和聰明的代碼。一些建議可能有效,但所有這些建議都不太理想,其中一些建議非常難以實施。(有時丑陋的黑客是不可避免的,但我盡量避免使用它們。)從實際的角度來看,這是我的建議。

  1. 無論如何,請告知開發人員沖突的兩個框架,并明確表示他們未能避免和/或處理沖突會導致您遇到真正的業務問題,如果解決這個問題,可能會導致業務收入損失。強調雖然在每個類的基礎上解決現有的沖突是一個不那么具有侵入性的解決方案,但是完全改變它們的前綴(或者如果它們當前不是,那么使用它們,并且對它們感到羞恥?。┦谴_保它們不會的最佳方法。再次看到同樣的問題。

  2. 如果命名沖突僅限于一組相當小的類,請查看是否可以解決這些類,特別是如果您的代碼之一未直接或間接使用其中一個沖突類。如果是,請查看供應商是否將提供不包含沖突類的框架的自定義版本。如果沒有,請坦率地說,他們缺乏靈活性會降低您使用框架的投資回報率。不要因為在合理范圍內咄咄逼人而感到沮喪 - 客戶永遠是對的。;-)

  3. 如果一個框架更“可有可無”,您可以考慮將其替換為另一個框架(或代碼組合),無論是第三方還是自制程序。(后者是不受歡迎的最壞情況,因為它肯定會產生額外的業務成本,無論是開發還是維護。)如果你這樣做,請告知該框架的供應商你決定不使用他們的框架的原因。

  4. 如果兩個框架被認為對您的應用程序同樣不可或缺,請探索將其中一個框架的使用分解為一個或多個單獨進程的方法,也許可以通過DO進行通信,如Louis Gerbarg建議的那樣。根據溝通的程度,這可能沒有你想象的那么糟糕。我相信有幾個程序(包括QuickTime)使用這種方法通過在Leopard中使用Seatbelt沙箱配置文件提供更細粒度的安全性,這樣只允許代碼的特定子集執行關鍵或敏感操作。性能將是一種權衡,但可能是您唯一的選擇

我猜測許可費,條款和持續時間可能會阻止對這些點的即時行動。希望您能夠盡快解決沖突。祝好運


查看完整回答
反對 回復 2019-08-06
  • 3 回答
  • 0 關注
  • 1965 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號