In een storyboard, hoe maak ik een aangepaste cel voor gebruik met meerdere controllers?

Ik probeer het te gebruiken storyboards in een app waar ik aan werk. In de app zijn er Lijsten en Gebruikers en elk bevat een collectie van de andere (leden van een lijst, lijsten eigendom van een gebruiker). Dus, bijgevolg, ik heb ListCell en UserCell klassen. Het doel is om deze opnieuw te gebruiken in de app (ie, in een van mijn tableview-controllers).

Dat is waar ik een probleem.

Hoe maak ik een aangepast tableview cel in het storyboard dat opnieuw kan worden gebruikt in elke view controller?

Hier zijn de specifieke dingen die ik tot nu toe heb geprobeerd.

  • In de Controller #1, toegevoegd met een prototype van een cel, stelt u de klasse naar mijn UITableViewCell subklasse, stelt u het hergebruik id, voegde de labels en vast ze tot de klasse verkooppunten. In Controller 2, toegevoegd een lege prototype cel, stel deze in dezelfde klasse en hergebruik id als voorheen. Als het draait, worden de labels verschijnen niet wanneer de cellen worden weergegeven in Controller 2. Werkt prima in de Controller #1.
  • Ontworpen elk type cel in een ander PUNT en vast tot de juiste cel klasse. In een storyboard, een lege prototype van de cel en stelt u de klasse en hergebruik id te verwijzen naar mijn cel klasse. In controllers’ viewDidLoad methoden, geregistreerd die NIB-bestanden voor het hergebruik id. Wanneer weergegeven, worden de cellen in beide controllers waren leeg, zoals het prototype.
  • Gehouden prototypes in beide controllers leeg en instellen class en hergebruik id naar mijn cel klasse. De bouw van de cellen’ UI geheel in code. De cellen werken perfect in alle controllers.

In het tweede geval vermoed ik dat het prototype is altijd het overschrijven van de PENPUNT en als ik doodde het prototype van de cellen, het registreren van mijn PUNT voor het hergebruik id zou werken. Maar dan zou ik niet in staat om de setup gaat over van de cellen naar andere frames, dat is echt het hele punt van het gebruik van storyboards.

Aan het einde van de dag, ik wil twee dingen: draad tot tableview gebaseerd stromen in het storyboard en cel definiëren van lay-outs visueel in plaats van in code. Ik zie niet in hoe je zowel van de mensen die zo ver.

InformationsquelleAutor Cliff W | 2012-02-12

 

6 Replies
  1. 204

    Als ik het goed begrijp, je wilt:

    1. Het ontwerpen van een cel in de IB die gebruikt kunnen worden in meerdere storyboard scènes.
    2. Configureren unieke storyboard gaat over van die cel, afhankelijk van de scène de cel in.

    Helaas, er is momenteel geen manier om dit te doen. Om te begrijpen waarom uw eerdere pogingen niet werken, je nodig hebt om meer te begrijpen over hoe storyboards en prototype tabelweergave cellen werken. (Als u niet de zorg over waarom deze andere pogingen niet werkt, voel je vrij om nu te verlaten. Ik heb geen magische oplossingen voor u, anders dan suggereren dat je een bug.)

    Een storyboard is, in essentie, niet veel meer dan een verzameling .xib bestanden. Als u het laden van een tabel weergeven controller die een prototype van de cellen van een storyboard, hier is wat er gebeurt:

    • Ieder prototype cel is eigenlijk haar eigen embedded mini-punt. Dus als de tabel view-controller is het laden, het loopt door elk van de prototype cel penpunten en gesprekken -[UITableView registerNib:forCellReuseIdentifier:].
    • De tabelweergave vraagt de controller voor de cellen.
    • U waarschijnlijk bellen -[UITableView dequeueReusableCellWithIdentifier:]
    • Bij de aanvraag van een cel met een bepaalde hergebruik id, het controleert of het heeft een punt geregistreerd. Als dit het geval is, wordt een exemplaar van die cel. Deze is samengesteld uit de volgende stappen:

      1. Kijken naar de klasse van de cel, zoals gedefinieerd in de cel van de penpunt. Bel [[CellClass alloc] initWithCoder:].
      2. De -initWithCoder: methode gaat door en voegt subviews en stelt eigenschappen die zijn gedefinieerd in de punt. (IBOutlets waarschijnlijk verslaafd raken hier zo goed, hoewel ik nog niet getest, dat; het kan gebeuren in -awakeFromNib)
    • U bij het configureren van uw mobiele echter u wilt.

    Het is belangrijk om hier op te merken is dat er een onderscheid wordt gemaakt tussen de klasse van de cel en de visuele verschijning van de cel. U maakt twee aparte prototype cellen van dezelfde klasse, maar met hun subviews vastgelegd helemaal anders. In feite, als u de standaard UITableViewCell stijlen, dit is precies wat er gebeurt. De “Standaard” – stijl en de “Subtitle” style, bijvoorbeeld, zijn beide vertegenwoordigd door dezelfde UITableViewCell klasse.

    Dit is belangrijk: De klasse van de cel niet een één-op-één relatie met een bepaalde hiërarchie weergeven. De hiërarchie weergeven wordt geheel bepaald door wat er in het prototype van de cel die werd geregistreerd met deze controller.

    Opmerking, dat de cel het hergebruik-id is niet geregistreerd in sommige wereldwijde cel apotheek. De hergebruik-id wordt alleen gebruikt binnen de context van een enkele UITableView exemplaar.


    Gegeven deze informatie, laten we eens kijken naar wat er gebeurd is in uw bovenstaande probeert.

    In de Controller #1, toegevoegd met een prototype van een cel, stelt u de klasse naar mijn
    UITableViewCell subklasse, stelt u het hergebruik id, voegde de labels en vast
    hen tot de klasse van de verkooppunten. In Controller 2, toegevoegd een lege
    prototype cel, stel deze in dezelfde klasse en hergebruik id als voorheen. Wanneer
    het draait, worden de labels verschijnen niet wanneer de cellen worden weergegeven in
    Controller (#2. Werkt prima in de Controller #1.

    Dit is te verwachten. Terwijl beide cellen had dezelfde klasse, de hiërarchie weergeven die is doorgegeven aan de cel in Controller 2 was volledig verstoken van subviews. Dus heb je een lege cel, en dat is precies wat je in het prototype.

    Ontworpen elk type cel in een ander PUNT en vast tot de
    cel-klasse. In een storyboard, een lege cel prototype
    en stel de klasse en hergebruik id te verwijzen naar mijn cel klasse. In
    controllers’ viewDidLoad methoden, geregistreerd die NIB-bestanden voor de
    hergebruik id. Wanneer weergegeven, worden de cellen in beide controllers waren leeg als de
    prototype.

    Nogmaals, dit is te verwachten. De hergebruik-id wordt niet gedeeld tussen de storyboard-scènes of penpunten, zodat het feit dat al deze verschillende cellen had dezelfde hergebruik id is zinloos. De cel krijgt u terug van de tableview zal een verschijning die overeenkomt met het prototype van de cel in die scène van het storyboard.

    Deze oplossing was dichtbij, dat wel. Als u opgemerkt, kan je gewoon programmatisch oproep -[UITableView registerNib:forCellReuseIdentifier:], het passeren van de UINib met de cel, en u wilt terug te krijgen die dezelfde cel. (Dit is niet omdat het prototype een “dwingende” de punt; je gewoon niet had ingeschreven de penpunt met de tableview, dus het was nog steeds op zoek naar de punt van de ingesloten in het storyboard.) Helaas is er een fout is met deze aanpak — er is geen manier om hook-up storyboard gaat over naar een cel in een stand-alone punt.

    Gehouden prototypes in beide controllers leeg en instellen class en hergebruik id
    naar mijn cel klasse. De bouw van de cellen’ UI geheel in code. Cellen
    werken perfect in alle controllers.

    Natuurlijk. Hopelijk is dit niet verrassend.


    Zo, dat is waarom het niet werkt. U kunt het ontwerp van uw cellen in de zelfstandige punten en gebruik ze in meerdere storyboard scènes; je kan het gewoon op dit moment niet hook-up storyboard gaat over naar de cellen. Hopelijk wel, je hebt iets geleerd in het proces van het lezen van dit.

    • Ah, ik snap het. U genageld mijn onbegrip—de hiërarchie weergeven is volledig onafhankelijk van mijn klas. Voor de hand liggende achteraf! Bedankt voor het goede antwoord.
    • Geweldig antwoord, bedankt!
    • Niet langer onmogelijk, het lijkt: stackoverflow.com/questions/8574188/…
    • Ik heb gezegd dat de oplossing in mijn antwoord. Maar het is niet in het storyboard; het is in een apart Punt. Dus je kon niet van draad tot segues of andere storyboard-achtige dingen. Er hoeft dus niet volledig adres van de eerste vraag.
    • Als van XCode8 de volgende oplossing lijkt te werk als u wilt dat een storyboard enige oplossing. Stap 1) Maak van uw prototype cel in een tableview in ViewController #1 en associëren met de aangepaste UITableViewCell klasse Stap 2) Copy / Paste die cel in ViewController #2 tableview. De loop van de tijd je hebt om te onthouden handmatig doorgeven updates om kopieën van de cel door het verwijderen van kopieën die je hebt gemaakt in het storyboard en plakken terug in de bijgewerkte prototype.
  2. 58

    Ondanks de grote antwoord door BJ Homer ik voel me alsof ik een oplossing. Zo ver als mijn testen gaat, het werkt.

    Concept: het Creëren van een aangepaste klasse voor het xib cel. Daar kunt u wachten voor een touch event en uitvoeren van de overgang programmatisch. Nu alles wat we nodig hebben is een verwijzing naar de controller het uitvoeren van de Overgang. Mijn oplossing is om het in tableView:cellForRowAtIndexPath:.

    Voorbeeld

    Ik heb een DetailedTaskCell.xib met een tabel cel, die ik wil gebruiken in meerdere tabel views:

    In een storyboard, hoe maak ik een aangepaste cel voor gebruik met meerdere controllers?

    Er is een aangepaste klasse TaskGuessTableCell voor die cel:

    In een storyboard, hoe maak ik een aangepaste cel voor gebruik met meerdere controllers?

    Dit is waar de magie gebeurt.

    //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

    Ik heb meerdere Segues, maar ze hebben allemaal dezelfde naam: "FinishedTask". Als je flexibel moet zijn hier, ik stel voor om toe te voegen een andere eigenschap.

    De ViewController ziet er zo uit:

    //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

    Er misschien meer elegante manieren om hetzelfde, maar het werkt! 🙂

    • Dank je, ik ben de implementatie van deze benadering in mijn project. U kunt dit overschrijven methode in plaats, zodat u niet hoeft te krijgen van de indexPath en selecteer de rij jezelf: -(void)setSelected:(BOOL)gekozen geanimeerde:(BOOL)geanimeerde { [super setSelected:geselecteerde animatie:animatie]; if(geselecteerd) [self.controller performSegueWithIdentifier:zelf.segue afzender:self -]; } ik dacht dat het super zou selecteer de cel die bij het aanroepen van [super touchesEnded:raakt withEvent:evenement];. Weet je wanneer het is geselecteerd als er niet bij?
    • Merk op dat met deze oplossing bent u het activeren van de segue elke keer een touch eindigt in een cel. Dit geldt ook als u gewoon bladeren in de cel, niet proberen om het te selecteren. Misschien hebt u meer geluk dwingende -setSelected: op de cel, en het activeren van de segue alleen bij de overgang van NO te YES.
    • Ik heb meer geluk met setSelected:, BJ. Bedankt. Inderdaad, het is een onelegante oplossing (voelt verkeerd), maar op hetzelfde moment, het werkt, dus gebruik ik het totdat dit wordt opgelost (of verandert er iets in Apple ‘ s hof).
  3. 16

    Ik was op zoek naar en vond ik dit antwoord door Richard Venable. Het werkt voor mij.

    iOS 5 bevat een nieuwe methode op UITableView: registerNib:forCellReuseIdentifier:

    Te gebruiken, zet een UITableViewCell in een punt. Het is de enige wortel
    object in de punt.

    U kunt zich inschrijven op de punt na het laden van uw tableView, dan wanneer u
    bel dequeueReusableCellWithIdentifier: met de cell-id, het
    trek het van de punt, net zoals als je had een Storyboard
    prototype cel.

  4. 10

    BJ Homer heeft een uitstekende uitleg van wat er gaande is.

    Vanuit een praktisch oogpunt zou ik toevoegen dat het, gelet u kunt geen cellen als xibs EN sluit segues, de beste te kiezen is dat de cel als een xib – overgangen zijn veel gemakkelijker te onderhouden dan cel lay-outs en eigenschappen over meerdere plaatsen, en uw segues waarschijnlijk anders uit dan je verschillende controllers toch. U kunt het definiëren van de overgang rechtstreeks vanaf uw tafel view-controller naar de volgende controller, en het uitvoeren van het in de code. .

    Een verdere toelichting is dat de cel als een aparte xib-bestand voorkomt u in staat om verbinding te maken welke acties etc. direct naar de tabelweergave controller (ik heb niet werkte dit uit, hoe dan ook – je kan niet aangeven bestand is eigenaar van iets zinnigs). Ik ben bezig om dit door het vaststellen van een protocol voor de mobiele ‘ s table view-controller wordt verwacht om te voldoen aan en het toevoegen van de controller als een zwakke eigenschap, vergelijkbaar met een gemachtigde, in cellForRowAtIndexPath.

    • Ja, ik denk dat dit de richting die ik ben gaan in een te. Bedankt.
  5. 10

    Swift 3

    BJ Homer gaf een uitstekende uitleg, Het helpt mij te begrijpen van het concept. Om make a custom cell reusable in storyboard, die gebruikt kunnen worden in een TableViewController we moeten mix the Storyboard and xib aanpak. Stel we hebben een cel genoemd als CustomCell die worden gebruikt in de TableViewControllerOne en TableViewControllerTwo. Ik ben het in stappen.

    1. Bestand > Nieuw > Klik op Bestand > Selecteer Cocoa Touch Class > klik op Volgende > Geef de Naam Van je klas(bijvoorbeeld CustomCell) > selecteer Subklasse als UITableVieCell > Tick het ook XIB-bestand in en druk op Volgende.

    2. Het aanpassen van de cel als u wilt en stel de id in de attribute inspector voor cel, hier zijn we ll ingesteld als CellIdentifier. Deze id wordt gebruikt in uw ViewController te identificeren en te hergebruiken in de Cel.

    3. Nu hoeven we alleen maar te register this cell in onze ViewController viewDidLoad. Er is geen behoefte aan initialisatie methode.

    4. Nu kunnen we gebruik maken van deze aangepaste cel in een tableView.

    In TableViewControllerOne

    let reuseIdentifier = "CellIdentifier"
    
    override func viewDidLoad() {
    super.viewDidLoad()
    tableView.register(UINib(nibName: "CustomCell", bundle: nil), forCellReuseIdentifier: reuseIdentifier)
    } 
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier:reuseIdentifier, for: indexPath) as! CustomCell
        return cell!
    }
  6. 5

    Ik een manier gevonden om belasting van de cel voor dezelfde VC, niet getest voor de segues. Dit kan een tijdelijke oplossing voor het creëren van de cel in een apart punt

    Laten we zeggen dat je een VC en 2 tafels en u wilt om het ontwerp van een cel in een storyboard en gebruiken in beide tabellen.

    (ex: een tabel en een veld zoeken met een UISearchController met een tabel voor de resultaten en u wilt gebruik maken van dezelfde Cel in)

    Wanneer de controller vraagt voor de cel doen:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString * identifier = @"CELL_ID";
    
        ContactsCell *cell = [self.YOURTABLEVIEW dequeueReusableCellWithIdentifier:identifier];
      //Ignore the "tableView" argument
    }

    En hier hebt u uw cel van het storyboard

    • Ik heb dit geprobeerd en het lijkt te werken, MAAR de cellen zijn nooit gebruikt. Het systeem maakt altijd en deallocs nieuwe cellen per keer.
    • Dit is het zelfde aanbeveling die kan worden gevonden in het het Toevoegen van een zoekbalk in een tabelweergave Met Storyboards. Als je geïnteresseerd bent, is er een meer diepgaande uitleg van deze oplossing er (zoek tableView:cellForRowAtIndexPath:).
    • maar dit is minder tekst en beantwoord de vraag

Geef een reactie

Het e-mailadres wordt niet gepubliceerd. Vereiste velden zijn gemarkeerd met *