2015-03-04 4 views
-2

Я использую Parse в качестве моего бэкэнд. Сохранение/выборка объектов выполняется в отдельном потоке от основного потока, так что если вы делаете что-либо с данными, вы пытаетесь принести, вы должны сделать это в справочном блоке, как это:Objective-C - добавить объект к NSMutableArray по определенному индексу

[Card fetchInBackgroundWithBlock:^(PFObject *object, NSError *error) { 
    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; 
    ... 
    //setting up button based on Card's name 
    ... 
    [buttonArray addObject:button]; 
}]; 

Это создает новый поток, и когда объект был извлечен из Parse, выполняется код внутри блока.

Я добавляю кнопку для каждого объекта Карты из массива карт, прикрепленных к пользователю синтаксического анализа. Когда вы нажимаете кнопку карты, вы можете увидеть некоторую информацию об этом, а также выбрать ее удаление. Я выполняю размотку segue, которая обрабатывает удаление кнопки для удаленной карты, а также перемещение любых кнопок под удаленным, поэтому нет пробелов. Моя проблема в том, что, поскольку кнопки создаются и добавляются в мой массив внутри другого потока, некоторые объекты могут быть извлечены из строя. Таким образом, мой экран может отображать кнопки в порядке 1 2 3 4, но мой массив удерживает кнопки [3,2,1,4]. Как я могу убедиться, что сохраняю кнопки в массиве в том же порядке, что и на экране, что является тем же самым порядком, что карты хранятся в моем массиве Parse?

Вот как я удаление кнопок в настоящее время, которая движется неправильные кнопки:

-(IBAction)prepareForUnwindPaymentCardDeleted:(UIStoryboardSegue *)segue 
{ 
    [buttonArray removeObjectAtIndex:cardNum]; 
    for(int i = cardNum; i < [buttonArray count]; i++) 
    { 
     UIButton *button = [buttonArray objectAtIndex:i]; 
     [button setTag:i]; 
     [button setFrame:CGRectMake(xCenter-width/2, button.frame.origin.y - 52, width, height)]; 
    } 
    yValue -= 52; 
} 

yValue является у-координату происхождения кнопки, и соответствует координате у, что следующая кнопка должна быть помещена в если я добавлю новую карту/кнопку. Следовательно, когда я удаляю кнопку/карту, я уменьшаю yValue, поэтому я не оставляю промежуток между текущей текущей кнопкой и новой кнопкой. cardNum - это переменная, которая равна индексу карты в моем массиве Parse и также является указателем кнопки в том порядке, в котором она появляется. Тем не менее, я обнаружил, что это не всегда индекс кнопки внутри buttonArray.

Что я хочу для моего NSMutableArray buttonArray, чтобы его индексы соответствовали порядку появления на экране кнопок, поэтому, если я удаляю кнопку 3, мне нужно сдвинуть кнопки 4-n до заполнения пробела, затем уменьшите каждый из их тегов, чтобы соответствовать правильной карте.

Редактировать - Моим решением оказалось просто создать кнопку и добавить ее в мой массив до вызова fetchinbackground. Таким образом, все добавлялось в том порядке, который я ожидал. Я неправильно использовал метод insertObjectAtIndex, но поскольку я добавлял к индексу равный счету, он не вызывал ошибок. Когда я узнаю немного больше о них, вместо этого я буду использовать NSMutableDictionary, как было предложено Джошем и Дунканом.

+0

Тег Parse не нужен и не связан с ним по существу. Я добавляю асинхронный тег, который более подходит. – nhgrif

+1

1) Собственно прочитайте спецификацию для NSMutableArray. 2) Узнайте о синхронизации в Objective-C. –

+0

Возможный дубликат [Добавление объекта по определенному индексу NSMutableArray] (http://stackoverflow.com/questions/5137359/adding-an-object-at-a-specific-index-of-an-nsmutablearray) – nhgrif

ответ

2

NSArrays не может иметь пустые места в них, поэтому вы не можете использовать insertObject: atIndex: для вставки элементов за конец массива.

Я считаю, что вы можете использовать его, чтобы добавить элемент в конец:

NSMutableArray *array = [NSMutableArray arrayWithCapcity: 10]; 
int index = 0; 

[array insertObject @"foo" atIndex: index++]; 

или даже

array[index++] = @"foo"; 

Как Джош отметил, если вы хотите карту от кнопок к объектам, используйте словарь.

Если вы действительно хотите «разреженный» массив, то вы можете заполнить пустые пространства объектами NSNull, а затем использовать replaceObjectAtIndex:withObject:.

Что-то вроде этого:

int count = 10; 
NSMutableArray *array = [NSMutableArray arrayWithCapcity: count]; 
int index = 0; 
for (int index = 0; index<count; index++); 
    array[index] = [NSNull null]; 

, а затем заменить объект (например, с индексом 7): существуют

[array replaceObjectAtIndex: 7 withObject @"foo"]; 

или

объекты
array[7] = @"foo"; 

NSNull для этой конкретной цели , Они, по сути, являются «страницей, преднамеренно оставленной пустой» для коллекций, таких как массивы. Затем вы можете использовать тестовый код, например

... принимать решения на основе «пустых» мест в вашем массиве. (В этом редком случае вы можете использовать == для сравнения объектов для равенства, поскольку существует только один объект NSNull. Это одноэлемент.)

+0

Я взял строки кода, инициализируя кнопку и добавляя ее в массив из блока fetchInBackground, поэтому, оказывается, я добавлял их в правильном порядке и всегда добавлял их к индексу, равному счету, который добавляет это до конца массива, как вы сказали, что я могу сделать. Просто взятие строк из фонового кода было простым исправлением, которое я искал. Не могли бы вы порекомендовать использовать словарь? У меня никогда не должно быть более трех кнопок, и часто это будет только одно. Является ли использование массива над картой чем-то, что приведет к отключению приложения из магазина приложений? –

+0

Apple не дает patootie крысы, какие структуры данных вы используете внутри своей программы. Они отклонят вас за использование частных API-интерфейсов или нарушают их правила интерфейса пользователя, сбой, отображение неприемлемого контента и т. Д. –

+0

Я не совсем понимаю, что вы пытаетесь сделать, поэтому немного сложно порекомендовать решение. Это похоже на то, что у вас есть проблема с управлением одной и той же структурой данных из двух разных потоков, что является полным no-no. Вам нужно создать свой код, чтобы пользователь не мог добавлять или удалять кнопки, пока сервер обновляет контент из фона. –

-1

Вы пробовали insertObject:atIndex: в NSMutableArray? Вы можете использовать indexOfObject:, чтобы получить соответствующий индекс для карты в вашем карточном массиве.

+0

Я искал addObject: atIndex: функция и пропустила это! Благодарю. Мне также нужно было использовать [NSMutableArray arrayWithSize: numCards] или insertObject: atIndex выдает ошибку. Кроме того, удаление кнопки из моего массива не удаляло кнопку из представления, поэтому иногда, когда кнопки были сдвинуты, можно было бы скользить под «удаленным», что бы выглядело так, будто я удалил неправильный. На данный момент я устанавливаю его в скрытое, прежде чем удалять его из массива, поэтому он кажется удаленным, пока не найду более правильное решение. –

+0

@JakeT. - Как работает ваш код, даже с '[NSMutableArray arrayWithSize: numCards]' неизвестно. Просто прочитайте описание 'insertObject: atIndex:', и вы увидите, что он четко указывает * «вы не можете вставить объект с индексом, большим, чем текущий счетчик массива» *, также см. Ответ Duncan C. Не разрешайте свою проблему таким образом, она * будет * идти не так. См. Ответы от Duncan & Josh о том, как правильно это сделать. – CRD

+0

@JakeT. Я должен сказать, что мой ответ не столь подробный и тщательный, как ответы от Дункана и Джоша. Будьте внимательны при работе с изменяемыми массивами и используйте 'addObject',' replaceObjectAtIndex: withObject' и 'insertObject: atIndex:' условно. – Peng90

2

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

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

+0

Карта представляет собой объект Parse, который может содержать только простые типы. Я не могу добавить кнопки в карты. Тем не менее, я посмотрю в NSMutableDictionary. –

Смежные вопросы