| ÕªÒª£ºÔÚ½«UITableView+FDTemplateLayoutCell×Ô¶¯Ëã¸ß¹¤¾ß¸üÐÂÖÁ1.2°æ±¾Ö®ºó£¬°Ù¶ÈÖªµÀiOSÍŶӶÔUITableViewCellÀûÓÃAutoLayout×Ô¶¯¸ß¶È¼ÆËãºÍUITableView»¬¶¯ÓÅ»¯½øÐÐÁË×ܽᣬÒÔ¼°RunLoopʵ¼ù¼¼ÇÉ¡£
ǰÑÔ
ÕâÆªÎÄÕÂÊÇÎÒºÍÎÒÃÇÍŶÓ×î½ü¶ÔUITableViewCellÀûÓÃAutoLayout×Ô¶¯¸ß¶È¼ÆËãºÍUITableView»¬¶¯ÓÅ»¯µÄÒ»¸ö×ܽᡣ´ÓÕâÆªÎÄÕÂÀÄã¿ÉÒÔ¶Áµ½£º
UITableView¸ß¶È¼ÆËãºÍ¹ÀËãµÄ»úÖÆ
²»Í¬iOSϵͳÔڸ߶ȼÆËãÉϵIJîÒì
iOS8 self-sizing cell
UITableView+FDTemplateLayoutCellÈçºÎÓÃÒ»¾ä»°½â¾ö¸ß¶ÈÎÊÌâ
UITableView+FDTemplateLayoutCellÖжÔRunLoopµÄʹÓü¼ÇÉ
UITableViewCell¸ß¶È¼ÆËã
rowHeight
UITableViewÊÇÎÒÃÇÔÙÊìϤ²»¹ýµÄÊÓͼÁË£¬ËüµÄdelegateºÍdata source»Øµ÷²»ÖªÐ´Á˶àÉٴΣ¬Ò²²»ÃâÓöµ½UITableViewCell¸ß¶È¼ÆËãµÄÊ¡£UITableViewѯÎÊcell¸ß¶ÈÓÐÁ½ÖÖ·½Ê½¡£Ò»ÖÖÊÇÕë¶ÔËùÓÐCell¾ßÓй̶¨¸ß¶ÈµÄÇé¿ö£¬Í¨¹ý£º
self.tableView.rowHeight = 88; |
ÉÏÃæµÄ´úÂëÖ¸¶¨ÁËÒ»¸öËùÓÐcell¶¼ÊÇ88¸ß¶ÈµÄUITableView£¬¶ÔÓÚ¶¨¸ßÐèÇóµÄ±í¸ñ£¬Ç¿ÁÒ½¨ÒéʹÓÃÕâÖÖ£¨¶ø·ÇÏÂÃæµÄ£©·½Ê½±£Ö¤²»±ØÒªµÄ¸ß¶È¼ÆËãºÍµ÷Óá£rowHeightÊôÐÔµÄĬÈÏÖµÊÇ44£¬ËùÒÔÒ»¸ö¿ÕµÄUITableViewÏÔʾ³ÉÄǸöÑù×Ó¡£
ÁíÒ»ÖÖ·½Ê½¾ÍÊÇʵÏÖUITableViewDelegateÖеģº
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { // return xxx } |
ÐèҪעÒâµÄÊÇ£¬ÊµÏÖÁËÕâ¸ö·½·¨ºó£¬rowHeightµÄÉèÖý«ÎÞЧ¡£ËùÒÔ£¬Õâ¸ö·½·¨ÊÊÓÃÓÚ¾ßÓжàÖÖcell¸ß¶ÈµÄUITableView¡£
estimatedRowHeight
Õâ¸öÊôÐÔiOS7¾Í³öÏÖÁË£¬ÎĵµÊÇÕâôÃèÊöËüµÄ×÷Óõģº
If the table contains variable height rows, it might be expensive to calculate all their heights when the table loads. Using estimation allows you to defer some of the cost of geometry calculation from load time to scrolling time.
¶÷£¬ÌýÉÏÈ¥Âù¿¿Æ×µÄ¡£ÎÒÃÇÖªµÀ£¬UITableViewÊǸöUIScrollView£¬¾ÍÏñƽʱʹÓÃUIScrollViewÒ»Ñù£¬¼ÓÔØÊ±Ö¸¶¨contentSizeºóËü²ÅÄܸù¾Ý×Ô¼ºµÄbounds¡¢contentInset¡¢contentOffsetµÈÊôÐÔ¹²Í¬¾ö¶¨ÊÇ·ñ¿ÉÒÔ»¬¶¯ÒÔ¼°¹ö¶¯ÌõµÄ³¤¶È¡£¶øUITableViewÔÚÒ»¿ªÊ¼²¢²»ÖªµÀ×Ô¼º»á±»Ìî³ä¶àÉÙÄÚÈÝ£¬ÓÚÊÇѯÎÊdata source¸öÊýºÍ´´½¨cell£¬Í¬Ê±Ñ¯ÎÊdelegateÕâЩcellÓ¦¸ÃÏÔʾµÄ¸ß¶È£¬Õâ¾ÍÔì³ÉËüÔÚ¼ÓÔØµÄʱºòÀË·ÑÁ˶àÓàµÄ¼ÆËãÔÚÆÁÄ»Íâ±ßµÄcellÉÏ¡£ºÍÉÏÃæµÄrowHeightºÜÀàËÆ£¬ÉèÖÃÕâ¸ö¹ÀËã¸ß¶ÈÓÐÁ½ÖÖ·½·¨£º
self.tableView.estimatedRowHeight = 88; // or - (CGFloat)tableView:(UITableView *)tableView estimatedHeightForRowAtIndexPath:(NSIndexPath *)indexPath { // return xxx } |
ÓÐËù²»Í¬µÄÊÇ£¬¼´Ê¹Ãæ¶ÔÖÖÀ಻ͬµÄcell£¬ÎÒÃÇÒÀÈ»¿ÉÒÔʹÓüòµ¥µÄestimatedRowHeightÊôÐÔ¸³Öµ£¬Ö»ÒªÕûÌå¹ÀËãÖµ½Ó½ü¾Í¿ÉÒÔ£¬±ÈÈç´ó¸ÅÓÐÒ»°ëcell¸ß¶ÈÊÇ44£¬ Ò»°ëcell¸ß¶ÈÊÇ88£¬ ÄǾͿÉÒÔ¹ÀËãÒ»¸ö66£¬»ù±¾·ûºÏÔ¤ÆÚ¡£
˵ÍêÁ˹ÀËã¸ß¶ÈµÄ»ù±¾Ê¹Ó㬿ÉÒÔ¿ªÊ¼Í²ÛÁË£º
- ÉèÖùÀËã¸ß¶Èºó£¬contentSize.height¸ù¾Ý¡°cell¹ÀËãÖµ x cell¸öÊý¡±¼ÆË㣬Õâ¾Íµ¼Ö¹ö¶¯ÌõµÄ´óС´¦ÓÚ²»Îȶ¨µÄ״̬£¬contentSize»áËæ×Źö¶¯´Ó¹ÀËã¸ß¶ÈÂýÂýÌæ»»³ÉÕæÊµ¸ß¶È£¬ÈâÑۿɼû¹ö¶¯ÌõͻȻ±ä»¯ÉõÖÁ¡°ÌøÔ¾¡±¡£
-
ÈôÊÇÓÐÉè¼Æ²»ºÃµÄÏÂÀˢлòÉÏÀ¼ÓÔØ¿Ø¼þ£¬»òÊÇKVOÁËcontentSize»òcontentOffsetÊôÐÔ£¬ÓпÉÄÜʹ±í¸ñ»¬¶¯Ê±Ìø¶¯¡£
-
¹ÀËã¸ß¶ÈÉè¼Æ³õÖÔÊǺõģ¬ÈüÓÔØËٶȸü¿ì£¬ÄÇÆ¾É¶ÒªÈ¥ÇÖº¦»¬¶¯µÄÁ÷³©ÐÔÄØ£¬Óû§¿ÉÄܶԽøÈëÒ³ÃæÊ±¶àÁãµã¼¸Ãë¼ÓÔØÊ±¼ä¸Ð¾õ²»´ó£¬µ«ÊÇ»¬¶¯Ê±ÊµÊ±¼ÆËã¸ß¶È´øÀ´µÄ¿¨¶ÙÊÇÃ÷ÏÔÄÜÌåÑéµ½µÄ£¬¸öÈ˾õµÃ»¹²»ÈçÒ»¿ªÊ¼¶¼ËãºÃÁËÄØ£¨iOS 8¸ü¹ý·Ö£¬¼´Ê¹¶¼ËãºÃÁËÒ²»á±ß»®±ß¼ÆË㣩¡£
iOS8 self-sizing cell
¾ßÓж¯Ì¬¸ß¶ÈÄÚÈݵÄcellÒ»Ö±ÊǸöÍ·ÌÛµÄÎÊÌ⣬±ÈÈçÁÄÌìÆøÅݵÄcell£¬frame²¼¾Öʱ´úͨ³£ÊÇÓÃÊý¾ÝÄÚÈÝ·´Ëã¸ß¶È£º
CGFloat height = textHeightWithFont() + imageHeight + topMargin + bottomMargin + ...; |
¹©UITableViewDelegateµ÷ÓÃʱºÜ¿ÉÄÜÊǸöcellµÄÀà·½·¨£º
@interface BubbleCell : UITableViewCell + (CGFloat)heightWithEntity:(id)entity; @end |
¸÷ÖÖħ·¨margin¼ÓÉÏñîºÏÁËÆÁÄ»¿í¶È¡£
AutoLayoutʱ´úºÃÁ˲»ÉÙ£¬ÌṩÁË-systemLayoutSizeFittingSize:µÄAPI£¬ÔÚcontentViewÖÐÉèÖÃÔ¼Êøºó£¬¾ÍÄܼÆËã³ö׼ȷµÄÖµ£»È±µãÊǼÆËãËٶȿ϶¨Ã»ÓÐÊÖËã¿ì£¬¶øÇÒÕâÊǸöʵÀý·½·¨£¬ÐèҪά»¤×¨ÃÅΪ¼ÆËã¸ß¶È¶øÉúµÄtemplate layout cell£¬Ëü»¹ÒªÇóʹÓÃÕß¶ÔÔ¼ÊøÉèÖõıȽÏÊìÁ·£¬Òª±£Ö¤contentViewÄÚ²¿ÉÏÏÂ×óÓÒËùÓз½Ïò¶¼ÓÐÔ¼ÊøÖ§³Å£¬ÉèÖò»ºÏÀíµÄ»°¼ÆËãµÄ¸ß¶È¾Í³ÉÁË0¡£
ÕâÀﻹ²»µÃ²»Ìáµ½Ò»¸öUILabelµÄµ°ÌÛÎÊÌ⣬µ±UILabelÐÐÊý´óÓÚ0ʱ£¬ÐèÒªÖ¸¶¨preferredMaxLayoutWidthºóËü²ÅÖªµÀ×Ô¼ºÊ²Ã´Ê±ºò¸ÃÕÛÐС£ÕâÊǸö¡°¼¦Éúµ°µ°Éú¼¦¡±µÄÎÊÌ⣬ÒòΪUILabelÐèÒªÖªµÀsuperviewµÄ¿í¶È²ÅÄÜÕÛÐУ¬¶øsuperviewµÄ¿í¶È»¹ÒÀÕÌ×Å×Óview¿í¶ÈµÄÀÛ¼Ó²ÅÄÜÈ·¶¨¡£Õâ¸öÎÊÌâºÃÏñµ½iOS 8²ÅÄܹ»×Ô¶¯½â¾ö£¨²»¹ýÎÒÃÇÕÒµ½Á˽â¾ö·½°¸£©¡£
»Øµ½ÕýÌ⣬iOS 8 WWDCÖÐÍÆ³öÁËself-sizing cellµÄ¸ÅÄּÔÚÈÃcell×Ô¼º¸ºÔð×Ô¼ºµÄ¸ß¶È¼ÆË㣬ʹÓÃframe layoutºÍauto layout¶¼¿ÉÒÔÏíÊܵ½£º

Õâ¸öÌØÐÔÊ×ÏÈÒªÇóÊÇiOS 8£¬ÒªÊÇ×îµÍÖ§³ÖµÄϵͳ°æ±¾Ð¡ÓÚ8µÄ»°£¬»¹µÃÕë¶ÔÀϰ汾µ¥Ð´Ì×ÀÏʽµÄËã¸ß£¨‡å£©£¬²»¹ýÓõÄAPIµ½²»ÊÇÐÂÃæ¿×£º
self.tableView.estimatedRowHeight = 213; self.tableView.rowHeight = UITableViewAutomaticDimension; |
ÕâÀïÓÖ²»µÃ²»Í²ÛÁË£¬×Ô¶¯¼ÆËãrowHeight¸úestimatedRowHeightµ½µ×ÊÇÓÐʲô³ð£¬Èç¹û²»¼ÓÉϹÀËã¸ß¶ÈµÄÉèÖã¬×Ô¶¯Ëã¸ß¾ÍʧЧÁË¡£
PS£ºiOS 8ϵͳÖÐrowHeightµÄĬÈÏÖµÒѾÉèÖóÉÁËUITableViewAutomaticDimension£¬ËùÒÔµÚ¶þÐдúÂë¿ÉÒÔÊ¡ÂÔ¡£
ÎÊÌ⣺
Õâ¸ö×Ô¶¯Ëã¸ßÔÚpushµ½ÏÂÒ»¸öÒ³Ãæ»òÕßתÆÁʱ»á³öÏָ߶ÈÌØ±ð¹îÒìµÄÇé¿ö£¬²»¹ýÏÖÔڵİ汾ÐÞ¸´ÁË¡£
ÇóÒ»¸öÄÜÈÃ×îµÍÖ§³ÖiOS 8µÄ¹«Ë¾¡£
iOS 8³é·çµÄËã¸ß»úÖÆ
ÏàͬµÄ´úÂëÔÚiOS 7ºÍiOS 8ÉÏ»¬¶¯Ë³³©³Ì¶ÈÍêÈ«²»Í¬£¬iOS 8ĪÃûÆæÃîµÄ¿¨¡£ºÜ´óÒ»²¿·ÖÔÒòÊÇiOS 8ÉϵÄËã¸ß»úÖÆ´ó²»Ïàͬ£¬ÕâÊÇÎÒ×öµÄС²âÊÔ£º
Ñо¿ºó·¢ÏÖÕâô¶à´Î¶îÍâ¼ÆËãÓÐÏÂÃæµÄÔÒò£º
²»¿ªÆô¸ß¶È¹ÀËãʱ£¬UITableViewÉÏÀ´¾ÍÒª¶ÔËùÓÐcellµ÷ÓÃËã¸ßÀ´È·¶¨contentSize¡£
dequeueReusableCellWithIdentifier:forIndexPath: Ïà±È²»´ø¡°forIndexPath¡±µÄ°æ±¾»á¶àµ÷ÓÃÒ»´Î¸ß¶È¼ÆËã¡£
iOS 7¼ÆËã¸ß¶ÈºóÓС°»º´æ¡±»úÖÆ£¬²»»áÖØ¸´¼ÆË㣻¶øiOS 8²»ÂÛºÎʱ¶¼»áÖØÐ¼ÆËãcell¸ß¶È¡£
iOS 8°Ñ¸ß¶È¼ÆËã¸ã³ÉÕâ¸öÑù×Ó£¬´ÓWWDCÒ²µ¹ÊÇÄÜÕÒµ½µã½âÊÍ£¬cell±»ÈÏÎªËæÊ±¶¼¿ÉÄܸıä¸ß¶È£¨Èç´ÓÉèÖÃÖе÷Õû¶¯Ì¬×ÖÌå´óС£©£¬ËùÒÔÿ´Î»¬¶¯³öÀ´ºó¶¼ÒªÖØÐ¼ÆËã¸ß¶È¡£
˵ÁËÕâô¶à£¬¾¿¾¹ÓÐûÓмÈÄÜʡȥËã¸ß·³ÄÕ£¬ÓÖÄܱ£Ö¤Ë³³©µÄ»¬¶¯£¬»¹ÄÜÖ§³ÖiOS 6+µÄһվʽ½â¾ö·½°¸ÄØ£¿
UITableView+FDTemplateLayoutCell
ʹÓÃUITableView+FDTemplateLayoutCellÎÞÒÉÊǽâ¾öËã¸ßÎÊÌâµÄ×î¼Ñʵ¼ùÖ®Ò»£¬¼ÈÓÐiOS 8 self-sizing¹¦Äܼòµ¥µÄAPI£¬ÓÖ¿ÉÒÔ´ïµ½iOS7Á÷³©µÄ»¬¶¯Ð§¹û£¬»¹±£³ÖÁË×îµÍÖ§³ÖiOS6¡£
ʹÓÃÆðÀ´´ó¸ÅÊÇÕâÑù£º
#import <UITableView+FDTemplateLayoutCell.h> - (CGFloat)tableView:(UITableView *) tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { return [tableView fd_heightForCellWithIdentifier: @"identifer" cacheByIndexPath:indexPath configuration:^(id cell) { // ÅäÖà cell µÄÊý¾ÝÔ´£¬ºÍ "cellForRow" ¸ÉµÄÊÂÒ»Ö£¬±ÈÈ磺 cell.entity = self.feedEntities[indexPath.row]; }]; } |
дÍêÉÏÃæµÄ´úÂëºó£¬Äã¾ÍÒѾʹÓõ½ÁË£º
ºÍÿ¸öUITableViewCell ReuseIDÒ»Ò»¶ÔÓ¦µÄtemplate layout cell
Õâ¸öcellֻΪÁ˲μӸ߶ȼÆË㣬²»»áÕæµÄÏÔʾµ½ÆÁÄ»ÉÏ£»Ëüͨ¹ýUITableViewµÄ-dequeueCellForReuseIdentifier: ·½·¨lazy´´½¨²¢±£´æ£¬ËùÒÔÒªÇóÕâ¸öReuseID±ØÐëÒѾ±»×¢²áµ½ÁËUITableViewÖУ¬Ò²¾ÍÊÇ˵£¬ÒªÃ´ÊÇStoryboardÖеÄÔÐÍcell£¬ÒªÃ´¾ÍÊÇʹÓÃÁËUITableViewµÄ-registerClass:forCellReuseIdentifier:»ò-registerNib:forCellReuseIdentifier:ÆäÖÐÖ®Ò»µÄ×¢²á·½·¨¡£
¸ù¾ÝautolayoutÔ¼Êø×Ô¶¯¼ÆËã¸ß¶È
ʹÓÃÁËϵͳÔÚiOS 6¾ÍÌṩµÄAPI£º-systemLayoutSizeFittingSize:
¸ù¾Ýindex pathµÄÒ»Ì׸߶Ȼº´æ»úÖÆ
¼ÆËã³öµÄ¸ß¶È»á×Ô¶¯½øÐлº´æ£¬ËùÒÔ»¬¶¯Ê±Ã¿¸öcellÕæÕýµÄ¸ß¶È¼ÆËãÖ»»á·¢ÉúÒ»´Î£¬ºóÃæµÄ¸ß¶ÈѯÎʶ¼»áÃüÖлº´æ£¬¼õÉÙÁ˷dz£¿É¹ÛµÄ¶àÓà¼ÆËã¡£
×Ô¶¯µÄ»º´æÊ§Ð§»úÖÆ
ÎÞÐëµ£ÐÄÄãÊý¾ÝÔ´µÄ±ä»¯ÒýÆðµÄ»º´æÊ§Ð§£¬µ±µ÷ÓÃÈç-reloadData£¬-deleteRowsAtIndexPaths:withRowAnimation:µÈÈκÎÒ»¸ö´¥·¢ UITableView ˢлúÖÆµÄ·½·¨Ê±£¬ÒÑÓеĸ߶Ȼº´æ½«ÒÔ×îСµÄ´ú¼ÛÖ´ÐÐʧЧ¡£Èçɾ³ýÒ»¸öindexPathΪ[0:5]µÄcellʱ£¬[0:0] ~ [0:4]µÄ¸ß¶È»º´æ²»ÊÜÓ°Ï죬¶ø[0:5]ºóÃæËùÓеĻº´æÖµ¶¼ÏòÇ°ÒÆ¶¯Ò»¸öλÖá£×Ô¶¯»º´æÊ§Ð§»úÖÆ¶ÔUITableViewµÄ9¸ö¹«ÓÐAPI¶¼½øÐÐÁË·Ö±ðµÄ´¦Àí£¬ÒÔ±£Ö¤Ã»ÓÐÒ»´Î¶àÓàµÄ¸ß¶È¼ÆËã¡£
Ô¤»º´æ»úÖÆ
Ô¤»º´æ»úÖÆ½«ÔÚUITableViewûÓ묶¯µÄ¿ÕÏÐʱ¿ÌÖ´ÐУ¬¼ÆËãºÍ»º´æÄÇЩ»¹Ã»ÓÐÏÔʾµ½ÆÁÄ»ÖеÄcell£¬Õû¸ö»º´æ¹ý³ÌÍêȫûÓиÐÖª£¬ÕâʹµÃÍêÕûÁбíµÄ¸ß¶È¼ÆËã¼ÈûÓз¢ÉúÔÚ¼ÓÔØÊ±£¬ÓÖûÓз¢ÉúÔÚ»¬¶¯Ê±£¬Í¬Ê±±£Ö¤Á˼ÓÔØËٶȺͻ¬¶¯Á÷³©ÐÔ£¬ÏÂÎÄ»á×ÅÖØ½²ÏÂÕâ¿éµÄʵÏÖÔÀí¡£
ÎÒÃÇÔÚÉè¼ÆÕâ¸ö¹¤¾ßµÄAPIʱÕå×ÃÁ˷dz£³¤µÄʱ¼ä£¬¼ÈÒª±£Ö¤¹¦ÄܵÄÇ¿´ó£¬Ò²Òª±£Ö¤½Ó¿ÚµÄ¾«¼ò£¬Ò»Ðе÷Óñ³ºóÒþ²Ø×źܶ๦ÄÜ¡£
ÕâÒ»Ì×»º´æ»úÖÆÄܶԻ¬¶¯Æð¶à´óÓ°ÏìÄØ£¿³ýÁËÈâÑÛÄÜÃ÷ÏԵĸÐÖªµ½Í⣬ÎÒ»¹×öÁ˸öС²âÊÔ¡£Ò»¸öÓÐ54¸öÄÚÈݺ͸߶Ȳ»Í¬cellµÄtable view£¬´ÓÍ·»¬¶¯µ½Î²£¬ÔÙ´Ó⻬¶¯µ½Í·£¬iOS 8ϵͳÏ£¬iPhone 6£¬Ê¹ÓÃTime Profiler¼à²âËã¸ßº¯ÊýËù»¨·ÑµÄʱ¼ä£º
δʹÓûº´æAPI¡¢Î´Ê¹ÓùÀË㣬¹²»¨·Ñ877ms

ʹÓûº´æAPI¡¢¿ªÆô¹ÀË㣬¹²»¨·Ñ77ms

²âÊÔÊý¾ÝµÄ¾«¶ÈÏȲ»¹Ü£¬´ÓÁ¿¼¶ÉϾͲîÁËÒ»¸öÊýÁ¿¼¶£¬ËµÊµ»°×Ô¼ºÒ²Ã»Ïëµ½²î¾àÓÐÕâô´ó¡£
ͬʱ£¬¹¤¾ßҲ˳ÊÖ½â¾öÁË-preferredMaxLayoutWidthµÄÎÊÌ⣬ÔÚ¼ÆËã¸ß¶ÈǰÏòcontentView¼ÓÁËÒ»ÌõºÍtable view¿í¶ÈÏàͬµÄ¿í¶ÈÔ¼Êø£¬Ç¿ÐÐÈÃcontentViewÄÚ²¿µÄ¿Ø¼þÖªµÀÁË×Ô¼º¸¸viewµÄ¿í¶È£¬ÔÙ·´Ëã×Ô¼º±»Íâ½çÔ¼ÊøµÄ¿í¶È£¬ÆÆ³ý¡°¼¦Éúµ°µ°Éú¼¦¡±µÄÎÊÌ⣬ÕâÀï±È½Ïtricky£¬¾Í²»Õ¹¿ªËµÁË¡£ÏÂÃæËµËµÀûÓÃRunLoopÔ¤»º´æµÄʵÏÖ¡£
ÀûÓÃRunLoop¿ÕÏÐʱ¼äÖ´ÐÐÔ¤»º´æÈÎÎñ
FDTemplateLayoutCellµÄ¸ß¶ÈÔ¤»º´æÊÇÒ»¸öÓÅ»¯¹¦ÄÜ£¬ËüÒªÇóÒ³Ãæ´¦ÓÚ¿ÕÏÐ״̬ʱ²ÅÖ´ÐмÆË㣬µ±Óû§ÕýÔÚ»¬¶¯ÁбíʱÏÔÈ»²»Ó¦¸ÃÖ´ÐмÆËãÈÎÎñÓ°Ï컬¶¯ÌåÑé¡£
Ò»°ãÀ´Ëµ£¬Õâ¸ö¹¦ÄÜÒªñîºÏUITableViewµÄ»¬¶¯×´Ì¬²ÅÐУ¬µ«ÕâÖÖʵÏÖÊ®·Ö²»ÓÅÑÅÇÒ¿ÉÄÜÆÆ»µÍⲿµÄdelegate½á¹¹£¬µ«ºÃÔÚÎÒÃÇ»¹ÓÐRunLoopÕâ¸ö¹¤¾ß£¬Á˽âËüµÄÔËÐлúÖÆºó£¬¿ÉÒÔÓúܼòµ¥µÄ´úÂëʵÏÖÉÏÃæµÄ¹¦ÄÜ¡£
¿ÕÏÐRunLoopMode
µ±Óû§ÕýÔÚ»¬¶¯UIScrollViewʱ£¬RunLoop½«Çл»µ½UITrackingRunLoopMode½ÓÊÜ»¬¶¯ÊÖÊÆºÍ´¦Àí»¬¶¯Ê¼þ£¨°üÀ¨¼õËٺ͵¯»ÉЧ¹û£©£¬´Ëʱ£¬ÆäËûMode£¨³ýNSRunLoopCommonModesÕâ¸ö×éºÏMode£©ÏµÄʼþ½«È«²¿ÔÝÍ£Ö´ÐУ¬À´±£Ö¤»¬¶¯Ê¼þµÄÓÅÏÈ´¦Àí£¬ÕâÒ²ÊÇiOS»¬¶¯Ë³³©µÄÖØÒªÔÒò¡£
µ±UIûÔÚ»¬¶¯Ê±£¬Ä¬ÈϵÄModeÊÇNSDefaultRunLoopMode£¨Í¬CFÖеÄkCFRunLoopDefaultMode£©£¬Í¬Ê±Ò²ÊÇCFÖж¨ÒåµÄ¡°¿ÕÏÐ״̬Mode¡±¡£µ±Óû§É¶Ò²²»µã£¬´ËʱҲûÓÐÊ²Ã´ÍøÂç IOʱ£¬¾ÍÊÇÔÚÕâ¸öModeÏ¡£
ÓÃRunLoopObserverÕÒ׼ʱ»ú
×¢²áRunLoopObserver¿ÉÒԹ۲⵱ǰRunLoopµÄÔËÐÐ״̬£¬²¢ÔÚ״̬»úÇл»Ê±ÊÕµ½Í¨Öª£º
RunLoop¿ªÊ¼
RunLoop¼´½«´¦ÀíTimer
RunLoop¼´½«´¦ÀíSource
RunLoop¼´½«½øÈëÐÝÃß״̬
RunLoop¼´½«´ÓÐÝÃß״̬±»Ê¼þ»½ÐÑ
RunLoopÍ˳ö
ÒòΪ¡°Ô¤»º´æ¸ß¶È¡±µÄÈÎÎñÐèÒªÔÚ×îÎÞ¸ÐÖªµÄʱ¿Ì½øÐУ¬ËùÒÔÓ¦¸ÃͬʱÂú×㣺
RunLoop´¦ÓÚ¡°¿ÕÏС±×´Ì¬Mode£»
µ±ÕâÒ»´ÎRunLoopµü´ú´¦ÀíÍê³ÉÁËËùÓÐʼþ£¬ÂíÉÏÒªÐÝÃßʱ¡£
ʹÓÃCFµÄ´øblock°æ±¾µÄ×¢²áº¯Êý¿ÉÒÔÈôúÂë¸ü¼ò½à£º
CFRunLoopRef runLoop = CFRunLoopGetCurrent(); CFStringRef runLoopMode = kCFRunLoopDefaultMode; CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler (kCFAllocatorDefault, kCFRunLoopBeforeWaiting, true, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity _) { // TODO here }); CFRunLoopAddObserver(runLoop, observer, runLoopMode); |
·Ö½â³É¶à¸öRunLoop SourceÈÎÎñ
¼ÙÉèÁбíÓÐ20¸öcell£¬¼ÓÔØºóչʾÁËǰ5¸ö£¬ÄÇô¿ªÆô¹ÀËãºótable viewÖ»¼ÆËãÁËÕâ5¸öµÄ¸ß¶È£¬´ËʱʣÏÂ15¸ö¾ÍÊÇ¡°Ô¤»º´æ¡±µÄÈÎÎñ£¬¶øÎÒÃDz¢²»Ï£ÍûÕâ15¸ö¼ÆËãÈÎÎñÔÚͬһ¸öRunLoopµü´úÖÐͬ²½Ö´ÐУ¬ÕâÑù»á¿¨¶ÙUI£¬ËùÒÔÓ¦¸Ã°ÑËüÃÇ·Ö±ð·Ö½âµ½15¸öRunLoopµü´úÖÐÖ´ÐУ¬Õâʱ¾ÍÐèÒªÊÖ¶¯ÏòRunLoopÖÐÌí¼ÓSourceÈÎÎñ£¨ÓÉÓ¦Ó÷¢ÆðºÍ´¦ÀíµÄÊÇSource 0ÈÎÎñ£©
Foundation²ãû¶ÔRunLoopSourceÌṩֱ½Ó¹¹½¨µÄAPI£¬µ«ÊÇÌṩÁËÒ»¸ö¼ä½ÓµÄ¡¢¼ÈÊìϤÓÖİÉúµÄAPI£º
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(id)arg waitUntilDone:(BOOL)wait modes:(NSArray *)array; |
Õâ¸ö·½·¨½«´´½¨Ò»¸öSource 0ÈÎÎñ£¬·Ö·¢µ½Ö¸¶¨Ï̵߳ÄRunLoopÖУ¬ÔÚ¸ø¶¨µÄModeÏÂÖ´ÐУ¬ÈôÖ¸¶¨µÄRunLoop´¦ÓÚÐÝÃß״̬£¬Ôò»½ÐÑËü´¦Àíʼþ£¬¼òµ¥À´Ëµ¾ÍÊÇ¡°Ë¯Äãxx£¬ÆðÀ´àË£¡¡±
ÓÚÊÇ£¬ÎÒÃÇÓÃÒ»¸ö¿É±äÊý×é×°ÔØµ±Ç°ËùÓÐÐèÒª¡°Ô¤»º´æ¡±µÄindex path£¬Ã¿¸öRunLoopObserver»Øµ÷ʱ¶¼°ÑµÚÒ»¸öÈÎÎñÄóöÀ´·Ö·¢£º
NSMutableArray *mutableIndexPathsToBePrecached = self.fd_allIndexPathsToBePrecached.mutableCopy; CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler (kCFAllocatorDefault, kCFRunLoopBeforeWaiting, true, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity _) { if (mutableIndexPathsToBePrecached.count == 0) { CFRunLoopRemoveObserver(runLoop, observer, runLoopMode); return; } NSIndexPath *indexPath = mutableIndexPathsToBePrecached.firstObject; [mutableIndexPathsToBePrecached removeObject:indexPath]; [self performSelector:@selector(fd_precacheIndexPathIfNeeded:) onThread:[NSThread mainThread] withObject:indexPath waitUntilDone:NO modes:@[NSDefaultRunLoopMode]]; }); |
ÕâÑù£¬Ã¿¸öÈÎÎñ¶¼±»·ÖÅ䵽ϸö¡°¿ÕÏС±RunLoopµü´úÖÐÖ´ÐУ¬Æä¼äµ«·²Ó묶¯Ê¼þ¿ªÊ¼£¬ModeÇл»³ÉUITrackingRunLoopMode£¬ËùÓеġ°Ô¤»º´æ¡±ÈÎÎñµÄ·Ö·¢ºÍÖ´Ðж¼»á×Ô¶¯Ôݶ¨£¬×î´ó³Ì¶È±£Ö¤»¬¶¯Á÷³©¡£ |