Elementu instancji nie można używać na typie

138

Mam następującą klasę:

class ReportView: NSView {  
    var categoriesPerPage = [[Int]]()
    var numPages: Int = { return categoriesPerPage.count }
}

Kompilacja kończy się niepowodzeniem i pojawia się komunikat:

Nie można użyć elementu członkowskiego instancji „CategoriesPerPage” z typem „ReportView”

Co to znaczy?

Aderstedt
źródło
12
Zgadując, że zamierzasz zadeklarować obliczoną właściwość, numPagesa nie zamknięcie, usuń znak równości:var numPages: Int { return categoriesPerPage.count }
vadian
1
Czy można dokładniej wyjaśnić, co oznacza ten komunikat o błędzie? Widzę to w zupełnie innym kontekście.
William Entriken
2
Kiedy deklarujesz blok w zakresie klasy, jak powyżej, jesteś ograniczony do tego, co jest dostępne w typie. Nie masz dostępu do żadnych członków instancji.
Aderstedt
Uwaga: komunikat o błędzie jest podobny do tego, który pojawia się podczas próby utworzenia zmiennej leniwej, ale zapomniałeś o jednym z wymagań . W twoim przypadku nie chcesz leniwej zmiennej, ponieważ categoriesPerPagejest zdefiniowana jako varzamiast let.
Senseful
1
Usuń = z: var numPages: Int =
andrewz

Odpowiedzi:

132

Po prostu masz błąd składni podczas mówienia = {return self.someValue}. Nie =jest potrzebne.

Posługiwać się :

var numPages: Int {
    get{
        return categoriesPerPage.count
    }

}

jeśli chcesz dostać, tylko możesz pisać

var numPages: Int {
     return categoriesPerPage.count
}

w pierwszym przypadku możesz także dodać obserwatorów jako set willSet&didSet

var numPages: Int {
    get{
        return categoriesPerPage.count
    }
    set(v){
       self.categoriesPerPage = v
    }
}

pozwalając na użycie = operatorjako seter

myObject.numPages = 5
Daniel Krom
źródło
1
Ups, przegapiłem znak równości. Dzięki.
Aderstedt
Mówisz, że zamierzasz zainicjalizować categoriesPerPage, która jest 2-dim tablicą, z vktórą jest Int?
Dan
@Dan your'e rację Przykładem jest tylko wykazać setprzykład, z-oczywiście nie można przypisać intdo[int]
Daniel Krom
Zrobiłem to milion razy i nadal przegapiłem dodatkowy znak = :)
Alexandre G
nie potrzebujesz średnika fam
Peter Schorn
51

Dla każdego, kto się na to natknie, upewnij się, że nie próbujesz modyfikować klasy, a nie instancji! (chyba że zadeklarowałeś zmienną jako statyczną)

na przykład.

MyClass.variable = 'Foo' // WRONG! - Instance member 'variable' cannot be used on type 'MyClass'

instanceOfMyClass.variable = 'Foo' // Right!
Derek
źródło
5
Jest to różnica pomiędzy staticzmienną a instancezmienną, MyClass.variablejest ważne, jeżeli będziesz zadeklarować ją jako zmienną statyczną (dzielone pomiędzy wszystkich przypadkach)
Daniel Krom
To był mój problem. Uważam, że to trochę dziwne, gdy XCode decyduje się umieścić klasę na pierwszym miejscu w opcjach autouzupełniania przed instancją o podobnej nazwie, gdy kontekst wydaje się wskazywać na zdecydowanie używanie instancji, a nie samej klasy. A w przypadkach, gdy Twoja instancja różni się tylko wielkością liter, może być trudno zauważyć, że wybrałeś klasę, a nie instancję, którą zamierzałeś. Dzięki!
LeftOnTheMoon
19

Mówi się, że masz zmienną instancji (zmienna jest widoczna / dostępna tylko wtedy, gdy masz instancję tej klasy) i próbujesz jej użyć w kontekście zakresu statycznego (metoda klasy).

Możesz uczynić zmienną instancji zmienną klasową, dodając atrybut static / class.

Tworzysz instancję swojej klasy i wywołujesz metodę instancji dla tej zmiennej.

Vlad
źródło
W moim przypadku próbowałem użyć zmiennej instancji w bloku uzupełniania wywołanym po zainicjowaniu instancji innej klasy. Oczywiście init jest funkcją klasową i zadeklarowanie zmiennej instancji jako statycznej rozwiązało problem.
Reinhard Männer
8

Inny przykład to:

@obc class Album: NSObject {
    let name:String
    let singer:Singer
    let artwork:URL
    let playingSong:Song


    // ...

    class func getCurrentlyPlayingSongLyric(duration: Int = 0) -> String {
        // ...
       return playingSong.lyric
    }
}

otrzymasz również błąd tego samego typu, jak:

instance member x cannot be used on type x. 

Dzieje się tak, ponieważ przypisujesz metodę za pomocą słowa kluczowego „class” (co sprawia, że ​​metoda jest metodą typu) i używasz:

Album.getCurrentlyPlayingSongLyric(duration: 5)

ale kto wcześniej ustawił zmienną playingSong? Dobrze. W takim przypadku nie powinieneś używać słowa kluczowego class:

 // ...

 func getCurrentlyPlayingSongLyric(duration: Int = 0) -> String {
        // ...
       return playingSong.lyric
 }

 // ...

Teraz możesz iść.

mgyky
źródło
7

Czasami Xcode, gdy nadpisuje metody, dodaje class funczamiast po prostu func. Wtedy w metodzie statycznej nie widać właściwości instancji. Bardzo łatwo to przeoczyć. To był mój przypadek.

wprowadź opis obrazu tutaj

milczi
źródło
Ah dziękuję! Spędziłem dużo czasu zastanawiając się, dlaczego nie otrzymałem żadnych sugestii autouzupełniania elementów członkowskich instancji w Xcode. Wygląda na to, że to błąd, napiszę radar w Apple 👍🏽
Apoorv Khatreja
3

Twoim początkowym problemem był:

class ReportView: NSView {
  var categoriesPerPage = [[Int]]()
  var numPages: Int = { return categoriesPerPage.count }
}

Nie można użyć elementu członkowskiego instancji „CategoriesPerPage” z typem „ReportView”

poprzednie posty poprawnie wskazują, że jeśli chcesz obliczonej właściwości , =znak jest błędny.

Dodatkowa możliwość błędu:

Jeśli Twoim zamiarem było „Ustawianie domyślnej wartości właściwości za pomocą zamknięcia lub funkcji” , wystarczy tylko nieznacznie ją zmienić. (Uwaga: ten przykład oczywiście nie miał tego robić)

class ReportView: NSView {
  var categoriesPerPage = [[Int]]()
  var numPages: Int = { return categoriesPerPage.count }()
}

Zamiast usuwać =, dodajemy() aby wskazać domyślne zamknięcie inicjalizacji. (Może to być przydatne podczas inicjowania kodu interfejsu użytkownika, aby zachować wszystko w jednym miejscu).

Jednak występuje dokładnie ten sam błąd :

Nie można użyć elementu członkowskiego instancji „CategoriesPerPage” z typem „ReportView”

Problemem jest próba zainicjowania jednej właściwości wartością innej. Jednym z rozwiązań jest utworzenie inicjatora lazy. Nie zostanie wykonana, dopóki wartość nie zostanie uzyskana.

class ReportView: NSView {
  var categoriesPerPage = [[Int]]()
  lazy var numPages: Int = { return categoriesPerPage.count }()
}

teraz kompilator jest szczęśliwy!

bshirley
źródło
0

Ciągle otrzymywałem ten sam błąd pomimo tworzenia zmiennej static. Rozwiązanie: Clean Build, Clean Derived Data, Restart Xcode. Lub skrót Cmd + Shift + Alt + K.

UserNotificationCenterWrapper.delegate = self

public static var delegate: UNUserNotificationCenterDelegate? {
        get {
            return UNUserNotificationCenter.current().delegate
        }
        set {
            UNUserNotificationCenter.current().delegate = newValue
        }
    }
Naishta
źródło
0

Na wypadek, gdyby ktoś naprawdę potrzebował takiego zamknięcia , można to zrobić w następujący sposób:

var categoriesPerPage = [[Int]]()
var numPagesClosure: ()->Int {
    return {
        return self.categoriesPerPage.count
    }
}
algrid
źródło