2009-06-15 89 views
3

偶爾,它的建立方法調度表有用所以調用方法A調用的AIMP1()方法,而在另一時間調用方法A調用BImpl()。在Objective-C中,如何爲系統自動調用的方法(例如委託方法)做到這一點?例如,如果系統第一次調用viewDidAppear,我希望它調用viewAppearFirstTime,同時調用viewDidAppear隨後會碰到一個完全不同的方法體(而不是使用布爾標誌在代碼中執行if-else檢查)。如何在Objective-C中實現或修改方法調度表?

另一個例子,說UIView的drawRect在應用程序中經常被調用,如果第一次調用drawRect與後續調用不同,我不想包含if-test,因爲這是代碼更難閱讀和檢查也是不必要的後第一次。

+0

對於不是單例的任何類,這是非常有問題的,因爲方法查找表是按類而不是實例,所以任何混合將應用於類的每個實例。 – Chuck 2009-06-15 18:01:20

回答

3

我會在這裏告誡:您描述的特定情況可能不應該這樣做。這幾乎肯定是過於聰明,應該分爲viewDidLoadviewWillAppear而不是viewWillAppear的兩個版本。這就是說,問題出現了。

我的首選解決方案是保留一個SEL指向我想要做的事情。舉例來說,我使用這種技術的一個複雜的異步活動後,「下一步行動」:

if (self.nextActionSelector != NULL) 
{ 
    [self performSelector:self.nextActionSelector]; 
} 

因此,對於這一點,你可以使用一個viewWillAppearSelector會隨時間而改變,並且viewWillAppear只會叫什麼它指向。

Ben對Method Swizzling的建議在某些情況下很有用,但更多的時候當您試圖修改某些現有對象而不是您自己的行爲時。它確實可以使調試變得有趣......好吧,實際上並不好玩。痛苦。很痛苦。

除此之外,我會看看-forwardInvocation:,它可以用來響應你不直接實現的消息。然後,您可以重寫調用以調用您真正想要的方法。不過,這並不是真正意義上的使用方式。它用於透明地將呼叫轉接到其他對象。但至少調試它並不困難,因爲調試器會按照您的預期進行調試。

通常在這種情況下,而不是一個布爾值,我尋找我以前運行過的證據。檢查view是否已經設置,或者是第一次初始化的其他值,所以我不需要一個特殊的變量,所以我很容易清理我的狀態(就像iPhone在內存緊張時傾倒東西的做法) 。在可能的情況下,我會讓這些東西在他們的吸氣者中自行初始化,而不是讓一些外部派對擁有特殊的首次邏輯。保持這裏的邏輯簡單,使得維護更容易,嘿,NSInvocation是瘋狂的 - 慢(好吧,你不會注意到它,除了在一個緊密的循環中,但它比我的測試中的方法調用慢大約500倍,我並不是建議在性能,可維護性方面做出這個決定)。

2

閱讀this,然後將您的NSInvocation實例放入NSDictionary

2

Objective-C的運行時,可以修改從選擇的映射在運行時的方法實現,這是非常漂亮的。看看這篇關於CocoaDev的文章以獲取更多信息:CocoaDev: Method Swizzling。你可以調用任何你有現有映射的函數,這樣你就可以在obj-c運行時有效地替換你想要的任何函數。

這真的不是你應該做的,雖然到處都是 - 我第一次嘗試NSInvocations。既然你可以編寫自己的viewDidAppear功能,並調出你的viewAppearFirstTime:從內功能,方法混寫可能是矯枉過正。

祝你好運!

2

如果要修改方法所有類的實例,可以通過方法調整來實現。我從來沒有聽說過它被用於此目的,但你可能能夠完成你想要使用從class_replaceMethodviewDidAppearFirstTime內的東西。

但是,如果要修改的方法分發單個實例,我認爲你唯一的選擇是你的viewDidAppear方法內的條件語句來考慮,不需要在第一和隨後出現單獨的方法重新設計(從你的描述,你的代碼分成viewDidLoadviewWillAppear功能似乎是有道理的)。

相關問題