Ошибка компилятора "ожидаемый метод не найден" при использовании индекса на NSArray

Я написал этот простой код, чтобы опробовать новый синтаксис Objective-C для NSArrays:

NSArray *array = @[@"foo"];
NSLog(@"%@", array[0]); 

Первая строка работает нормально, но подписка приводит к ошибке:

Ожидаемый метод для чтения элемента массива, не найденного в объекте типа 'NSArray *'

Просто интересно, сделал ли я что-то не так, или литералы еще не полностью реализованы. Я компилирую с Apple LLVM 4.0 и использую iOS 5 SDK.

Вот скриншот ошибки тоже.

ошибка

8 ответов

Решение

Вы должны компилироваться с SDK для iOS 6 или OS X 10.8 - в противном случае объекты Foundation не имеют необходимых методов для подписывания бита литерального синтаксиса.* В частности, в этом случае для подписки требуется objectAtIndexedSubscript: быть реализованным NSArray и это новый метод, созданный для взаимодействия с этой функцией компилятора. Части нового синтаксиса, которые имеют отношение только к созданию объектов, должны работать нормально - я не верю, что для этого нужны какие-либо новые методы.

Дополнительную информацию читайте на http://clang.llvm.org/docs/ObjectiveCLiterals.html


* Я основываю это на небольшом исследовании, выполненном borrrden: /questions/14833691/mozhno-li-ispolzovat-llvm-40-v-xcode-43/14833705#14833705

Я получил много откликов по этому ответу, который, на мой взгляд, основан на ответе Борррдена. Пожалуйста, если вы считаете, что мой ответ стоит лишнего голоса, нажмите и проголосуйте там же.

Если вы не ориентируетесь на iOS 6 или OS X 10.8, я хотел бы отметить, что заставить подписку работать по-прежнему на удивление легко. Все, что вам нужно сделать, это добавить требуемые методы в качестве категории, для которой будут работать подписки, и соответствующим образом реализовать эти методы. Поэтому добавьте в следующие классы методы:

NSArray: - (id)objectAtIndexedSubscript: (NSUInteger)index;

NSMutableArray: - (void)setObject: (id)obj atIndexedSubscript: (NSUInteger)index;

NSDictionary: - (id)objectForKeyedSubscript: (id)key;

NSMutableDictionary: - (void)setObject: (id)obj forKeyedSubscript: (id)key;

Реализация этого проста, как вызов соответствующего метода для класса. Например, для реализации подписки на NSArray вы просто реализуете:

- (id) objectAtIndexedSubscript:(NSUInteger)index{
    return [self objectAtIndex:index];
}

Единственный недостаток, который я вижу, это то, что вам нужно обязательно импортировать свою категорию в любой класс, который намеревается использовать подписку. Конечно, вы можете обойти это требование, включив #import в заголовке вашего префикса обычно файл: <appname>-Prefix.pch, (спасибо Джошу Касвеллу за то, что указал на это).

Одним из преимуществ является то, что вы можете изменить методы подписки в соответствии со своими потребностями. Например, Apple не позволяет вам добавлять / удалять объекты в NSMutableArray, используя подписку, но это можно сделать достаточно легко:

 - (void) setObject:(id)obj atIndexedSubscript:(NSUInteger)index{
    if (index < self.count){
        if (obj)
            [self replaceObjectAtIndex:index withObject:obj];
        else
            [self removeObjectAtIndex:index];
    } else {
        [self addObject:obj];
    }
}

Я получил следующий код по этой ссылке:

Вы можете просто добавить эту категорию в NSObject и сбор подписки будет работать. Я положил его в мой файл.pch.

// Add support for subscripting to the iOS 5 SDK.
#if __IPHONE_OS_VERSION_MAX_ALLOWED < 60000
@interface NSObject (SubscriptingSupport)

- (id)objectAtIndexedSubscript:(NSUInteger)idx;
- (void)setObject:(id)obj atIndexedSubscript:(NSUInteger)idx;
- (void)setObject:(id)obj forKeyedSubscript:(id <NSCopying>)key;
- (id)objectForKeyedSubscript:(id)key;

@end
#endif

Конечно, вам понадобится новейшая версия CLANG, которая уже есть в XCode 4.4.

У меня возникла та же проблема, но тогда это было не из-за отсутствия версии для iOS... но это было просто потому, что исходный массив был установлен как NSArray а не NSMutableArray, Меняя его на NSMutableArray исправил это для меня

Я добавляю это, потому что это распространенная ошибка, которая все еще существует в XCode по состоянию на 7/2015, и нелегко понять, как ее решить.

Я получил эту ошибку при попытке вызвать метод объекта, не создавая экземпляр объекта. Мое решение состояло в том, чтобы создать экземпляр объекта, а затем вызвать метод свойства для экземпляра этого объекта.

Пример: что не сработало: [self methodCall: arrayItem] (см. Полный пример ниже)

[self tappedUser:self.activities[indexPath.row].followItem.user.givenName];

Что это исправило: ObjectClass newObject = arrayItem; [self methodCall: newObject] (см. полный пример ниже)

FollowActivityItem *followItem = self.activities[indexPath.row];
[self tappedUser:followItem.user.givenName];

Добавлять #import <Foundation/Foundation.h> в ваш файл h, и используйте NSMutableArray вместо

Получите эту ошибку для некоторого глупого конфликта именования:

NSInteger item = indexPath.item;
switch (item) {
    //many lines of code
}
SongItem *item = self.datas[item]//this item is not the item of indexPath

Если кто-нибудь доберется до этой старой темы после получения этой ошибки в Xcode 9.3 beta 4 с каким-то устаревшим кодом Objective-C, как я, то здесь было мое исправление.

Обновить:

@property (nonatomic, strong) id<CustomClass> myObject;

Для того, чтобы:

@property (nonatomic, strong) NSMutableArray<CustomClass> *myObject;
Другие вопросы по тегам