Как я могу иметь несколько UITableViewCell в одном файле NIB в приложении MonoTouch для iPhone?

В MonoTouch есть много примеров, когда люди загружают файлы NIB следующим образом:

var customController = new MyCustomController();
NSBundle.MainBundle.LoadNib("MyCustomController", customController, null);

Основываясь на многих примерах кода, которые я видел в сообщениях в блогах, люди склонны делать это для пользовательских UITableViewCells, которые они разработали в Interface Builder.

Это все хорошо, но, возможно, файл NIB содержит более одного пользовательского UITableViewCell. Я нашел сообщение в блоге, в котором показан один используемый файл NIB, содержащий несколько настраиваемых ячеек таблицы (в Objective-C): http://pegolon.wordpress.com/2008/11/15/using-uitableviewcell-with-interfacebuilder/

Это делает то, что я хочу!

В этом примере Objective-C становится ясно, что NSBundle.MainBundle.LoadNib на самом деле что-то возвращает (NSArray), а затем возвращаемый объект повторяется: каждый объект в NSArray является «шаблоном» ячейки таблицы.

Когда я пытаюсь сделать это в MonoTouch/C#, я изо всех сил пытаюсь перебрать возвращенный NSArray. Он не позволяет мне получить доступ к его содержимому с помощью индексаторов массива и не позволяет мне зацикливаться на нем.

Как мне это сделать?


person Alex York    schedule 01.04.2011    source источник


Ответы (4)


Хорошо, мне удалось заставить его работать. Важно то, как получить объекты из NSArray:

NSArray nsArr = NSBundle.MainBundle.LoadNib("MyCustomController", customController, null);
UITableViewCell = (UITableViewCell)Runtime.GetNSObject(nsArr.ValueAt(0)); // gets the first item

Я также создал пример проекта и статью о том, как использовать пользовательские ячейки таблицы из файлов пера:

Пользовательские ячейки таблицы в MonoTouch

person Dimitris Tavlikos    schedule 03.04.2011
comment
Это отличный пример. У меня не было времени, чтобы привести вам пример, но в основном я заработал так. - person chrisntr; 04.04.2011

Как упоминалось в комментарии к ответу Эдуардо Скоза, описанный рабочий процесс невозможен с XCode 4 без некоторой настройки. Interface Builder в XCode 4 не может создавать подклассы для вас, вы должны сделать это самостоятельно. Вот полный рабочий процесс в MonoTouch для создания представления подкласса без контроллера. Это полезно для ячеек табличного представления и других многоразовых представлений.

  1. Начните с создания нового пустого класса в MonoTouch. Назовите класс как угодно.
  2. Откройте только что созданный файл класса и наследуйте его от нужного класса. (UIView, UITableViewCell и т. д.)
  3. Добавьте атрибут [Register("yourClassName")] в класс.
  4. Добавьте нужные вам выходы, создав свойство (оно не должно быть общедоступным) с автоматическим геттером и сеттером. Добавьте к свойству атрибут [Outlet].
  5. Добавьте действия в класс, если хотите. Объявите их так: [Action("MethodName")] public void MethodName(NSObject sender) {}. Я считаю, что можно также объявить метод закрытым, но я не пробовал.
  6. Создайте метод конструктора со следующей сигнатурой: public YourClassName(IntPtr ptr) : base(ptr) {}. Если вы забудете этот шаг, вы получите исключение при попытке загрузить файл XIB из кода, сообщающее, что не удалось найти этот конструктор.
  7. Убедитесь, что вы сохранили файл.
  8. Теперь добавьте в проект новый вид iPhone или iPad. (Просто представление, не контроллер представления)
  9. Откройте представление в Interface Builder, дважды щелкнув представление в MonoDevelop.
  10. В Interface Builder выберите уже существующее представление и откройте Identity Inspector.
  11. Измените класс на имя класса, который вы создали ранее. Интерфейсный Разработчик должен автоматически заполнить имя для вас.
  12. Теперь настройте представление с помощью меток, кнопок и т. д.
  13. Теперь включите представление помощника в Interface Builder, если оно еще не включено.
  14. Вы только посмотрите на это! Все выходы и действия, которые вы сделали в файле класса C#, находятся в классе Objective C, который показывает помощник. Теперь вы можете подключить элементы управления в вашем представлении к существующим выходам и действиям.
  15. Когда вы закончите, убедитесь, что вы сохранили файл XIB, который вы редактировали, и вернитесь в MonoDevelop.

Чтобы создать экземпляр представления, вы делаете, как написал Димитрис:

NSArray nsArr = NSBundle.MainBundle.LoadNib("YourViewName", theController, null);
YourClassName instantiatedView = (YourClassName)Runtime.GetNSObject(nsArr.ValueAt(0));

theController — это контроллер представления, который будет установлен в качестве владельца файла представления. Насколько я знаю, вы должны передать методу действительный контроллер представления. Если вы создаете экземпляр представления в контроллере представления, вы можете передать this методу. И теперь вы можете использовать любые свойства или методы, которые вы определили в своем представлении, чтобы изменить внешний вид представления. Итак, если вы подключили UILabel к имени свойства выхода (и оно объявлено как общедоступное), вы можете использовать instantiatedView.Name.Text = "John Doe"; Однако вам не следует использовать этот метод, чтобы избавиться от контроллера представления во всех ситуациях. Контроллер представления предназначен для разделения обязанностей. Поэтому, если вам нужна более сложная логика для представления, вы должны пересмотреть, является ли это правильным путем.

person René    schedule 28.02.2012

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

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

public partial class OrderPrimary : UITableViewCell
{
    static OrderPrimary lastCell;

    public OrderPrimary(IntPtr handle) : base(handle)
    {
         lastCell=this;
    }

    static public OrderPrimary NewCell()
    {
         NSObject obj=new NSObject();
         NSBundle.MainBundle.LoadNib("OrderPrimary",obj,null);

         return lastCell;
    }
}

Не большой или умный, но работает для меня. Я не мог понять, как это сделать по-другому .. комментарии приветствуются!

Обратите внимание, что в этом примере у меня есть только одно представление в XIB.

person vlad259    schedule 01.04.2011
comment
Спасибо за ваш ответ - хотя, да, это не то, что мне нужно. В любом случае, вы можете опубликовать фрагмент кода на gist.github.com или что-то в этом роде? - person Alex York; 01.04.2011
comment
Это пища для размышлений. На данный момент все мои пользовательские ячейки имеют свой собственный файл NIB, и все они имеют свой собственный UIViewController, который содержит ячейку. Это явно неправильно, но кажется, что это стандартный способ сделать это, основываясь на всех примерах, которые я видел, копируя и вставляя в Интернете. - person Alex York; 01.04.2011
comment
Да я это тоже видел. Это, кажется, не стоит дорого (что-нибудь?), Так что, возможно, это не проблема. Я получил хороший совет по вопросу, который я поднял относительно ячеек: «проблема в выбранной строке uitableviewdelegate дает неверный nsindexpath»> stackoverflow.com/questions/4861196/ - person vlad259; 01.04.2011
comment
@ Алекс Йорк: Это не так. Разница между использованием контроллера представления и NSObject (который используется в примере objc) минимальна. Почему бы вам просто не добавить все нужные ячейки в один XIB с одним контроллером представления? Вам просто нужно пропустить LoadNib(-ing) и создание экземпляра самого контроллера представления, удаляя его после добавления ячеек в табличное представление. - person Dimitris Tavlikos; 01.04.2011

Я не пробовал это для представлений ячеек, но я думаю, что лучший способ заставить это работать правильно - использовать наследование от построителя интерфейса при определении вашей ячейки.

По сути, вам нужно определить подкласс UITableCellView в IB (щелкните правой кнопкой мыши класс и «добавить подкласс»). Используйте этот класс для создания ячейки. Когда MonoTouch обновит файл .cs.design в вашем проекте, он создаст частичные классы для этих типов, которые вам нужно будет завершить реализацию (убедитесь, что ваша реализация наследуется от UITableViewCell. После этого это должно быть просто вопросом создания новых ячеек с new CustomTableViewCell().

Некоторое время назад я писал об этом с помощью UIViews, но процесс должен быть одинаковым для ячеек: http://escoz.com/monotouch-tip-inherit-uiviews-all-the-time/. Надеюсь это поможет.

person Eduardo Scoz    schedule 02.04.2011
comment
К сожалению, кажется, что этот рабочий процесс больше невозможен в XCode 4 в соответствии с документацией: В Xcode 3 вы обычно добавляете новый класс в иерархию классов в Interface Builder, добавляете выходы и методы действий, а затем спрашиваете Interface Builder для создания соответствующих заголовков и файлов реализации для вас в Xcode. ... С другой стороны, в Xcode 4 все создание классов выполняется непосредственно Xcode. Ссылка - person René; 28.02.2012
comment
Продолжение: Однако это можно сделать немного по-другому. Подробности смотрите в моем ответе. - person René; 28.02.2012