#ios #objective-c #arrays
#iOS #objective-c #массивы
Вопрос:
Я хотел бы создать массив C, в котором хранятся некоторые объекты, но хотел бы объявить его следующим образом:
id array = malloc(sizeof(NSObject * 4));
Но это выдает ошибку; он просит меня либо:
Исправьте это — используйте __bridge для прямого преобразования (без смены владельца).
Или:
Исправьте это: используйте CFBridgeRelease для вызова передачи права собственности на 1 ‘void’ в ARC.
Я пробовал оба, но все равно выдает ошибку:
Отсутствует)
Я помню, что делал это; но я забыл, как, поскольку прошло некоторое время.
Как я могу сохранить id
идентификаторы в массиве C и извлекать из него данные, а затем отбрасывать их?
Комментарии:
1. Какой тип
id
?void*
,NSObject*
или что-то еще?2.
id
это просто Objective-Cid
.3. @Deduplicator
id
определяется как указатель на любой объект ObjC.4. Что не так с предложением Xcode по исправлению?
id thing = (__bridge id)(malloc(sizeof(NSObject*)));
5. @EdgarAroutiounian Ошибка, как написано выше «Отсутствует)». Вопрос:
id
является ли указатель на struct, который указывает на любой Objective-C, поэтому, когда я объявляю массив C, нужно ли мне «уважать» его, чтобы выделить правильную сумму? Потому что все указатели имеют одинаковый размер?
Ответ №1:
Размер указателя одинаков для всех типов, включая объекты, поэтому все, что вам нужно, — это следующее:
id *myArray = malloc(sizeof(void *) * 4);
Обратите внимание, что тип, используемый слева в опубликованном примере, также был неправильным, поскольку ожидается, что на выделяемую память будут ссылаться как на массив указателей C на объекты, а не просто на объект.
Если вы компилируете с включенным ARC, вам нужно будет добавить к объявлению myArray
квалификатор срока службы и привести возвращаемое значение malloc
. Это потому, что ARC может управлять временем жизни только указателей на объекты, а массив, в котором вы собираетесь хранить объекты, относится к типу C. Например, чтобы явно сообщить ARC, что указатели в массиве неуправляемые, вы могли бы изменить предыдущий код следующим образом:
__unsafe_unretained id *myArray = (__unsafe_unretained id *) malloc(sizeof(void *) * 4);
Обратите внимание, что, поскольку ARC не может управлять количеством сохранений в массивах C, вам предстоит убедиться, что все, что вы храните в массиве, можно безопасно использовать.
Комментарии:
1. Спасибо, но я получаю эту ошибку, используя решение выше: неявное преобразование типа указателя Objective-C ‘void *’ в `__strong id *’ с помощью ARC запрещено .
2. Кажется, это работает. Но мне очень любопытно вот что: правда ли, что мы никогда не должны приводить возвращаемое значение
malloc
ради хорошей практики-sake и не могли бы вы, пожалуйста, сказать мне, будет ли это нарушать хорошую практику —(__unsafe_unretained id *)
? Заранее спасибо.3. Теперь я вспомнил, что я также хотел спросить: означает ли это, что в приведенном выше решении это
void *
то же самое, чтоid *
? Но я думал, чтоid
сам по себе уже является указателем. Этоid*
означало бы, что это объявлено как указатель на указатель наid
?4.
void *
означает указатель на что-то неопределенного типа, тогда какid
означает указатель на объект.id *
означает указатель на указатель типаid
.id
является typedef дляstruct objc_object *
, поэтому typedef включает в себя*
.5. @Unheilig Вы спросили: «Правда ли, что мы никогда не должны приводить возвращаемое значение malloc ради хорошей практики». Где вы это услышали? В некоторых случаях приведение было бы ненужным и, следовательно, просто добавило бы бессмысленный беспорядок в код, но в данном случае это необходимо для того, чтобы предоставить компилятору ARC достаточную информацию о типе, чтобы сделать возможной компиляцию кода.
Ответ №2:
Вы не можете хранить массивы объектов в Objective-C. Это позволяет выделять указатели только на объекты. Для этого правильный синтаксис был бы таким:
id *array = malloc(sizeof(*array) * 4);
или, возможно
id *array = malloc(sizeof(id) * 4);
но первый вариант более СУХОЙ.
Комментарии:
1. Спасибо, но обе версии выдают ошибку: указатель на ‘id’ неконстантного типа без явного владельца .