2014-04-24 11 views
5

mam klasy A z nagłówka, który wygląda mniej więcej tak:wartości ustawienia w niestandardowych struct jako nieruchomości w Objective-C

typedef struct { 
    int x; 
    int y; 
} Position; 

@interface ClassA : NSObject 

@property Position currentPosition; 

@end 

I próbuję przypisać poszczególne wartości struct pozycji z danej nieruchomości inna klasa jak ta:

ClassA * classA = [ClassA new]; 
classA.currentPosition.x = 10; 

Co daje błąd "wyrażenie nie jest przypisywane" i nie będzie się kompilować.

mogę ustawić go tak:

ClassA * classA = [ClassA new]; 
Position position = { 
    .x = 1, 
    .y = 2 
}; 

classA.currentPosition = position; 

I mogę nawet zmieniać poszczególne "Właściwości" z position zmiennej tak:

ClassA * classA = [ClassA new]; 
Position position = { 
    .x = 1, 
    .y = 2 
}; 

// WORKS 
position.x = 4;  

// DOESN'T WORK 
// classA.currentPosition.x = 4; 

classA.currentPosition = position; 

Dlaczego nie mogę ustawić wartości indywidualnie kiedy są własnością?

+0

Jeśli użyłeś typedef, nie musisz dodawać 'struct' w deklaracji @property. –

+0

@NicolasMiari - poprawiłem, próbowałem różnych sposobów deklarowania, po prostu skopiowałem niewłaściwe rzeczy. – Logan

+0

Zobacz także [Jak uzyskać dostęp do przypisania do elementów CGRect, gdy CGRect jest instancją?] (Http://stackoverflow.com/q/5860755), mimo że jest to wstępnie zadeklarowana właściwość. –

Odpowiedz

6

To wyrażenie:

classA.currentPosition 

zwraca tymczasową kopię swojej struktury, a nie sam struct. Błąd kompilatora informuje użytkownika, że ​​nie można przypisać wartości do jakiegoś elementu tej tymczasowej kopii (ponieważ jest to technicznie rzecz biorąc: rvalue). Ale nie chcesz przypisać wartości do tego elementu, ponieważ po prostu zniknie wraz z samą strukturą.

Dlaczego więc otrzymujesz tylko kopię struktury?

Ponieważ

@property Position currentPosition 

jest właściwie tylko skrótem:

-(Position)currentPosition; 
-(void)setCurrentPosition(Position value); 

oraz w językach C-rodzinnych, pierwsza linia (getter) wskazuje, że jest to powrót struct Pozycja przez wartość, lub jako kopię.

Możesz stworzyć własny akcesor, który zwróci referencję, ale prawdopodobnie nie powinieneś. Nie jest to pospolity idiom w Objective-C - przynajmniej nie w tym kontekście - i powinieneś ogólnie postarać się trzymać wspólnych idiomów dla danego języka.

Zamiast tego należy użyć pozycji podobnej do poniższej;

Position pos = classA.position; 
pos.x = 4; 
classA.position = pos; 

Wreszcie, jeśli naprawdę chcesz, aby móc ustawić currentPosition używając składni pierwotnie pożądany, natomiast utrzymywanie objective-c idiomów, można po prostu zrobić Stanowisko klasa zamiast struct. Następnie właściwość może zwrócić Position *, a reszta składni będzie działać. Upewnij się, że zainicjowałeś wskaźnik w swojej funkcji init (lub w razie potrzeby).

+1

Wydaje się to odpowiadać na moje pytanie, ale jestem ciekawy, dlaczego dostał propozycję? Czy jest coś, co sprawia, że ​​jest to nieprawidłowe? – Logan

+0

Potrzebujesz 3 wiersze za każdym razem, gdy chcesz przypisać jedną z właściwości w strukturze. Klonuje twoją strukturę za każdym razem, gdy uzyskujesz do niej dostęp. Więc nie przypisujesz właściwości, tylko ciągle tworzysz nowe instancje tej struktury z różnymi wartościami. – manecosta

2

Właściwości nie działają dla C-struktur.

Można zrobić to lubią:

@property Position *currentPosition; 

Zasadniczo, za pomocą wskaźnika.

Teraz rzeczywiście trzeba zainicjować ten wskaźnik tak:

- (id) init { 
    self = [super init]; 
    if(self){ 
     self.currentPosition = malloc(sizeof(Position)); 
    } 
    return self; 
} 

Następnie, nie zapomnij użyć notacji strzałki, ponieważ masz do czynienia ze wskaźnikiem:

classA.currentPosition->x = 5; 

I don zapomnij zwolnić pamięć, o którą prosiłeś!

-(void)dealloc{ 
    free(self.currentPosition); 
} 
+1

Możesz to zrobić (jest ważny), ale nie powinieneś (jest to * nie * idiomatyczne). Są lepsze i bardziej Objective-C-ish sposoby na zrobienie tego samego. – adpalumbo

+0

Daje to błąd w 'self.currentPosition = malloc (sizeof (Position));' - "Przypisanie do" Position "z niezgodnego typu 'void *'" – Logan

+2

Ten błąd oznacza, że ​​nie zmieniłeś deklaracji właściwości jako wskaźnik, @ Logan. –

Powiązane problemy