errore: la proprietà atomica scrivibile non può accoppiare un setter / getter sintetizzato con un setter / getter definito dall'utente


128

Di recente ho provato a compilare un vecchio progetto Xcode (che era solito compilare bene), e ora vedo molti errori di questo modulo:

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

Il modello di codice che causa questi errori è sempre simile al seguente:

// Interface:

@property (retain) NSObject * someProperty;

// Implementation:

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

Vedo perché viene generato l'errore. Dico al compilatore di sintetizzare i miei accessor di proprietà (sia getter che setter), e subito dopo sostituisco manualmente il setter. Quel codice ha sempre annusato un po '.

Quindi, qual è il modo corretto per farlo? Se uso @dynamicinvece di @synthesize, dovrò anche scrivere il getter. Quello è l'unico modo?


Questo succede solo con le atomicproprietà? In caso di proprietà atomiche potrebbe essere una buona idea mantenere sincronizzata la coppia getter / setter rispetto alla strategia di blocco. Questo è difficile se una parte viene sintetizzata mentre l'altra è un codice personalizzato.
Nikolai Ruhe,

Certamente scompare se rendo la proprietà non anatomica. Interessante. Non avevo nemmeno pensato al problema della sincronizzazione.
e.James

Ho visitato questo argomento per trovare una soluzione a quel problema esatto. Non voglio davvero scrivere un getter e un setter da solo. Oh bene ...
Constantino Tsarouhas,

Per impostazione predefinita, ogni proprietà è atomica e dobbiamo renderle esplicitamente non anatomiche. Le proprietà atomiche sono thread-safe, quindi non possiamo implementare setter e getter per loro perché cambierà la sua funzionalità thread-safe. Spero che tu capisca il motivo per cui stai ricevendo questo errore.
Mohd Haider,

Risposte:


218

Ho avuto lo stesso problema e dopo aver fatto un po 'di ricerca, ecco la mia conclusione su questo problema:

Il compilatore ti avvisa di un oggetto @propertydichiarato atomico (ovvero omettendo la nonatomicparola chiave), ma fornisci un'implementazione incompleta di come sincronizzare l'accesso a quella proprietà.

Per far scomparire questo avviso:

Se dichiari a @propertydi essere atomico, esegui una delle seguenti operazioni:

  • utilizzare @dynamico;
  • usare @synthesizee mantenere il setter e getter sintetizzati oppure;
  • fornire un'implementazione manuale sia del setter che del getter (senza utilizzare una delle direttive di cui sopra).

Se dichiari il @propertycon (nonatomic)allora puoi mescolare implementazioni manuali e sintetizzate di getter e setter.

Aggiornamento: una nota sulla sintesi automatica delle proprietà

A partire da LLVM 4.0, CLang fornisce l'auto-sintesi per le proprietà dichiarate che non lo sono @dynamic. Per impostazione predefinita, anche se si omette il @synthesize, il compilatore fornirà i metodi getter e setter per te. Tuttavia, la regola per le proprietà atomiche è sempre la stessa: o lascia che il compilatore fornisca sia il getter che il setter, oppure implementali entrambi da solo!


Grazie! "Dichiara la proprietà @ con (nonatomico)"
Nianliang il

14

È necessario implementare anche il getter. Esempio:

// 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;
}

12

Questa domanda, tra gli altri risultati migliori ottenuti dalla ricerca di "proprietà personalizzata obiettivo C", non viene aggiornata con le informazioni su "setter =" o "getter =".

Quindi, per fornire maggiori informazioni su questa domanda:

È possibile fornire la chiamata @property con il proprio metodo scrivendo

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

Notare i due punti per il metodo di impostazione fornito.

Documentazione di riferimento di Apple

EDIT: Non sono abbastanza sicuro di come le nuove modifiche alle proprietà di Objective-C (ora sono molto più intelligenti) cambiano le risposte a questa domanda. Forse dovrebbe essere contrassegnato come non aggiornato.


Ho scoperto che l'impostazione del metodo setter non ha effettivamente rimosso l'avviso. ad es. -> "@property (assegnare, setter = setDelegate :) id delegate;" In questo caso, tutto quello che posso fare è aggiungere il mio getter o aggiungere la proprietà nonatomica, cosa che non sono sicuro che dovrei, dato che sto impostando il delegato me stesso "atomicamente", non importa avere la proprietà nonatomica , o almeno così capisco.
David van Dugteren,

Interessante, David. In quale "versione" di Objective-C è presente (suppongo che la versione XCode sarebbe più utile)? Non sono sicuro di cosa influiscano le recenti modifiche a Objective-C, in particolare con iOS 6.
Matias Forbord,

0

Per gli altri che ottengono questo errore non per il motivo descritto dall'OP, è probabile che tu abbia lo stesso problema:

Hai un @property con lo stesso nome di un metodo - ().

Qualcosa come questo:

@property UIView *mainView;

-(UIView *)mainView;
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.