Le membre d'instance ne peut pas être utilisé sur le type

139

J'ai la classe suivante:

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

La compilation échoue avec le message:

Le membre d'instance "categoriesPerPage" ne peut pas être utilisé sur le type "ReportView"

Qu'est-ce que ça veut dire?

Aderstedt
la source
12
En supposant que vous allez déclarer une propriété calculée numPagesplutôt qu'une fermeture, supprimez le signe égal:var numPages: Int { return categoriesPerPage.count }
vadian
1
Peut-il être expliqué plus en détail ce que signifie ce message d'erreur? Je le vois dans un contexte complètement différent.
William Entriken
2
Lorsque vous déclarez un bloc dans la portée de la classe, comme ci-dessus, vous êtes limité à ce qui est disponible dans le type. Vous n'avez accès à aucun membre de l'instance.
Aderstedt le
Remarque: Le message d'erreur est similaire à celui que vous obtenez lorsque vous essayez de créer une variable différée mais que vous avez oublié l'une des exigences . Dans votre cas, vous ne voulez pas de variable différée car elle categoriesPerPageest définie comme varau lieu de let.
Senseful
1
Supprimer = de: var numPages: Int =
andrewz

Réponses:

132

Vous avez juste une erreur de syntaxe en disant = {return self.someValue}. Le =n'est pas nécessaire.

Utilisation :

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

}

si tu veux obtenir seulement tu peux écrire

var numPages: Int {
     return categoriesPerPage.count
}

avec la première façon, vous pouvez également ajouter des observateurs comme set willSet&didSet

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

permettant de l'utiliser = operatorcomme setter

myObject.numPages = 5
Daniel Krom
la source
1
Oups, j'ai raté le signe égal. Merci.
Aderstedt le
Vous dites que vous allez initialiser categoriesPerPage, qui est un tableau à 2 dimensions avec vlequel est Int?
Dan
@Dan Your'e right, L'exemple est juste pour montrer l' setexemple, bien sûr que vous ne pouvez pas attribuer intà[int]
Daniel Krom
Cela a été fait un million de fois et a encore manqué le signe supplémentaire :)
Alexandre G
vous n'avez pas besoin du point-virgule fam
Peter Schorn
51

Pour toute autre personne qui trébuche là-dessus, assurez-vous de ne pas essayer de modifier la classe plutôt que l'instance! (sauf si vous avez déclaré la variable comme statique)

par exemple.

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

instanceOfMyClass.variable = 'Foo' // Right!
Derek
la source
5
C'est la différence entre staticvariable et instancevariable, MyClass.variableest valide si vous la déclarez comme variable statique (partagée entre toutes les instances)
Daniel Krom
C'était mon problème. Je trouve cela un peu étrange quand XCode décide de mettre la classe en premier dans les options de saisie semi-automatique avant une instance portant le même nom lorsque le contexte semble me pointer définitivement en utilisant l'instance plutôt que la classe elle-même. Et dans les cas où votre instance ne diffère que par cas, il peut être difficile de remarquer que vous avez choisi la classe plutôt que l'instance que vous vouliez. Merci!
LeftOnTheMoon
19

Cela signifie que vous avez une variable d'instance (la variable n'est visible / accessible que lorsque vous avez une instance de cette classe) et que vous essayez de l'utiliser dans le contexte d'une portée statique (méthode de classe).

Vous pouvez faire de votre variable d'instance une variable de classe en ajoutant un attribut static / class.

Vous instanciez une instance de votre classe et appelez la méthode d'instance sur cette variable.

Vlad
la source
Dans mon cas, j'ai essayé d'utiliser une variable d'instance dans le bloc d'achèvement appelé après l'initialisation d'une instance d'une autre classe. Bien sûr, un init est une fonction de classe, et déclarer la variable d'instance comme statique a résolu le problème.
Reinhard Männer
8

Un autre exemple est que vous avez une classe comme:

@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
    }
}

vous obtiendrez également le même type d'erreur comme:

instance member x cannot be used on type x. 

C'est parce que vous attribuez à votre méthode le mot-clé "class" (qui fait de votre méthode une méthode de type) et en utilisant comme:

Album.getCurrentlyPlayingSongLyric(duration: 5)

mais qui a défini la variable playSong avant? D'accord. Vous ne devez pas utiliser de mot-clé de classe dans ce cas:

 // ...

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

 // ...

Vous êtes maintenant libre de partir.

mgyky
la source
8

Parfois, Xcode lorsque les méthodes de remplacement s'ajoutent class funcau lieu de simplement func. Ensuite, dans la méthode statique, vous ne pouvez pas voir les propriétés de l'instance. Il est très facile de l'ignorer. C'était mon cas.

entrez la description de l'image ici

Milczi
la source
Ah merci! J'ai passé beaucoup de temps à comprendre pourquoi je ne recevais aucune des suggestions de saisie semi-automatique des membres de l'instance dans Xcode. Cela semble être un bug, je vais déposer un radar avec Apple 👍🏽
Apoorv Khatreja
3

Votre problème initial était:

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

Le membre d'instance "categoriesPerPage" ne peut pas être utilisé sur le type "ReportView"

les articles précédents le soulignent correctement, si vous voulez une propriété calculée , le =signe est errant.

Possibilité supplémentaire d'erreur:

Si votre intention était de «définir une valeur de propriété par défaut avec une fermeture ou une fonction» , vous n'avez qu'à la modifier légèrement également. (Remarque: cet exemple n'était évidemment pas destiné à faire cela)

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

Au lieu de supprimer le =, nous ajoutons() pour désigner une fermeture d'initialisation par défaut. (Cela peut être utile lors de l'initialisation du code de l'interface utilisateur, pour tout conserver au même endroit.)

Cependant, la même erreur se produit exactement :

Le membre d'instance "categoriesPerPage" ne peut pas être utilisé sur le type "ReportView"

Le problème est d'essayer d'initialiser une propriété avec la valeur d'une autre. Une solution consiste à créer l'initialiseur lazy. Il ne sera pas exécuté tant que la valeur n'aura pas été accédée.

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

maintenant le compilateur est content!

bshirley
la source
0

J'ai continué à obtenir la même erreur malgré la création de la variable static. Solution: Clean Build, Nettoyer les données dérivées, Redémarrez Xcode. Ou raccourci Cmd + Maj + Alt + K

UserNotificationCenterWrapper.delegate = self

public static var delegate: UNUserNotificationCenterDelegate? {
        get {
            return UNUserNotificationCenter.current().delegate
        }
        set {
            UNUserNotificationCenter.current().delegate = newValue
        }
    }
Naishta
la source
0

Juste au cas où quelqu'un aurait vraiment besoin d'une telle fermeture , cela peut être fait de la manière suivante:

var categoriesPerPage = [[Int]]()
var numPagesClosure: ()->Int {
    return {
        return self.categoriesPerPage.count
    }
}
algrid
la source