objective c - في لوحة العمل ، كيف أقوم بإنشاء خلية مخصصة للاستخدام مع وحدات تحكم متعددة؟




objective-c ios (4)

على الرغم من الإجابة الكبيرة من BJ Homer أشعر بأن لدي حل. بقدر ما يذهب الاختبار ، فإنه يعمل.

مفهوم: إنشاء فئة مخصصة لخلية xib. هناك يمكنك الانتظار لحدث اللمس وأداء segue برمجيا. كل ما نحتاجه الآن هو إشارة إلى وحدة التحكم التي تقوم بإجراء Segue. الحل هو وضعه في tableView:cellForRowAtIndexPath:

مثال

لدي DetailedTaskCell.xib يحتوي على خلية جدول أريد استخدامها في طرق عرض جدول متعددة:

هناك فئة مخصصة TaskGuessTableCell لتلك الخلية:

هذا هو المكان الذي يحدث السحر.

// TaskGuessTableCell.h
#import <Foundation/Foundation.h>

@interface TaskGuessTableCell : UITableViewCell
@property (nonatomic, weak) UIViewController *controller;
@end

// TashGuessTableCell.m
#import "TaskGuessTableCell.h"

@implementation TaskGuessTableCell

@synthesize controller;

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event
{
    NSIndexPath *path = [controller.tableView indexPathForCell:self];
    [controller.tableView selectRowAtIndexPath:path animated:NO scrollPosition:UITableViewScrollPositionNone];
    [controller performSegueWithIdentifier:@"FinishedTask" sender:controller];
    [super touchesEnded:touches withEvent:event];
}

@end

لدي العديد من الشرائح ولكنهم جميعا لديهم نفس الاسم: "FinishedTask" . إذا كنت بحاجة إلى أن تكون مرنا هنا ، أقترح إضافة خاصية أخرى.

يبدو ViewController مثل هذا:

// LogbookViewController.m
#import "LogbookViewController.h"
#import "TaskGuessTableCell.h"

@implementation LogbookViewController

- (void)viewDidLoad
{
    [super viewDidLoad]

    // register custom nib
    [self.tableView registerNib:[UINib nibWithNibName:@"DetailedTaskCell" bundle:[NSBundle mainBundle]] forCellReuseIdentifier:@"DetailedTaskCell"];
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    TaskGuessTableCell *cell;

    cell = [tableView dequeueReusableCellWithIdentifier:@"DetailedTaskCell"];
    cell.controller = self; // <-- the line that matters
    // if you added the seque property to the cell class, set that one here
    // cell.segue = @"TheSegueYouNeedToTrigger";
    cell.taskTitle.text  = [entry title];
    // set other outlet values etc. ...

    return cell;
}

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender
{
    if([[segue identifier] isEqualToString:@"FinishedTask"])
    {
        // do what you have to do, as usual
    }

}

@end

قد يكون هناك طرق أكثر أناقة لتحقيق الشيء نفسه ولكن - يعمل! :)

أحاول استخدام القصص المصورة في تطبيق أعمل عليه. في التطبيق هناك قوائم ومستخدمين وكل منها يحتوي على مجموعة أخرى (أعضاء قائمة ، قوائم يملكها مستخدم). لذلك ، لدي فئات UserCell و UserCell . الهدف هو جعل تلك قابلة لإعادة الاستخدام في جميع أنحاء التطبيق (أي ، في أي من وحدات تحكم tableview الخاصة بي).

هذا هو المكان الذي أواجه فيه مشكلة.

كيف يمكنني إنشاء خلية Tableview مخصصة في لوحة العمل التي يمكن إعادة استخدامها في أي وحدة تحكم في العرض؟

إليك الأشياء المحددة التي جربتها حتى الآن.

  • في وحدة التحكم # 1 ، إضافة خلية نموذج ، تعيين فئة إلى الفئة الفرعية UITableViewCell بي ، تعيين معرف إعادة الاستخدام ، إضافة التسميات و توصيلها إلى منافذ الفصل الدراسي. في وحدة التحكم # 2 ، إضافة خلية نموذجية فارغة ، تعيينها إلى نفس الفئة وإعادة استخدام معرف كما كان من قبل. عند تشغيله ، لن تظهر التصنيفات أبدًا عندما يتم عرض الخلايا في وحدة التحكم # 2. يعمل بشكل جيد في وحدة تحكم # 1.

  • صممت كل نوع من الخلايا في NIB مختلفة وتم توصيلها إلى فئة الخلية المناسبة. في لوحة العمل ، إضافة خلية نموذجية فارغة وتعيين فئة وإعادة استخدام معرف للإشارة إلى فئة الخلية الخاصة بي. في أساليب viewDidLoad التحكم ، سجلت تلك الملفات NIB لمعرف إعادة الاستخدام. عندما تظهر ، كانت الخلايا في كل من وحدات التحكم فارغة مثل النموذج الأولي.

  • أبقى النماذج الأولية في كل من وحدات التحكم فارغة وتعيين فئة وإعادة استخدام معرف لفئة الخلية الخاصة بي. شيدت واجهة المستخدم للخلايا بالكامل في التعليمات البرمجية. تعمل الخلايا بشكل مثالي في جميع وحدات التحكم.

في الحالة الثانية أشك في أن النموذج الأولي هو دائماً تجاوز بنك الاستثمار القومي وإذا قمت بقتل خلايا النموذج الأولي ، فإن تسجيل بلدي بنك الاستثمار القومي لمعرف إعادة الاستخدام سيعمل. ولكنني لن أتمكن بعد ذلك من إعداد مقاطع من الخلايا إلى إطارات أخرى ، وهي في الواقع نقطة استخدام القصص المصورة.

في نهاية اليوم ، أريد شيئين: اسلك التدفقات المستندة إلى tableview في لوحة العمل وتحديد تخطيطات الخلايا بصريًا وليس في الشفرة. لا أستطيع أن أرى كيف أحصل على هذين الاثنين حتى الآن.


كما أفهمها ، فأنت تريد:

  1. صمم خلية في البكالوريا التي يمكن استخدامها في العديد من المشاهد المصورة.
  2. قم بتكوين Segboard فريدة من نوعها من هذه الخلية ، اعتمادا على المشهد الذي توجد فيه الخلية.

للأسف ، لا توجد طريقة حاليًا لإجراء ذلك. لفهم سبب عدم نجاح محاولاتك السابقة ، تحتاج إلى فهم المزيد حول كيفية عمل الخلايا القصصية وخلية عرض جدول النموذج الأولي. (إذا كنت لا تهتم لماذا لم تنجح هذه المحاولات الأخرى ، فلا تتردد في المغادرة الآن. ليس لدي أي حلول سحرية بالنسبة لك ، بخلاف الإيحاء بأنك قدمت خطأً).

القصة المصورة ، في جوهرها ، ليس أكثر بكثير من مجموعة من الملفات .xib. عند تحميل وحدة تحكم في عرض جدول تحتوي على بعض خلايا النموذج الأولي من لوحة العمل ، إليك ما يحدث:

  • كل خلية نموذجية هي في الواقع المصغرة الخاصة بها صغيرة المنقار. لذلك عندما يتم تحميل وحدة تحكم عرض الجدول لأعلى ، فإنه يعمل من خلال كل من المناقير في الخلية النموذجية والمكالمات -[UITableView registerNib:forCellReuseIdentifier:] .
  • يسأل عرض الجدول وحدة تحكم الخلايا.
  • ربما تتصل -[UITableView dequeueReusableCellWithIdentifier:]
  • عندما تطلب خلية تحتوي على معرف إعادة استخدام محدد ، فإنها تتحقق مما إذا كانت تحتوي على nib مسجلة. إذا كان كذلك ، فإنه ينشئ مثيلًا لتلك الخلية. يتكون هذا من الخطوات التالية:

    1. انظر إلى صنف الخلية ، كما هو محدد في مستنقع الخلية. اتصل [[CellClass alloc] initWithCoder:] .
    2. The -initWithCoder: الأسلوب يمر ويضيف subviews وتعيين الخصائص التي تم تعريفها في بنك الاستثمار القومي. (من المحتمل أن يتم ربط -awakeFromNib هنا أيضًا ، على الرغم من أنني لم أختبر ذلك ؛ قد يحدث في -awakeFromNib )
  • يمكنك تكوين الخلية الخاصة بك كيفما تشاء.

من المهم أن نلاحظ هنا وجود تمييز بين صنف الخلية والمظهر البصري للخلية. يمكنك إنشاء خليتين نموذجيتين منفصلتين من نفس الفئة ، ولكن مع عرض مقاصدهما بشكل مختلف تمامًا. في الواقع ، إذا كنت تستخدم أنماط UITableViewCell الافتراضية ، فهذا هو بالضبط ما يحدث. على سبيل المثال ، يتم تمثيل النمط "الافتراضي" ونمط "العنوان الفرعي" بنفس فئة UITableViewCell .

هذا مهم : لا يحتوي فئة الخلية على علاقة رأس برأس مع عرض هرمي معين. يتم تحديد التسلسل الهرمي لواجهة العرض تمامًا وفقًا لما هو موجود في الخلية النموذجية التي تم تسجيلها باستخدام وحدة التحكم هذه.

لاحظ أيضًا أن معرف إعادة استخدام الخلية لم يتم تسجيله في بعض مستوصف الخلية العالمي. يتم استخدام معرف إعادة الاستخدام فقط في سياق مثيل UITableView واحد.

بالنظر إلى هذه المعلومات ، دعنا نلقي نظرة على ما حدث في محاولاتك السابقة.

في وحدة التحكم # 1 ، إضافة خلية نموذج ، تعيين فئة إلى الفئة الفرعية UITableViewCell الخاص بي ، تعيين معرف إعادة الاستخدام ، إضافة التسميات و توصيلها إلى منافذ الفصل الدراسي. في وحدة التحكم # 2 ، إضافة خلية نموذجية فارغة ، تعيينها إلى نفس الفئة وإعادة استخدام معرف كما كان من قبل. عند تشغيله ، لن تظهر التصنيفات أبدًا عندما يتم عرض الخلايا في وحدة التحكم # 2. يعمل بشكل جيد في وحدة تحكم # 1.

هذا متوقع. على الرغم من أن كلا الخاليتين لهما نفس الفئة ، إلا أن التسلسل الهرمي لواجهة العرض الذي تم تمريره إلى الخلية في وحدة التحكم رقم 2 كان خاليًا تمامًا من العروض التقديمية. لذا فأنت حصلت على خلية فارغة ، وهذا بالضبط ما تضعه في النموذج الأولي.

صممت كل نوع من الخلايا في NIB مختلفة وتم توصيلها إلى فئة الخلية المناسبة. في لوحة العمل ، إضافة خلية نموذجية فارغة وتعيين فئة وإعادة استخدام معرف للإشارة إلى فئة الخلية الخاصة بي. في أساليب viewDidLoad التحكم ، سجلت تلك الملفات NIB لمعرف إعادة الاستخدام. عندما تظهر ، كانت الخلايا في كل من وحدات التحكم فارغة مثل النموذج الأولي.

مرة أخرى ، هذا متوقع. لا يتم مشاركة معرف إعادة الاستخدام بين مشاهد القصة المصورة أو الحاصرات ، لذلك فإن حقيقة أن كل هذه الخلايا المميزة لها نفس معرف إعادة الاستخدام لا معنى لها. سيكون للخلية التي تحصل عليها من tableview مظهر يطابق الخلية النموذجية في هذا المشهد في لوحة العمل.

هذا الحل كان قريبًا. كما لاحظت ، يمكنك الاتصال برمجيًا -[UITableView registerNib:forCellReuseIdentifier:] ، تمرير UINib يحتوي على الخلية ، وستحصل على نفس الخلية. (هذا ليس لأن النموذج الأولي كان "تجاوز" بنك الاستثمار القومي ، فببساطة لم تكن قد سجلت بنك الاستثمار القومي مع tableview ، لذلك كان لا يزال ينظر في بنك الاستثمار القومي جزءا لا يتجزأ من القصة المصورة.) لسوء الحظ ، هناك خلل مع هذا النهج - لا توجد طريقة لربط قطع لوحة القصة بخلية في مستنقع مستقل.

أبقى النماذج الأولية في كل من وحدات التحكم فارغة وتعيين فئة وإعادة استخدام معرف لفئة الخلية الخاصة بي. شيدت واجهة المستخدم للخلايا بالكامل في التعليمات البرمجية. تعمل الخلايا بشكل مثالي في جميع وحدات التحكم.

بطبيعة الحال. نأمل ، وهذا غير مفاجئ.

لذلك ، هذا هو السبب في أنها لم تنجح. يمكنك تصميم الخلايا الخاصة بك في المناقير المستقلة واستخدامها في العديد من المشاهد المصورة ؛ لا يمكنك حاليًا ربط أجزاء لوحة القصة بهذه الخلايا. نأمل ، على الرغم من أنك تعلمت شيئا في عملية قراءة هذا.


لقد قدم BJ Homer شرحًا ممتازًا لما يجري.

من وجهة نظر عملية ، أود أن أضيف أنه ، بالنظر إلى أنه لا يمكن أن يكون لديك خلايا مثل xibs واتصال segues ، فإن أفضل خيار هو أن يكون الخلية في صورة xib - التحولات أسهل بكثير من الصيانة من تخطيطات الخلية وخصائصها عبر أماكن متعددة ، ومن المرجح أن تكون المقاطع المنفصلة مختلفة عن وحدات التحكم المختلفة الخاصة بك على أي حال. يمكنك تعريف segue مباشرة من وحدة تحكم عرض الجدول الخاص بك إلى وحدة التحكم التالية ، وإجراء ذلك في التعليمات البرمجية. .

هناك ملاحظة أخرى تتمثل في أن امتلاكك للخلية كملف xib منفصل يمنعك من الاتصال بأي إجراءات وما إلى ذلك مباشرة إلى وحدة تحكم عرض الجدول (لم أقم بهذا العمل على أي حال - لا يمكنك تعريف مالك الملف على أنه أي شيء ذي معنى ). إنني أعمل حول هذا من خلال تحديد بروتوكول من المتوقع أن تتوافق وحدة التحكم في عرض جدول الخلية مع إضافة وحدة تحكم كخاصية ضعيفة ، على غرار المفوض ، في cellForRowAtIndexPath.


لقد وجدت طريقة لتحميل الخلية لنفس VC ، ولم يتم اختبارها للقطاعات. قد يكون هذا الحل لإنشاء الخلية في طرف مستقيل

لنفترض أن لديك واحدًا من جداول VC و 2 وتريد تصميم خلية في لوحة العمل واستخدامها في كلا الجدولين.

(مثال: جدول وحقل بحث مع UISearchController مع جدول للنتائج وتريد استخدام نفس الخلية في كل منهما)

عندما تطلب وحدة التحكم من الخلية القيام بذلك:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString * identifier = @"CELL_ID";

    ContactsCell *cell = [self.YOURTABLEVIEW dequeueReusableCellWithIdentifier:identifier];
  // Ignore the "tableView" argument
}

وهنا لديك الخلية الخاصة بك من القصة المصورة





storyboard