Zastanawiałem się, jak zdusić ostrzeżenie:
Kategoria implementuje metodę, która będzie również implementowana przez klasę podstawową.
Mam to dla określonej kategorii kodu:
+ (UIFont *)systemFontOfSize:(CGFloat)fontSize {
return [self aCustomFontOfSize:fontSize];
}
objective-c
clang
Doz
źródło
źródło
super
inaczej.Odpowiedzi:
Kategoria umożliwia dodawanie nowych metod do istniejącej klasy. Jeśli chcesz ponownie zaimplementować metodę, która już istnieje w klasie, zazwyczaj tworzysz podklasę zamiast kategorii.
Dokumentacja Apple: dostosowywanie istniejących klas
Dwie metody z dokładnie taką samą sygnaturą w tej samej klasie doprowadziłyby do nieprzewidywalnego zachowania, ponieważ każdy obiekt wywołujący nie może określić, której implementacji chce.
Dlatego należy albo użyć kategorii i podać nazwy metod, które są nowe i unikalne dla klasy, albo podklasę, jeśli chcesz zmienić zachowanie istniejącej metody w klasie.
źródło
Chociaż wszystko, co zostało powiedziane, jest poprawne, w rzeczywistości nie odpowiada to na pytanie, jak usunąć ostrzeżenie.
Jeśli z jakiegoś powodu musisz mieć ten kod (w moim przypadku mam HockeyKit w swoim projekcie i zastępują one metodę w kategorii UIImage [edytuj: to już nie jest przypadek]) i musisz skompilować swój projekt , możesz użyć
#pragma
instrukcji, aby zablokować ostrzeżenie w następujący sposób:Znalazłem informacje tutaj: http://www.cocoabuilder.com/archive/xcode/313767-disable-warning-for-override-in-category.html
źródło
Lepszą alternatywą (zobacz odpowiedź Bneely na temat tego, dlaczego to ostrzeżenie chroni Cię przed katastrofą) jest użycie zawijania metod. Używając swizzlingu metod, możesz zastąpić istniejącą metodę z kategorii bez niepewności, kto „wygrywa”, zachowując jednocześnie możliwość wywołania starej metody. Sekret polega na nadaniu przesłonięciu innej nazwy metody, a następnie zamianie ich za pomocą funkcji wykonawczych.
Następnie zdefiniuj własną implementację:
Zastąp domyślną implementację swoją:
źródło
Spróbuj tego w swoim kodzie:
UPDATE2: Dodaj to makro
źródło
Możesz użyć swizzling metody, aby pominąć to ostrzeżenie kompilatora. Oto jak zaimplementowałem swizzling metod do rysowania marginesów w UITextField, gdy używamy niestandardowego tła z UITextBorderStyleNone:
źródło
Właściwości zastępujące są ważne dla rozszerzenia klasy (kategoria anonimowa), ale nie dla zwykłej kategorii.
Zgodnie z dokumentami Apple Docs przy użyciu rozszerzenia klasy (kategorii anonimowej) można utworzyć interfejs prywatny do klasy publicznej, tak aby interfejs prywatny mógł przesłonić właściwości udostępnione publicznie. tzn. możesz zmienić właściwość z tylko do odczytu na tylko do odczytu.
Przykładem użycia jest sytuacja, gdy piszesz biblioteki, które ograniczają dostęp do właściwości publicznych, podczas gdy ta sama właściwość wymaga pełnego dostępu do odczytu i zapisu w bibliotece.
Łącze do dokumentów Apple: https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html
Wyszukaj „ Użyj rozszerzeń klas, aby ukryć informacje prywatne ”.
Więc ta technika jest ważna dla rozszerzenia klasy, ale nie dla kategorii.
źródło
Kategorie są dobre, ale można je nadużywać. Pisząc kategorie, powinieneś z zasady NIE wdrażać ponownie metod wyjścia. Może to spowodować dziwny efekt uboczny, ponieważ teraz ponownie piszesz kod, od którego zależy inna klasa. możesz złamać znaną klasę i skończyć wywracając debugger na lewą stronę. To po prostu złe programowanie.
Jeśli chcesz to zrobić, naprawdę powinieneś utworzyć podklasę.
Potem sugestia swizzlingu, to dla mnie duże NIE-NIE-NIE.
Przesuwanie go w czasie wykonywania jest kompletne NIE-NIE-NIE.
Chcesz, aby banan wyglądał jak pomarańcza, ale tylko w czasie wykonywania? Jeśli chcesz pomarańczę, napisz pomarańczę.
Nie nadawaj bananowi wyglądu i zachowuj się jak pomarańcza. A co gorsza: nie zamieniaj swojego banana w tajnego agenta, który po cichu sabotuje banany na całym świecie, wspierając pomarańcze.
Yikes!
źródło
Miałem ten problem, gdy zaimplementowałem metodę delegata w kategorii, a nie w klasie głównej (mimo że nie było implementacji klasy głównej). Rozwiązaniem dla mnie było przeniesienie z głównego pliku nagłówkowego klasy do pliku nagłówkowego kategorii. Działa to dobrze
źródło