Элемент экземпляра не может использоваться по типу

139

У меня есть следующий класс:

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

Компиляция завершается с сообщением:

Элемент экземпляра categoryPerPage нельзя использовать для типа ReportView

Что это значит?

Aderstedt
источник
12
Предполагая, что вы собираетесь объявить вычисляемое свойство, numPagesа не замыкание, удалите знак равенства:var numPages: Int { return categoriesPerPage.count }
vadian
1
Можно ли объяснить более подробно, что именно означает это сообщение об ошибке? Я вижу это в совершенно другом контексте.
Уильям Энтрикен
2
Когда вы объявляете блок в области видимости класса, как описано выше, вы ограничены тем, что доступно в типе. У вас нет доступа ни к одному из участников.
Aderstedt
Примечание. Сообщение об ошибке аналогично сообщению, которое вы получаете при попытке создать переменную lazy, но забыли одно из требований . В вашем случае вам не нужна переменная типа lazy, поскольку categoriesPerPageона определена как varвместо let.
Чувственный
1
Удалить = из: var numPages: Int =
andrewz

Ответы:

132

У вас просто есть синтаксическая ошибка при произнесении = {return self.someValue}. =Не требуется.

Используйте:

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

}

если хочешь получить только можешь написать

var numPages: Int {
     return categoriesPerPage.count
}

первым способом вы также можете добавить наблюдателей как set willSet&didSet

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

позволяет использовать = operatorв качестве сеттера

myObject.numPages = 5
Даниэль Кром
источник
1
К сожалению, я пропустил знак равенства. Спасибо.
Aderstedt
Вы говорите, что собираетесь инициализировать categoriesPerPage, который является 2-димным массивом с vInt?
Дан
@Dan your'e право, пример просто продемонстрировать setпример, из-конечно , вы не можете назначить intв[int]
Daniel Кр
Сделал это миллион раз и все еще пропустил лишний знак = :)
Александр G
вам не нужна точка с запятой
Питер Шорн
51

Для всех, кто сталкивается с этим, убедитесь, что вы не пытаетесь изменить класс, а не экземпляр! (если вы не объявили переменную как статическую)

например.

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

instanceOfMyClass.variable = 'Foo' // Right!
Дерек
источник
5
В этом разница между staticпеременной и instanceпеременной, MyClass.variableона действительна, если вы объявите ее как статическую переменную (общую для всех экземпляров)
Даниэль Кром
Это была моя проблема. Я нахожу странным, когда XCode решает поставить класс первым в параметрах автозаполнения перед экземпляром с аналогичным именем, когда контекст, кажется, указывает на то, что я определенно использую экземпляр, а не сам класс. И в тех случаях, когда ваш экземпляр отличается только от случая к случаю, может быть трудно заметить, что вы выбрали класс, а не тот экземпляр, который вы хотели. Спасибо!
LeftOnTheMoon
19

Это говорит о том, что у вас есть переменная экземпляра (переменная видна / доступна только тогда, когда у вас есть экземпляр этого класса), и вы пытаетесь использовать ее в контексте статической области (метод класса).

Вы можете сделать переменную вашего экземпляра переменной класса, добавив статический атрибут / атрибут класса.

Вы создаете экземпляр своего класса и вызываете метод экземпляра для этой переменной.

Влад
источник
В моем случае я попытался использовать переменную экземпляра в блоке завершения, вызываемом после инициализации экземпляра другого класса. Конечно, init - это функция класса, и объявление переменной экземпляра как статической решило проблему.
Рейнхард Меннер
8

Другой пример, у вас есть класс, как:

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

вы также получите такой же тип ошибки, как:

instance member x cannot be used on type x. 

Это потому, что вы присваиваете свой метод с ключевым словом «class» (что делает ваш метод методом типа) и используете like:

Album.getCurrentlyPlayingSongLyric(duration: 5)

но кто устанавливал переменную playingSong раньше? Хорошо. Вы не должны использовать ключевое слово класса для этого случая:

 // ...

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

 // ...

Теперь вы можете идти.

mgyky
источник
8

Иногда Xcode при переопределении методов добавляет class funcвместо просто func. Тогда в статическом методе вы не можете видеть свойства экземпляра. Это очень легко не заметить. Это был мой случай.

введите описание изображения здесь

milczi
источник
Ах, спасибо! Потратил много времени на выяснение, почему я не получил ни одного из предложений автозаполнения члена экземпляра в Xcode. Это похоже на ошибку, я напишу радар с Apple A
Апурв Хатреджа
3

Ваша начальная проблема была:

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

Элемент экземпляра categoryPerPage нельзя использовать для типа ReportView

предыдущие сообщения правильно указывают, если вы хотите вычисляемое свойство , =знак ошибочный.

Дополнительная возможность для ошибки:

Если вы намеревались «Задать значение свойства по умолчанию с помощью замыкания или функции» , вам нужно лишь немного его изменить. (Примечание: этот пример явно не предназначен для этого)

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

Вместо удаления =добавляем() обозначение закрытия инициализации по умолчанию. (Это может быть полезно при инициализации кода пользовательского интерфейса, чтобы хранить все это в одном месте.)

Тем не менее, точно такая же ошибка возникает:

Элемент экземпляра categoryPerPage нельзя использовать для типа ReportView

Проблема заключается в попытке инициализировать одно свойство значением другого. Одним из решений является создание инициализатора lazy. Это не будет выполнено, пока значение не получено.

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

теперь компилятор доволен!

bshirley
источник
0

Я продолжал получать ту же ошибку, несмотря на создание переменной static. Решение: очистить сборку, очистить производные данные, перезапустить Xcode. Или сочетание клавиш Cmd + Shift + Alt + K

UserNotificationCenterWrapper.delegate = self

public static var delegate: UNUserNotificationCenterDelegate? {
        get {
            return UNUserNotificationCenter.current().delegate
        }
        set {
            UNUserNotificationCenter.current().delegate = newValue
        }
    }
Naishta
источник
0

На тот случай, если кому-то действительно нужно подобное закрытие , это можно сделать следующим образом:

var categoriesPerPage = [[Int]]()
var numPagesClosure: ()->Int {
    return {
        return self.categoriesPerPage.count
    }
}
algrid
источник