Oparty na widoku NSTableView z wierszami, które mają dynamiczne wysokości

84

Mam aplikację z opartą na widoku NSTableView. W tym widoku tabeli znajdują się wiersze zawierające komórki zawierające zawartość składającą się z wielu wierszy NSTextFieldz włączonym zawijaniem wyrazów. W zależności od zawartości tekstowej NSTextFieldkomórki rozmiar wierszy potrzebnych do wyświetlenia komórki będzie różny.

Wiem, że mogę zaimplementować NSTableViewDelegatemetodę - tableView:heightOfRow:aby zwrócić wysokość, ale wysokość zostanie określona na podstawie zawijania słów użytego na NSTextField. Zawijanie wyrazów w NSTextFieldpodobny sposób opiera się na tym, jak szeroka NSTextFieldjest…, która jest określana przez szerokość NSTableView.

Soooo… Myślę, że moje pytanie brzmi… jaki jest dobry wzorzec projektowy do tego? Wygląda na to, że wszystko, czego próbuję, kończy się chaosem. Ponieważ TableView wymaga znajomości wysokości komórek, aby je ułożyć ... i NSTextFieldznajomości jego układu, aby określić zawijanie wyrazów ... a komórka potrzebuje wiedzy o zawijaniu słów, aby określić jej wysokość ... to okrągły bałagan ... i doprowadza mnie to do szaleństwa .

Propozycje?

Jeśli ma to znaczenie, wynik końcowy będzie również dostępny do edycji, NSTextFieldsktóry zmieni rozmiar, aby dopasować się do zawartego w nich tekstu. Mam już to działające na poziomie widoku, ale widok tabeli nie dostosowuje jeszcze wysokości komórek. Doszedłem do wniosku, że kiedy już rozwiążę kwestię wysokości, użyję noteHeightOfRowsWithIndexesChangedmetody - , aby poinformować widok stołu o zmianie wysokości… ale nadal będę pytać delegata o wysokość… stąd moja sprawa.

Z góry dziękuję!

Jiva DeVoe
źródło
Jeśli zarówno szerokość, jak i wysokość widoku mogą zmieniać się wraz z ich zawartością, to ich zdefiniowanie jest skomplikowane, ponieważ musisz iterować (ale wtedy możesz buforować). Ale twoja obudowa wydaje się mieć zmienną wysokość przy stałej szerokości. Jeśli szerokość jest znana (tj. Na podstawie szerokości okna lub widoku), to nic nie jest tutaj skomplikowane. Brakuje mi, dlaczego szerokość jest zmienna?
Rob Napier
Tylko wysokość może się zmieniać wraz z zawartością. I już rozwiązałem ten problem. Mam podklasę NSTextField, która automatycznie dostosowuje wysokość. Problem polega na tym, aby uzyskać wiedzę o tym dostosowaniu z powrotem do delegata widoku tabeli, aby mógł odpowiednio zaktualizować wysokość.
Jiva DeVoe,
@Jiva: Zastanawiasz się, czy już to rozwiązałeś.
Joshua Nozzi
Próbuję zrobić coś podobnego. Podoba mi się pomysł podklasy NSTextField, która dostosowuje swoją własną wysokość. Co powiesz na dodanie powiadomienia (delegata) o zmianie wysokości do tej podklasy i monitorowanie tego za pomocą odpowiedniej klasy (źródło danych, delegat konspektu, ...), aby uzyskać informacje o konspekcie?
John Velman,
Bardzo powiązane pytanie, z odpowiedziami, które pomogły mi bardziej niż te tutaj: Wysokość wiersza NSTableView na podstawie NSStrings .
Ashley,

Odpowiedzi:

132

To jest problem z kurczakiem i jajkiem. Tabela musi znać wysokość wiersza, ponieważ to określa, gdzie będzie leżeć dany widok. Ale chcesz, aby widok był już w pobliżu, więc możesz go użyć do obliczenia wysokości wiersza. Więc co jest pierwsze?

Odpowiedzią jest zachowanie dodatkowego NSTableCellView(lub innego widoku, którego używasz jako „widoku komórki”) tylko do pomiaru wysokości widoku. W tableView:heightOfRow:metodzie delegata, dostęp model dla „rząd” i ustawić objectValuena NSTableCellView. Następnie ustaw szerokość widoku na szerokość stołu i (jakkolwiek chcesz to zrobić) określ wymaganą wysokość dla tego widoku. Zwróć tę wartość.

Nie wywołuj noteHeightOfRowsWithIndexesChanged:z metody delegata tableView:heightOfRow:ani viewForTableColumn:row:! To jest złe i spowoduje mega kłopoty.

Aby dynamicznie aktualizować wysokość, to co powinieneś zrobić, to zareagować na zmianę tekstu (poprzez cel / akcję) i ponownie obliczyć obliczoną wysokość tego widoku. Teraz nie zmieniaj dynamicznie NSTableCellViewwysokości (ani żadnego widoku, którego używasz jako „widoku komórki”). Stół musi kontrolować ramkę tego widoku, a jeśli spróbujesz go ustawić, będziesz walczył z widokiem tabeli. Zamiast tego, w celu / akcji dla pola tekstowego, w którym obliczałeś wysokość, wywołaj noteHeightOfRowsWithIndexesChanged:, co pozwoli tabeli zmienić rozmiar tego pojedynczego wiersza. Zakładając, że masz ustawioną maskę autorezowania bezpośrednio na podwidokach (tj. Podwidoki NSTableCellView), rozmiar rzeczy powinien się zmienić! Jeśli nie, najpierw popracuj nad maską zmiany rozmiaru podglądów podrzędnych, aby uzyskać prawidłowy efekt ze zmiennymi wysokościami wierszy.

Nie zapominaj, że noteHeightOfRowsWithIndexesChanged:animacja jest domyślnie. Aby nie był animowany:

[NSAnimationContext beginGrouping];
[[NSAnimationContext currentContext] setDuration:0];
[tableView noteHeightOfRowsWithIndexesChanged:indexSet];
[NSAnimationContext endGrouping];

PS: Odpowiadam bardziej na pytania publikowane na forach Apple dla deweloperów niż przepełnienie stosu.

PSS: Napisałem NSTableView w oparciu o widok

corbin dunn
źródło
Dzięki za odpowiedzi. Nie widziałem tego pierwotnie ... Oznaczyłem to jako poprawną odpowiedź. Fora deweloperów są świetne, ja też z nich korzystam.
Jiva DeVoe
„Oblicz wymaganą wysokość dla tego widoku. Zwróć tę wartość”. .. To mój problem :(. Używam opartego na widoku tableView i nie mam pojęcia, jak to zrobić!
Mazyod
@corbin Dzięki za odpowiedź, oto co mam w mojej aplikacji. Jednak znalazłem z tym problem dotyczący Mavericks. Skoro doskonale znasz ten temat, czy mógłbyś sprawdzić moje pytanie? Tutaj: stackoverflow.com/questions/20924141/…
Alex
1
@corbin Czy istnieje kanoniczna odpowiedź na to pytanie, ale przy użyciu automatycznego układu i ograniczeń, z NSTableViews? Istnieje potencjalne rozwiązanie z automatycznym układem; zastanawiam się, czy to wystarczy bez interfejsów API RatedHeightForRowAtIndexPath (tego nie ma w kakao)
ZS
3
@ZS: Używam Auto Layout i zaimplementowałem odpowiedź Corbina. W programie tableView:heightOfRow:konfiguruję widok zapasowej komórki z wartościami wiersza (mam tylko jedną kolumnę) i zwracam cellView.fittingSize.height. fittingSizejest metodą NSView, która oblicza minimalny rozmiar widoku, który spełnia jego ograniczenia.
Peter Hosey
43

To stało się o wiele łatwiejsze w macOS 10.13 z .usesAutomaticRowHeights. Szczegóły są tutaj: https://developer.apple.com/library/content/releasenotes/AppKit/RN-AppKit/#10_13 (w sekcji zatytułowanej „NSTableView Automatic Row Heights”).

Zasadniczo po prostu wybierz swój NSTableViewlub NSOutlineVieww edytorze scenorysów i wybierz tę opcję w Inspektorze rozmiaru:

wprowadź opis obrazu tutaj

Następnie ustawisz rzeczy w swoim tak, NSTableCellViewaby miały górne i dolne ograniczenia do komórki, a twoja komórka zmieni rozmiar, aby dopasować się automatycznie. Nie jest wymagany kod!

Twoja aplikacja zignoruje wszelkie wysokości określone w heightOfRow( NSTableView) i heightOfRowByItem( NSOutlineView). Możesz zobaczyć, jakie wysokości są obliczane dla wierszy automatycznego układu za pomocą tej metody:

func outlineView(_ outlineView: NSOutlineView, didAdd rowView: NSTableRowView, forRow row: Int) {
  print(rowView.fittingSize.height)
}
Clifton Labrum
źródło
@tofutim: Jeśli działa poprawnie z zawiniętymi komórkami tekstowymi, jeśli używasz właściwych ograniczeń i upewniasz się, że ustawienie Preferowana szerokość każdego NSTextField z dynamiczną wysokością jest ustawione na Automatycznie. Zobacz także stackoverflow.com/questions/46890144/…
Ely
Myślę, że @tofutim ma rację, to nie zadziała, jeśli umieścisz NSTextView w TableView, spróbuje go zarchiwizować, ale nie zadziała. Działa to jednak z innym komponentem, na przykład NSImage ..
Albert
Użyłem stałej wysokości dla rzędu, ale to nie działa dla mnie
Ken Zira
2
Po kilku dniach zastanawiania się, dlaczego to nie działa, odkryłem: działa TYLKO wtedy, gdy TableCellViewNIE można go edytować. Nie ma znaczenia jest zaznaczone w Attributes [Behavior: Editable] lub Bindings Inspector [Conditionally Set Editable: Yes]
Łukasz
Chcę tylko podkreślić, jak ważne jest posiadanie rzeczywistych ograniczeń wysokości w komórce tabeli: moja nie, więc obliczona wielkość dopasowania komórki wynosiła 0,0 i pojawiła się frustracja.
green_knight
9

W oparciu o odpowiedź Corbina (przy okazji dzięki, rzucając trochę światła na to):

Swift 3, oparty na widoku NSTableView z automatycznym układem dla systemu macOS 10.11 (i nowszych)

Moja konfiguracja: mam układ, NSTableCellViewktóry jest rozłożony przy użyciu automatycznego układu. Zawiera (oprócz innych elementów) multilinię, NSTextFieldktóra może mieć do 2 wierszy. Dlatego wysokość całego widoku komórki zależy od wysokości tego pola tekstowego.

Aktualizuję, aby widok tabeli zaktualizował wysokość dwukrotnie:

1) Gdy zmienia się rozmiar widoku tabeli:

func tableViewColumnDidResize(_ notification: Notification) {
        let allIndexes = IndexSet(integersIn: 0..<tableView.numberOfRows)
        tableView.noteHeightOfRows(withIndexesChanged: allIndexes)
}

2) Gdy zmieni się obiekt modelu danych:

tableView.noteHeightOfRows(withIndexesChanged: changedIndexes)

Spowoduje to, że widok tabeli zapyta delegata o nową wysokość wiersza.

func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {

    // Get data object for this row
    let entity = dataChangesController.entities[row]

    // Receive the appropriate cell identifier for your model object
    let cellViewIdentifier = tableCellViewIdentifier(for: entity)

    // We use an implicitly unwrapped optional to crash if we can't create a new cell view
    var cellView: NSTableCellView!

    // Check if we already have a cell view for this identifier
    if let savedView = savedTableCellViews[cellViewIdentifier] {
        cellView = savedView
    }
    // If not, create and cache one
    else if let view = tableView.make(withIdentifier: cellViewIdentifier, owner: nil) as? NSTableCellView {
        savedTableCellViews[cellViewIdentifier] = view
        cellView = view
    }

    // Set data object
    if let entityHandler = cellView as? DataEntityHandler {
        entityHandler.update(with: entity)
    }

    // Layout
    cellView.bounds.size.width = tableView.bounds.size.width
    cellView.needsLayout = true
    cellView.layoutSubtreeIfNeeded()

    let height = cellView.fittingSize.height

    // Make sure we return at least the table view height
    return height > tableView.rowHeight ? height : tableView.rowHeight
}

Najpierw musimy pobrać obiekt modelu dla wiersza (entity ) i odpowiedni identyfikator widoku komórki. Następnie sprawdzamy, czy utworzyliśmy już widok dla tego identyfikatora. Aby to zrobić, musimy zachować listę z widokami komórek dla każdego identyfikatora:

// We need to keep one cell view (per identifier) around
fileprivate var savedTableCellViews = [String : NSTableCellView]()

Jeśli żaden nie zostanie zapisany, musimy utworzyć (i zapisać w pamięci podręcznej) nowy. Aktualizujemy widok komórki za pomocą naszego obiektu modelu i nakazujemy mu ponowne ułożenie wszystkiego w oparciu o aktualną szerokość widoku tabeli. fittingSizeWysokość może być następnie wykorzystany jako nowej wysokości.

JanApotheker
źródło
To jest doskonała odpowiedź. Jeśli masz wiele kolumn, będziesz chciał ustawić granice na szerokość kolumny, a nie szerokość tabeli.
Vojto
Podczas ustawiania cellView.bounds.size.width = tableView.bounds.size.widthwarto zresetować wysokość do małej liczby. Jeśli planujesz ponownie wykorzystać ten fikcyjny widok, ustawienie go na niską liczbę „zresetuje” rozmiar dopasowania.
Vojto
7

Dla każdego, kto chce więcej kodu, oto pełne rozwiązanie, którego użyłem. Dzięki Corbin Dunn za wskazanie mi właściwego kierunku.

Musiałem ustawić wysokość głównie w odniesieniu do tego, jak wysoko NSTextVieww moimNSTableViewCell .

W mojej podklasie NSViewControllertymczasowo tworzę nową komórkę, dzwoniącoutlineView:viewForTableColumn:item:

- (CGFloat)outlineView:(NSOutlineView *)outlineView heightOfRowByItem:(id)item
{
    NSTableColumn *tabCol = [[outlineView tableColumns] objectAtIndex:0];
    IBAnnotationTableViewCell *tableViewCell = (IBAnnotationTableViewCell*)[self outlineView:outlineView viewForTableColumn:tabCol item:item];
    float height = [tableViewCell getHeightOfCell];
    return height;
}

- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
    IBAnnotationTableViewCell *tableViewCell = [outlineView makeViewWithIdentifier:@"AnnotationTableViewCell" owner:self];
    PDFAnnotation *annotation = (PDFAnnotation *)item;
    [tableViewCell setupWithPDFAnnotation:annotation];
    return tableViewCell;
}

W moim, IBAnnotationTableViewCellktóry jest kontrolerem mojej komórki (podklasy NSTableCellView), mam metodę konfiguracji

-(void)setupWithPDFAnnotation:(PDFAnnotation*)annotation;

który ustawia wszystkie wyloty i ustawia tekst z moich adnotacji PDF. Teraz mogę „łatwo” obliczyć wysokość używając:

-(float)getHeightOfCell
{
    return [self getHeightOfContentTextView] + 60;
}

-(float)getHeightOfContentTextView
{
    NSDictionary *attributes = [NSDictionary dictionaryWithObjectsAndKeys:[self.contentTextView font],NSFontAttributeName,nil];
    NSAttributedString *attributedString = [[NSAttributedString alloc] initWithString:[self.contentTextView string] attributes:attributes];
    CGFloat height = [self heightForWidth: [self.contentTextView frame].size.width forString:attributedString];
    return height;
}

.

- (NSSize)sizeForWidth:(float)width height:(float)height forString:(NSAttributedString*)string
{
    NSInteger gNSStringGeometricsTypesetterBehavior = NSTypesetterLatestBehavior ;
    NSSize answer = NSZeroSize ;
    if ([string length] > 0) {
        // Checking for empty string is necessary since Layout Manager will give the nominal
        // height of one line if length is 0.  Our API specifies 0.0 for an empty string.
        NSSize size = NSMakeSize(width, height) ;
        NSTextContainer *textContainer = [[NSTextContainer alloc] initWithContainerSize:size] ;
        NSTextStorage *textStorage = [[NSTextStorage alloc] initWithAttributedString:string] ;
        NSLayoutManager *layoutManager = [[NSLayoutManager alloc] init] ;
        [layoutManager addTextContainer:textContainer] ;
        [textStorage addLayoutManager:layoutManager] ;
        [layoutManager setHyphenationFactor:0.0] ;
        if (gNSStringGeometricsTypesetterBehavior != NSTypesetterLatestBehavior) {
            [layoutManager setTypesetterBehavior:gNSStringGeometricsTypesetterBehavior] ;
        }
        // NSLayoutManager is lazy, so we need the following kludge to force layout:
        [layoutManager glyphRangeForTextContainer:textContainer] ;

        answer = [layoutManager usedRectForTextContainer:textContainer].size ;

        // Adjust if there is extra height for the cursor
        NSSize extraLineSize = [layoutManager extraLineFragmentRect].size ;
        if (extraLineSize.height > 0) {
            answer.height -= extraLineSize.height ;
        }

        // In case we changed it above, set typesetterBehavior back
        // to the default value.
        gNSStringGeometricsTypesetterBehavior = NSTypesetterLatestBehavior ;
    }

    return answer ;
}

.

- (float)heightForWidth:(float)width forString:(NSAttributedString*)string
{
    return [self sizeForWidth:width height:FLT_MAX forString:string].height ;
}
Sunkas
źródło
Gdzie jest heightForWidth: forString: zaimplementowane?
ZS,
Przepraszam za to. Dodałem to do odpowiedzi. Próbowałem znaleźć oryginalny wpis SO, z którego go otrzymałem, ale nie mogłem go znaleźć.
Sunkas
1
Dzięki! To prawie działa dla mnie, ale daje mi niedokładne wyniki. W moim przypadku szerokość, którą podaję do NSTextContainer, wydaje się nieprawidłowa. Czy używasz układu automatycznego do definiowania widoków podrzędnych swojego NSTableViewCell? Skąd się bierze szerokość „self.contentTextView”?
ZS
Opublikowałem pytanie dotyczące mojego problemu tutaj: stackoverflow.com/questions/22929441/…
ZS
3

Szukałem rozwiązania od dłuższego czasu i wpadłem na takie, które w moim przypadku świetnie się sprawdza:

- (double)tableView:(NSTableView *)tableView heightOfRow:(long)row
{
    if (tableView == self.tableViewTodo)
    {
        CKRecord *record = [self.arrayTodoItemsFiltered objectAtIndex:row];
        NSString *text = record[@"title"];

        double someWidth = self.tableViewTodo.frame.size.width;
        NSFont *font = [NSFont fontWithName:@"Palatino-Roman" size:13.0];
        NSDictionary *attrsDictionary =
        [NSDictionary dictionaryWithObject:font
                                    forKey:NSFontAttributeName];
        NSAttributedString *attrString =
        [[NSAttributedString alloc] initWithString:text
                                        attributes:attrsDictionary];

        NSRect frame = NSMakeRect(0, 0, someWidth, MAXFLOAT);
        NSTextView *tv = [[NSTextView alloc] initWithFrame:frame];
        [[tv textStorage] setAttributedString:attrString];
        [tv setHorizontallyResizable:NO];
        [tv sizeToFit];

        double height = tv.frame.size.height + 20;

        return height;
    }

    else
    {
        return 18;
    }
}
vomako
źródło
W moim przypadku chciałem rozszerzyć daną kolumnę w pionie, aby tekst, który wyświetlam na tej etykiecie, pasował do wszystkich. Więc biorę tę kolumnę i biorę z niej czcionkę i szerokość.
Klajd Deda
3

Ponieważ używam niestandardowego NSTableCellViewi mam dostęp do NSTextFieldmojego rozwiązania było dodanie metody NSTextField.

@implementation NSTextField (IDDAppKit)

- (CGFloat)heightForWidth:(CGFloat)width {
    CGSize size = NSMakeSize(width, 0);
    NSFont*  font = self.font;
    NSDictionary*  attributesDictionary = [NSDictionary dictionaryWithObject:font forKey:NSFontAttributeName];
    NSRect bounds = [self.stringValue boundingRectWithSize:size options:NSStringDrawingUsesLineFragmentOrigin|NSStringDrawingUsesFontLeading attributes:attributesDictionary];

    return bounds.size.height;
}

@end
Klajd Deda
źródło
Dzięki! Jesteś moim wybawcą! Tylko to sprawia, że ​​działa poprawnie. Spędziłem cały dzień, żeby to rozgryźć.
Tommy
2

Oto, co zrobiłem, aby to naprawić:

Źródło: zajrzyj do dokumentacji XCode, w sekcji „wysokość wiersza nstableview”. Znajdziesz przykładowy kod źródłowy o nazwie „TableViewVariableRowHeights / TableViewVariableRowHeightsAppDelegate.m”

(Uwaga: patrzę na kolumnę 1 w widoku tabeli, musisz dostosować, aby szukać gdzie indziej)

w Delegate.h

IBOutlet NSTableView            *ideaTableView;

w Delegate. m

widok tabeli deleguje kontrolę wysokości wiersza

    - (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row {
    // Grab the fully prepared cell with our content filled in. Note that in IB the cell's Layout is set to Wraps.
    NSCell *cell = [ideaTableView preparedCellAtColumn:1 row:row];

    // See how tall it naturally would want to be if given a restricted with, but unbound height
    CGFloat theWidth = [[[ideaTableView tableColumns] objectAtIndex:1] width];
    NSRect constrainedBounds = NSMakeRect(0, 0, theWidth, CGFLOAT_MAX);
    NSSize naturalSize = [cell cellSizeForBounds:constrainedBounds];

    // compute and return row height
    CGFloat result;
    // Make sure we have a minimum height -- use the table's set height as the minimum.
    if (naturalSize.height > [ideaTableView rowHeight]) {
        result = naturalSize.height;
    } else {
        result = [ideaTableView rowHeight];
    }
    return result;
}

potrzebujesz tego również, aby wpłynąć na nową wysokość wiersza (metoda delegowana)

- (void)controlTextDidEndEditing:(NSNotification *)aNotification
{
    [ideaTableView reloadData];
}

Mam nadzieję, że to pomoże.

Ostatnia uwaga: to nie obsługuje zmiany szerokości kolumny.

laurent
źródło
Rządzisz! :) Dziękuję Ci.
flagman
4
Niestety, ten przykładowy kod Apple (który jest obecnie oznaczony jako wersja 1.1) używa tabeli opartej na komórkach, a nie tabeli opartej na widoku (czego dotyczy to pytanie). Wywołania kodu -[NSTableView preparedCellAtColumn:row], które według dokumentów „są dostępne tylko dla widoków tabel opartych na NSCell”. Użycie tej metody w tabeli opartej na widoku powoduje wygenerowanie tego dziennika w czasie wykonywania: „Błąd NSTableView oparty na widoku: wywołano preparowanyCellAtColumn: wiersz:. Proszę zarejestrować błąd z zapisem wstecznym z tego dziennika lub przestać używać tej metody”.
Ashley
1

Oto rozwiązanie oparte na odpowiedzi JanApothekera, zmodyfikowane, ponieważ cellView.fittingSize.heightnie zwracało mi prawidłowej wysokości. W moim przypadku używam standard NSTableCellView,NSAttributedString dla komórki textField tekst, a pojedynczą tabelę kolumnowej z ograniczeniami dla komórki zestaw textField w IB.

Moim zdaniem kontroler oświadczam:

var tableViewCellForSizing: NSTableCellView?

W widokuDidLoad ():

tableViewCellForSizing = tableView.make(withIdentifier: "My Identifier", owner: self) as? NSTableCellView

Na koniec dla metody delegata tableView:

func tableView(_ tableView: NSTableView, heightOfRow row: Int) -> CGFloat {
    guard let tableCellView = tableViewCellForSizing else { return minimumCellHeight }

    tableCellView.textField?.attributedStringValue = attributedString[row]
    if let height = tableCellView.textField?.fittingSize.height, height > 0 {
        return height
    }

    return minimumCellHeight
}

mimimumCellHeightjest stałą ustawioną na 30 do tworzenia kopii zapasowych, ale nigdy nie jest używana. attributedStringsto moja tablica modeliNSAttributedString .

Działa to idealnie na moje potrzeby. Dzięki za wszystkie poprzednie odpowiedzi, które wskazały mi właściwy kierunek dla tego brzydkiego problemu.

jbaraga
źródło
1
Bardzo dobrze. Jeden problem. Tabela nie może być edytowalna lub textfield.fittingSize.height nie będzie działać i zwróci zero. Ustaw table.isEditable = false w viewdidload
jiminybob99
0

To brzmi jak coś, co musiałem zrobić wcześniej. Chciałbym móc powiedzieć, że wymyśliłem proste, eleganckie rozwiązanie, ale niestety nie. Nie z powodu braku prób. Jak już zauważyłeś, potrzeba, aby UITableView znać wysokość przed zbudowaniem komórek, naprawdę sprawia, że ​​wszystko wydaje się dość okrągłe.

Moim najlepszym rozwiązaniem było przeniesienie logiki do komórki, ponieważ przynajmniej mogłem wyodrębnić klasę potrzebną do zrozumienia, jak układają się komórki. Metoda taka jak

+ (CGFloat) heightForStory:(Story*) story

będzie w stanie określić, jak wysoka musi być komórka. Oczywiście wymagało to pomiaru tekstu itp. W niektórych przypadkach wymyśliłem sposoby buforowania informacji uzyskanych za pomocą tej metody, które można było następnie wykorzystać podczas tworzenia komórki. To było najlepsze, co wymyśliłem. Jest to irytujący problem, chociaż wydaje się, że powinna istnieć lepsza odpowiedź.

włóczęga
źródło