Отражение Objective C для универсальной реализации NSCoding

Все остальные ответы хороши, но вы должны также рассмотреть этот вопрос :) Идея этого близка к идее SwDevMan81, но это реальный код (не псевдо), и вы можете переместить более одного элемента (несколько выбранных) предметы) и с улучшением при движении вниз.

private void MoveUp_listBox_button_Click(object sender, EventArgs e)
{
  listBox.BeginUpdate();
  int numberOfSelectedItems = listBox.SelectedItems.Count;
  for (int i = 0; i < numberOfSelectedItems; i++)
  {
    // only if it's not the first item
    if (listBox.SelectedIndices[i] > 0)
    {
      // the index of the item above the item that we wanna move up
      int indexToInsertIn = listBox.SelectedIndices[i] - 1;
      // insert UP the item that we want to move up
      listBox.Items.Insert(indexToInsertIn, listBox.SelectedItems[i]);
      // removing it from its old place
      listBox.Items.RemoveAt(indexToInsertIn + 2);
      // highlighting it in its new place
      listBox.SelectedItem = listBox.Items[indexToInsertIn];
    }
  }
  listBox.EndUpdate();
}

private void MoveDown_listBox_button_Click(object sender, EventArgs e)
{
  listBox.BeginUpdate();
  int numberOfSelectedItems = listBox.SelectedItems.Count;
  // when going down, instead of moving through the selected items from top to bottom
  // we'll go from bottom to top, it's easier to handle this way.
  for (int i = numberOfSelectedItems-1; i >= 0; i--)
  {
    // only if it's not the last item
    if (listBox.SelectedIndices[i] < listBox.Items.Count - 1)
    {
      // the index of the item that is currently below the selected item
      int indexToInsertIn = listBox.SelectedIndices[i] + 2;
      // insert DOWN the item that we want to move down
      listBox.Items.Insert(indexToInsertIn, listBox.SelectedItems[i]);
      // removing it from its old place
      listBox.Items.RemoveAt(indexToInsertIn - 2);
      // highlighting it in its new place
      listBox.SelectedItem = listBox.Items[indexToInsertIn - 1];
    }
  }
  listBox.EndUpdate();
}
12
задан Dave DeLong 31 July 2009 в 18:12
поделиться

3 ответа

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

Обратите внимание, однако, что это будет работать только в том случае, если вы хотите сохранить общее поведение всех переменных экземпляра. Однако вы можете не захотеть, чтобы NSView сохранял свой супервизор; в таких случаях общий случай не сработает.

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

12
ответ дан 2 December 2019 в 19:32
поделиться

(я являюсь автором сообщения в блоге, на которое есть ссылка в комментарии Би Джей Гомера). Есть несколько предостережений при использовании кода:

  1. Целевой класс должен быть KVC-совместимым. Если вы используете свойства Objective-C 2.0 для своих ivars, то все готово. В противном случае вам необходимо убедиться, что ваш класс настроен для правильного ответа на методы valueForKey: и setValue: forKey:.
  2. В коде используется недокументированная «функция» среды выполнения для рекурсивного согласования классов ivar с NSCoding. При компиляции почти вся информация о типе (AFAIK) удаляется из кода, но для сохранения ivars, они также должны соответствовать NSCoding. Я обнаружил, что если ivar является объектом и я вызываю для него ivar_getTypeEncoding (), я верну строку ac, которая выглядит примерно так: {#IVAR_CLASS} (Пример: {#NSString}). Что я делаю, так это получаю строку между # и}, создаю объект класса с помощью NSClassFromString и рекурсирую по нему.
  3. Этот код сохранит ВСЕ ivars.
  4. Используйте на свой страх и риск (конечно)

Я написал это в основном как доказательство концепции, и было много случаев, когда этот код приводил к серьезным сбоям. Например, в объекте A есть ivar для B, а у B есть ivar для A, тогда использование кода для сериализации того или другого может (я считаю) вызвать бесконечный цикл.

Тем не менее, я думаю, что это довольно странно Замечательно, что Objective-C даже позволяет делать такие вещи, как в первую очередь.

  • Используйте на свой страх и риск (конечно).
  • Я написал это в основном как доказательство концепции, и есть много случаев, когда этот код терпит неудачу. Например, в объекте A есть ivar для B, а у B есть ivar для A, тогда использование кода для сериализации того или другого может (я считаю) вызвать бесконечный цикл.

    Тем не менее, я думаю, что это довольно странно Замечательно, что Objective-C даже позволяет делать такие вещи, как в первую очередь.

  • Используйте на свой страх и риск (конечно).
  • Я написал это в основном как доказательство концепции, и есть много случаев, когда этот код терпит неудачу. Например, в объекте A есть ivar для B, а у B есть ivar для A, тогда использование кода для сериализации того или другого может (я считаю) вызвать бесконечный цикл.

    Тем не менее, я думаю, что это довольно странно Замечательно, что Objective-C даже позволяет делать такие вещи, как в первую очередь.

    6
    ответ дан 2 December 2019 в 19:32
    поделиться

    Ознакомьтесь с RMModelObject:

    http://www.realmacforge.com/svn/trunk/RMModelObject/

    Однако обратите внимание, что материал ObjC Runtime работает в версии 10.5, а в Simulator, но не на настоящем iPhone. Нашел это на собственном опыте ... Может быть, OS 3.0 наконец-то его поддерживает, но я не проверял.

    0
    ответ дан 2 December 2019 в 19:32
    поделиться