błąd: niepodzielna właściwość do zapisu nie może sparować zsyntetyzowanej metody ustawiającej / pobierającej z funkcją ustawiającą / pobierającą zdefiniowaną przez użytkownika

128

Niedawno próbowałem skompilować starszy projekt Xcode (który wcześniej kompilował się dobrze), a teraz widzę wiele błędów tego formularza:

error: writable atomic property 'someProperty' cannot pair a synthesized setter/getter with a user defined setter/getter

Wzorzec kodu, który powoduje te błędy, zawsze wygląda następująco:

// Interface:

@property (retain) NSObject * someProperty;

// Implementation:

@synthesize someProperty; // to provide the getter
- (void)setSomeProperty:(NSObject *)newValue
{
    //..
}

Rozumiem, dlaczego generowany jest błąd. Mówię kompilatorowi, aby zsyntetyzował moje metody dostępu do właściwości (zarówno pobierające, jak i ustawiające), a następnie natychmiast zastępuję metodę ustawiającą ręcznie. Ten kod zawsze trochę nieprzyjemnie pachniał.

Więc jaki jest właściwy sposób, aby to zrobić? Jeśli użyję @dynamiczamiast @synthesize, będę musiał również napisać getter. Czy to jedyny sposób?

e.James
źródło
Czy dzieje się tak tylko w przypadku atomicnieruchomości? W przypadku właściwości atomowych dobrym pomysłem może być utrzymanie synchronizacji pary getter / setter w odniesieniu do strategii blokowania. Jest to trudne, jeśli jedna część jest syntetyzowana, a druga jest kodem niestandardowym.
Nikolai Ruhe,
Z pewnością zniknie, jeśli sprawię, że właściwość będzie nieatomowa. Ciekawy. Nawet nie pomyślałem o problemie z synchronizacją.
e.James
Odwiedziłem ten temat, aby znaleźć rozwiązanie tego konkretnego problemu. Naprawdę nie chcę sam pisać gettera i setera. No cóż…
Constantino Tsarouhas
Domyślnie każda właściwość jest atomowa i musimy jawnie uczynić ją nieatomową. Właściwości atomowe są bezpieczne dla wątków, więc nie możemy zaimplementować dla nich metody ustawiającej i pobierającej, ponieważ zmieni to funkcjonalność bezpieczną dla wątków. Mam nadzieję, że masz powód, dla którego otrzymujesz ten błąd.
Mohd Haider

Odpowiedzi:

218

Miałem ten sam problem i po przeprowadzeniu kilku badań, oto mój wniosek dotyczący tego problemu:

Kompilator ostrzega Cię o @propertytym, że zadeklarowałeś jako atomic (tj. Przez pominięcie nonatomicsłowa kluczowego), ale podajesz niepełną implementację sposobu synchronizacji dostępu do tej właściwości.

Aby to ostrzeżenie zniknęło:

Jeśli zadeklarujesz, że a @propertyjest atomowy, wykonaj jedną z następujących czynności:

  • używać @dynamiclub;
  • użyj @synthesizei zachowaj syntezator setera i gettera lub;
  • zapewniają ręczną implementację zarówno metody ustawiającej, jak i pobierającej (bez użycia jednej z powyższych dyrektyw).

Jeśli zadeklarujesz @propertywith (nonatomic), możesz mieszać ręczne i syntetyzowane implementacje metod pobierających i ustawiających.

Aktualizacja: uwaga na temat autosyntezy właściwości

Począwszy od LLVM 4.0, CLang zapewnia automatyczną syntezę zadeklarowanych właściwości, które nie są @dynamic. Domyślnie, nawet jeśli @synthesizepominiesz opcję, kompilator zapewni Ci metody pobierające i ustawiające. Jednak zasada właściwości atomowych jest wciąż ta sama: albo niech kompilator zapewniają zarówno getter i setter, OR je realizować zarówno siebie!

octy
źródło
Dzięki! „zadeklaruj @właściwość z (nieatomową)”
Nianliang,
14

Musisz również zaimplementować getter. Przykład:

// Interface:

@property (retain) NSObject * someProperty;

// Implementation:

- (void)setSomeProperty:(NSObject *)newValue
{
    @synchronized (self)
    {
        // ...
    }
}

- (NSObject *)someProperty
{
    NSObject *ret = nil;

    @synchronized (self)
    {
        ret = [[someProperty retain] autorelease];
    }

    return ret;
}
arturgrigor
źródło
12

To pytanie, wśród innych najpopularniejszych wyników wyszukiwania „niestandardowej właściwości celu C”, nie jest aktualizowane o informacje o „setter =” lub „getter =”.

Tak więc, aby podać więcej informacji na to pytanie:

Możesz podać wywołanie @property z własną metodą, pisząc

    @property(setter = MySetterMethod:, getter = MyGetterMethod)

Zwróć uwagę na dwukropek dla podanej metody ustawiającej.

Odniesienie dokumentacja firmy Apple

EDYCJA: Nie jestem do końca pewien, jak nowe zmiany we właściwościach Celu-C (są teraz znacznie bardziej inteligentne) zmieniają odpowiedzi na to pytanie. Być może wszystko powinno być oznaczone jako nieaktualne.

Matias Forbord
źródło
Okazało się, że ustawienie metody ustawiającej w rzeczywistości nie usuwa ostrzeżenia. np. -> "@property (assign, setter = setDelegate :) id delegate;" W tym przypadku wszystko, co mogę zrobić, to dodać własny getter lub dodać właściwość nieatomową, czego nie jestem pewien, czy powinienem, biorąc pod uwagę, że sam ustawiam delegata `` atomowo '', nie ma znaczenia posiadanie właściwości nieatomowej , a przynajmniej tak rozumiem.
David van Dugteren,
Ciekawe, David. W jakiej "wersji" Objective-C jest to (przypuszczam, że wersja XCode byłaby bardziej pomocna)? Nie jestem pewien, jaki wpływ mają na to ostatnie zmiany w Objective-C, szczególnie w iOS 6.
Matias Forbord
0

Dla innych, którzy otrzymują ten błąd nie z powodu opisanego OP, prawdopodobnie masz ten sam problem co ja:

Masz @właściwość o takiej samej nazwie jak metoda - ().

Coś takiego:

@property UIView *mainView;

-(UIView *)mainView;
Albert Renshaw
źródło