AMcoder - javascript, python, java, html, php, sql

iOS. տողերի բարձրությունների նախնական հաշվարկ UITableView-ի համար

Ես ամիսներ շարունակ պայքարում եմ դրա հետ իմ նախագծում:

Ահա գործարքը. ես ունեմ UITableView՝ ընդամենը 1 հատվածով, բայց UITableViewCells-ի բարձրությունները տարբերվում են: Յուրաքանչյուր UITableViewCell ներկայացնում է օբյեկտ, և նոր օբյեկտները մշտապես հասանելի են դառնում և տեղադրվում UITableView-ում: Աղյուսակում ցուցադրվող նոր օբյեկտի բարձրությունը արդյունավետորեն հայտնաբերելու միակ միջոցը այն մեկ անգամ նկարելն է (գործարկեք կոդը, որը նկարում է UITableViewCell-ը և նայեք, թե որն է ստացված բարձրությունը):

Ահ, բայց խնդիրը կա: UITableView պատվիրակության մեթոդը tableView:heightForRowAtIndexPath: կոչվում է ՆԱԽԽԵ բջիջը առաջին անգամ նկարելը: Սա իմաստ ունի. աղյուսակը ցանկանում է տեղադրել բջիջները նախքան դրանք նկարելը:

Ես շատ փորձեր եմ արել և կարող եմ գտնել միայն 2 տարբերակ, որոնք երկուսն էլ ունեն հիմնական բացասական կողմեր.

  1. Եթե ​​աղյուսակում ցուցադրվող նոր օբյեկտը նախկինում չի երևացել, պարզապես «կռահեք» բարձրությունը և ավելի ուշ (բջջը նկարելուց հետո) չափեք բջիջը, ըստ անհրաժեշտության: Այնուամենայնիվ, սա խնդիրներ է առաջացնում ոլորման հետ կապված, քանի որ երբ օգտատերը դադարում է ոլորել, կարող է պատահել, որ մեկ կամ մի քանի բջիջների չափսերը պետք է չափափոխվեն ճիշտ բարձրության վրա, ինչը վատ օգտվողի փորձ է ստեղծում, քանի որ աղյուսակը տեղաշարժվում է և նորից կազմակերպվում:
  2. Նախապես հաշվարկեք օբյեկտի բարձրությունը՝ «փորձարկելով» օբյեկտը, նախքան այն տեղադրելը UITableView-ում: Երբ նոր օբյեկտը հասանելի դառնա, ստեղծեք «կեղծ» UITableViewCell և նկարեք այն էկրանից դուրս՝ այդպիսով հաշվարկելով օբյեկտի բարձրությունը և պահելով այն ավելի ուշ: Սրա խնդիրն այն է, որ, իհարկե, մենք կարող ենք կատարել միայն բարձրության թեստավորում հիմնական թելի վրա (քանի որ մենք պետք է նկարենք), ինչը մեծ ուշացում է առաջացնում հավելվածում:

Իմ լուծումը մինչ այժմ եղել է օգտագործել #2-ը, բայց փորձել եմ մեղմել խնդիրը՝ այնպես անելով, որ բարձրության թեստերը տեղի ունենան միայն վայրկյանի 1/4-ը, ինչը օգնում է «բաց թողնել» թեստը, որպեսզի հիմնական շարանը շատ կողպված չէ: Սակայն լուծումը աննման է և դեռևս առաջացնում է հետաձգման խնդիրներ, հատկապես հին սարքերում: Հետաձգումը բավականաչափ վատ է, որ ես իսկապես ավելի լավ լուծման կարիք ունեմ:


  • Միգուցե լավ կլինի, եթե բացատրեք, թե որն է նոր օբյեկտը, եթե բարձրությունը կարելի է հաշվարկել, առանց իրականում այն ​​գծելու: 22.03.2012
  • Ոչ: Չի կարող: Մուտքային օբյեկտը շատ բարդ օբյեկտ է, սովորական օբյեկտ, որը բաղկացած է բազմաթիվ տարբեր շարժական մասերից: Հավատացեք ինձ, սա նույնպես իմ առաջին միտքն էր, և ես, ամենայն հավանականությամբ, կանեի դա, եթե կարողանայի: Իրականում, ես շաբաթներ էի ծախսել՝ փորձելով ստեղծել լավ գուշակության ալգորիթմ (#1-ին, իմ գրառման մեջ): 22.03.2012

Պատասխանները:


1

Բարձրությունը հաշվարկելու համար սա և այս պատասխանը առաջարկում է, որ դուք կարող եք նկարել էկրանից դուրս ֆոնային շարանը՝ օգտագործելով CGLayer: Կցել iOS փաստաթղթերին CGLayer-ին:

Եվ բարձրությունը քեշավորելու համար՝ կախված որոշ տվյալների id-ից, որոնք ցուցադրվում են բջիջում, կարող եք օգտագործել հետևյալ ծածկագիրը.

-(CGFloat)tableView:(UITableView*)tableView heightForRowAtIndexPath:(NSIndexPath*)indexPath
{
    NSString* objectId = [self getObjectIdForPath:indexPath];
    if (![self->idToCellHeight objectForKey: objectId])
    {
        CGFloat height = [object calculateHeightForId:objectId];
        [self->idToCellHeight setObject:[NSNumber numberWithFloat:height] forKey: objectId];
    }

    return [[self->idToCellHeight objectForKey:objectId] floatValue];
}

Իհարկե, առաջին խաղարկությունը դեռ պետք է կատարվի առանց ճշգրիտ բարձրությունը իմանալու, բայց եթե դուք չեք կարող հաշվարկել բարձրությունը ցուցադրված տվյալների հիման վրա, ապա լուծում չկա:

22.03.2012
  • Իհարկե, ես այս կերպ արդեն պահպանում եմ/քեշում եմ օբյեկտների բարձրությունները։ Գրառումը էկրանից դուրս ֆոնային թեմայի վրա նկարելը կատարյալ լուծում կլինի, բացառությամբ, որ ես կարծես թե չեմ գտնում որևէ ռեսուրս, թե ինչպես դա աշխատեցնել UIKit-ի հետ: Օբյեկտի բարձրությունը ստուգելու համար ես ստեղծում եմ հատուկ UITableViewCell ենթադասի օրինակ, որն ունի մի շարք UIKit բաղադրիչներ (UILabel, UIImageView և այլն): Ամեն անգամ, երբ փորձում եմ այս նկարչական գործողությունը կատարել ֆոնային շղթայի վրա, ես խափանում եմ: ... 22.03.2012
  • UIKit-ը ընդհանուր առմամբ անվտանգ չէ թելերից, օրինակ. UIKit մեթոդները ոչ հիմնական շղթաների վրա կանչելը կշփոթեցնի մատուցման շարժիչը, որը միաժամանակ թարմացնում է UI-ը հիմնական շղթայից: Այնուամենայնիվ, UIKit-ի որոշ մեթոդներ iOS 4.0-ում դարձել են թեման անվտանգ: Դիտեք այս գրառումը՝ cocoabuilder.com/archive/ կակաո/ 23.03.2012
  • Նաև այս հղումը՝ stackoverflow.com/questions/6087068/thread-safe- uikit-methods և Apple-ի փաստաթղթեր այս թեմայի վերաբերյալ՝ developer.apple.com/library/ios/#releasenotes/General/ Այսպիսով, ես ենթադրում եմ, որ ձեր դեպքում պետք է պարզել, թե որ UIKit մեթոդները կարող եք օգտագործել ֆոնային շարանը նկարելու համար: Ճիշտ է, դա հնարավոր չէ, եթե ձեր կոդը օգտագործում է դրանցից շատերը, և դրանք հեշտությամբ չեն կարող փոխարինվել շղթաների համար անվտանգ համարժեքներով: 23.03.2012
  • Շատ ու շատ աշխատանքից հետո ես կարողացա օգտագործել պատշաճ թելերով ապահով UIKit նյութեր՝ նախնական հաշվարկն իրականացնելու համար: Major PITA, բայց ի վերջո արժե այն: Ես սա նշում եմ որպես ընդունված պատասխան: 19.04.2012

  • 2

    Մտածեցի, որ կմասնակցեմ դրան: UITableView-ի համար տողերի բարձրությունների նախնական հաշվարկը լիովին հնարավոր է և շատ լավ է աշխատում օպտիմալացման համար:

    Որպես էկրանից դուրս գծագրման այլընտրանք, շատ լավ է օգտագործել դասերի sizeThatFits մեթոդները, ինչպիսիք են UILabel-ը՝ բարձրությունները որոշելու համար:

    Զգուշացումն այն է, որ գրեթե բոլոր UIView առնչվող մեթոդները պետք է կատարվեն հիմնական թելի վրա:

    Ես կբացատրեմ իմ մոտեցումը, որն է՝ ստեղծել չափերի տեսք, որը ես օգտագործում եմ բարձրության հաշվարկի համար:

    Չափերի տեսքը կարող է ստեղծվել հիմնական թեմայից դուրս.

    UILabel *mySizingLabel = [[UILabel alloc] init];

    Այնուամենայնիվ, չափը որոշելիս դա պետք է արվի հիմնական թելի վրա: Զգույշ եղեք, որ չօգտագործեք dispatch_async կամ [[NSOperationQueue] mainQueue]: Սա, օրինակ, չի աշխատի.

    __block CGSize size;
    dispatch_async(dispatch_get_main_queue(), ^{
        size = [mySizingLabel sizeThatFits:CGSizeMake(CGFLOAT_MAX, CGFLOAT_MAX)];
    }];
    
    CGFloat myCellHeight = size.height;
    

    Դա պայմանավորված է նրանով, որ տողը, որը նշանակում է myCellHeight-ը, կաշխատի sizeThatFits-ից առաջ՝ դրանով իսկ տալով անհեթեթ արժեք:

    Փոխարենը, անհրաժեշտ է սպասել հիմնական թեմայի վրա, մինչև sizeThatFits-ը վերադառնա: Դա կարելի է անել՝ օգտագործելով performSelectorOnMainThread-ը, իսկ waitը սահմանված է YES: Պարամետրերը կարող են փոխանցվել և դուրս գալ այդ մեթոդից՝ օգտագործելով NSMutableArray:

    Այս մոտեցումը մեծ առավելություն ունի նրանով, որ դուք կարող եք օգտվել UIView դասերի կողմից առաջարկվող չափերի բնորոշ մեթոդներից՝ առանց էկրանից դուրս նկարելու՝ օգտագործելով հատուկ գրաֆիկական համատեքստ:

    Մեկ այլ բան, մի գայթակղվեք օգտագործել UIKit հավելումը sizeWithFont: Բացի Մայք Ուելերի կողմից ընդգծված խնդիրներից "Դուք դա սխալ եք անում #2. պիտակների չափագրում -[NSString sizeWithFont:...]"-ով, նույն նախազգուշացումը կիրառվում է, որ այս մեթոդը նույնպես պետք է գործարկվի հիմնականում՝

    NSString UIKit Additions Reference

    Այս դասի ընդլայնման մեջ նկարագրված մեթոդները պետք է օգտագործվեն ձեր հավելվածի հիմնական թեմայից:

    20.06.2013
  • Ինչու՞ պարզապես չօգտագործել dispatch_sync-ը dispatch_async-ի փոխարեն: 06.02.2015

  • 3

    Կփորձեմ համառոտ բացատրել.

    Ինչպես նշում է Max MacLeod-ը, երբ ձեր տվյալների բազան պատրաստ է, հաշվարկեք տողի բարձրությունը ասինխրոն կերպով՝ օգտագործելով

    -(void)calculateAsyncRowHeights {
        dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
    
            UITableView *tableView=[self tableView];
    
            for(ManagedObject *o in _tableData) {
                CGFloat height=[self calculateRowHeight:tableView withObject:o]; //this is the method that calculates row heights. This is a seperate method because when necessary I call it in - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
                [o setRowHeight:height]; //I set rowHeight property of my model object
            }
    
            dispatch_async(dispatch_get_main_queue(), ^{
    
            });
        });
    }
    

    In - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath ստուգեք, թե արդյոք մոդելի օբյեկտն ունի տողի բարձրությունը արդեն հաշվարկված: Եթե ​​այո, վերադարձրեք այն, եթե ոչ, ապա հաշվարկեք այն [self accountRowHeight:tableView withObject:o]-ով; մեթոդը և վերադարձնել դրա վերադարձի արժեքը:

    Այն աշխատում է հմայքի պես և լուծեց իմ կատարողական բոլոր խնդիրները:

    13.01.2014

    4

    Ինձ թվում է, որ դուք պետք է ստեղծեք NSMutableArray, որը պարունակում է NSNumber տարրեր, որոնք համապատասխանում են աղյուսակում գոյություն ունեցող բջիջների հաշվարկված բարձրություններին: Երբ դուք ստանում եք նոր բջիջ, որը պետք է ավելացվի աղյուսակին, հաշվարկեք տարրի բարձրությունը և այնուհետև տեղադրեք բարձրությունը փոփոխվող զանգվածի մեջ ճիշտ դիրքում, կամ այլ կերպ ասած՝ այն նույն դիրքում, որտեղ այն կզբաղեցնի: աղյուսակը, այնուհետև վերաբեռնել աղյուսակի տվյալները:

    Այսպիսով, դուք ստիպված չեք լինի վերահաշվարկել որևէ բարձրություն, դուք պարզապես կհղեք օբյեկտը ձեր ինդեքսային ճանապարհի տողի ինդեքսում:

    22.03.2012
  • Խնդիրը չի RE-բարձրությունները հաշվարկելու մասին է... խոսքը ԱՌԱՋԻՆ հաշվարկի մասին է: Հաշվարկված բարձրություններն արդեն պահպանում եմ, առաջին հաշվարկից հետո, ինչպես նկարագրեցիր այստեղ։ Դուք ասացիք Երբ ստանում եք նոր բջիջ, որը պետք է ավելացվի աղյուսակում, հաշվարկեք տարրի բարձրությունը: ԴԱ այն մասն է, որը դժվարություններ է առաջացնում, սակայն: 22.03.2012
  • Ահ, ենթադրում եմ, որ կարոտել էի այն տեղը, որտեղ ասացիր, որ պահիր այն ավելի ուշ և մտածեցի, որ չափից շատ աշխատանք ես կատարում heightForRowAtIndexPath-ում, հիմար ես: 22.03.2012
  • Նոր նյութեր

    Օգտագործելով Fetch Vs Axios.Js-ը՝ HTTP հարցումներ կատարելու համար
    JavaScript-ը կարող է ցանցային հարցումներ ուղարկել սերվեր և բեռնել նոր տեղեկատվություն, երբ դա անհրաժեշտ լինի: Օրինակ, մենք կարող ենք օգտագործել ցանցային հարցումը պատվեր ներկայացնելու,..

    Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար
    Տիրապետել հանգստության արվեստին. մշակողի ուղեցույց՝ ճնշման տակ ծաղկելու համար Ինչպե՞ս հանգստացնել ձեր միտքը և աշխատեցնել ձեր պրոցեսորը: Ինչպես մնալ հանգիստ և զարգանալ ճնշման տակ...

    Մեքենայի ուսուցում բանկային և ֆինանսների ոլորտում
    Բարդ, խելացի անվտանգության համակարգերը և հաճախորդների սպասարկման պարզեցված ծառայությունները բիզնեսի հաջողության բանալին են: Ֆինանսական հաստատությունները, մասնավորապես, պետք է առաջ մնան կորի..

    Ես AI-ին հարցրի կյանքի իմաստը, այն ինչ ասում էր, ցնցող էր:
    Այն պահից ի վեր, երբ ես իմացա Արհեստական ​​ինտելեկտի մասին, ես հիացած էի այն բանով, թե ինչպես է այն կարողանում հասկանալ մարդկային նորմալ տեքստը, և այն կարող է առաջացնել իր սեփական արձագանքը դրա..

    Ինչպես սովորել կոդավորումը Python-ում վագրի պես:
    Սովորելու համար ծրագրավորման նոր լեզու ընտրելը բարդ է: Անկախ նրանից, թե դուք սկսնակ եք, թե առաջադեմ, դա օգնում է իմանալ, թե ինչ թեմաներ պետք է սովորել: Ծրագրավորման լեզվի հիմունքները, դրա..

    C++-ի օրական բիթ(ե) | Ամենաերկար պալինդրոմային ենթաշարը
    C++ #198-ի ամենօրյա բիթ(ե), Ընդհանուր հարցազրույցի խնդիր. Ամենաերկար պալինդրոմային ենթատող: Այսօր մենք կանդրադառնանք հարցազրույցի ընդհանուր խնդրին. Ամենաերկար palindromic substring...

    Kydavra ICAReducer՝ ձեր տվյալների ծավալայինությունը նվազեցնելու համար
    Ի՞նչ է ICAReducer-ը: ICAReducer-ն աշխատում է հետևյալ կերպ. այն նվազեցնում է նրանց միջև բարձր փոխկապակցված հատկանիշները մինչև մեկ սյունակ: Բավականին նման է PCAreducer-ին, չնայած այն..