2015-06-14 15 views
7

Więc, oczywiście, po WWDC gram z nowościami przedstawionymi w zeszłym tygodniu. Jak wiecie Apple wprowadziła rodzajowych do świata Objective-CGeneryczne jednostki Objective-C nie działają dla metod? (Xcode 7 Beta (kompilacja: 7A120f))

Uwaga: Ta odpowiedź jest jakoś follow-up na to pytanie: Are there strongly-typed collections in Objective-C?

Próbowałem ten kod w metodzie działa świetnie

NSMutableArray<NSString*> *array = [[NSMutableArray alloc] init]; 

[array addObject:@""]; 
[array addObject:@(54)];Incompatible pointer types sending 'NSNumber *' to parameter of type 'NSString * __nonnull' 
// Great, generics works as expected. 

jednak mam również metodę Chcę przekształcić do generyków

w pliku nagłówka:

- (NSArray <NSString*> *)objectsToSearch; 

Realizacja:

- (NSArray <NSString*> *)objectsToSearch 
{ 
    NSString *first = @"1"; 

    NSString *second = @"2"; 

    NSString *third = @"3"; 

    NSNumber *test = @(55); 

    return @[first, second, third, test]; // No-error!!! 
} 

robię coś źle lub Clang nie obsługuje leków generycznych + literały albo jest coś jeszcze mi brakuje?

+0

Tak, robisz coś złego, jak wiesz! I tak kompilator powinien generować błąd/ostrzeżenie.Xcode 7 to oprogramowanie w wersji beta, zgłoś je Apple jako błąd i miejmy nadzieję, że to naprawi. – CRD

+0

Dzięki za wyjaśnienie! – lvp

+0

Nie wierzę, że to błąd. Zobacz mój duży post poniżej z przykładowym kodem i dlaczego działa poprawnie. – drekka

Odpowiedz

10

Właśnie zdiagnozowałem to i nie sądzę, że to błąd. Poniższy kod pokazuje różne opcje i dlaczego każdy z nich będzie lub nie będzie się kompilować. Uwaga: Jest to oparte na moich przypuszczeniach co do sposobu działania. Może się różnić od tego, jak Apple to wytłumaczy.

#pragma clang diagnostic push 
#pragma clang diagnostic ignored "-Wunused-variable" 
-(void) testGenericArrays { 

    NSString *aString = @"abc"; 
    NSNumber *aNumber = @(55); 

    NSArray<NSString *> *arr1 = @[aString, aNumber]; 
    // Compiles because the RHS is an un-typed array at compilation time. 

    NSArray<NSString *> *arr2 = @[aString, @(20)]; 
    // Compiles because the RHS is an un-typed array at compilation time. 

    NSArray<NSString *> *arr3 = [NSArray<NSString *> arrayWithObjects:aString, aNumber, @(20), nil]; 
    // Compiles because the type erasure for arrayWithObjects only types the first argument which is a NSString. 
    // The rest of the arguments are a vaList which is not checked during header processing. 

    NSArray<NSString *> *arr4 = [NSArray<NSString *> arrayWithObjects:@(20), nil]; // <- Error! 
    NSArray<NSString *> *arr5 = [NSArray<NSString *> arrayWithObjects:aNumber, nil]; // <- Error! 
    // Neither of these two compile because the first argument is now a NSNumber and is checked. 

    NSArray<NSString *> *arr6 = [NSArray<NSString *> arrayWithObject:aNumber]; // <- Error! 
    // Doesn't compile because the argument is checked during header processing. 

    NSArray<NSString *> *arr7 = [NSArray arrayWithObject:aNumber]; 
    // Compiles because the RHS is an un-typed array at compilation time. 

    NSMutableArray<NSString *> *arr8 = [[NSMutableArray alloc] init]; 
    [arr8 addObject:aNumber]; // <- Error! 
    // Doesn't compile because the LHS is a typed array and we are adding to it. 
} 
#pragma clang diagnostic pop 

Mam nadzieję, że to wyjaśnia rzeczy dla ludzi. Możesz wyciąć i wkleić do testu jednostkowego i wypróbować samodzielnie.

0

Zgadzam się, że to błąd. Przetestowałem prostszą wersję twojej sprawy i nadal się nie udaje.

NSString *first = @"1"; 
NSString *second = @"2"; 
NSString *third = @"3"; 
NSNumber *test = @(55); 

NSArray <NSString*>* arr = @[first, second, third, test, @(20)]; 

To nie wydaje się być problemem z literalną składnią. Linia ta nadal nie powoduje błędów.

NSArray <NSString*>* anotherArray = [NSArray arrayWithObjects:first, second, third, test, @(20), nil]; 
2

Nie zakładaj, że Apple dodaje generycznych do Obj-C, ponieważ chcą poprawić Obj-C. Prawdziwym powodem jest to, że wszystkie struktury iOS/OS X napisane w Obj-C są bardzo trudne w użyciu w Swift - musisz rzucić wszystko od AnyObject.

Dodanie leków generycznych do Obj-C umożliwia Apple prawidłowe oznaczanie metod, np.

@property(nonatomic, readonly, copy) NSArray <__kindof UIView *> *subviews 

Ważne jest to, że teraz Swift może pracować z frameworkami znacznie lepiej. Wdrażanie ostrzeżeń/błędów dotyczących niewłaściwego użycia leków generycznych w Obj-C nie jest takie ważne, więc możemy spodziewać się tam wielu błędów.

Radzę zgłosić błąd, ale nie spodziewaj się, że zostanie on wkrótce naprawiony.

0

Właśnie natknąłem się na ten post i nie otrzymuję takich samych wyników. Wyciąłem i wkleiłem kod do XCode, aby potwierdzić i wszystkie powyższe przykłady dają błędy (mam ostrzeżenia ustawione na błędy). Więc nie widzę błędu. Albo to, albo istnieje ustawienie kompilatora, gdzieś między nami jest inaczej.

+0

Próbowałem go z beta Xcode 7, udało się skompilować –

+0

Nie mogę wyjaśnić, dlaczego wydaje się, że działa dla niektórych, a nie dla innych. Używam generycznych w ostatnim tygodniu, a oni tworzą wszystkie ostrzeżenia kompilatora, których oczekuję od nich. Sugerowałbym sprawdzenie ustawień kompilacji i wydaje mi się to najbardziej prawdopodobną przyczyną rozbieżności. Być może dlatego, że wszystkie ostrzeżenia są błędami, które moje działają. – drekka

+0

Zapomnij o moim ostatnim komentarzu. Sprawdzam inne rzeczy. – drekka