Preface
We usually useUITableView
It is used a lot, so I pay attention to the optimization of the list. Many times, we set upUIImageView
, the ratio is fixed to the width and height, and then passscaleAspectFill
andclipsToBounds
Keeping the picture undeformed is very efficient in this way. After all, we have fixed the width and height of the picture.
What if the product requires the pictures to be displayed in real proportions? If the server returns width and height, it will be easy. If not, how should we do it?
Let's explore together below.
Picture adaptive proportions
Generally, we useUITableViewAutomaticDimension
To achieve it.
We have done this directlysd_setImageWithURL
To add images, the same is true now. We also use this to obtain the width and height of the image.
- (void)sd_setImageWithURL:(nullable NSURL *)url placeholderImage:(nullable UIImage *)placeholder completed:(nullable SDExternalCompletionBlock)completedBlock
Once completed, we can get itUIImage
, so as to know the picturesize
. Then we can get the height of the image in proportion and then change the height of the image by updating the constraints.
The general approach is as follows:
[_imageView sd_setImageWithURL:[NSURL URLWithString:] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL _Nullable imageURL) { if (image) { // Get the image width and height CGSize imageSize = ; CGFloat maxWidth = kSCREEN_WIDTH - 32; // Get the current height in proportion CGFloat height = * maxWidth / ; [ mas_updateConstraints:^(MASConstraintMaker *make) { .mas_equalTo(height); }]; } }];
Then when we ran the code, we found that the height of the picture did not show the height we wanted, and it can be said that we did not even have the height.
It is obvious that the height of the picture is not effective. Think about it, we call the picture asynchronously, and then wait for the asynchronous result to come back and call it.mas_updateConstraints
, no proxy triggersheightForRowAtIndexPath
, how could the height be updated?
Since that's the case, let's reload the list.
[cell setHeightBlock:^(CGFloat imageHeight){ [tableView beginUpdates]; [tableView reloadRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationNone]; [tableView endUpdates]; }];
We've updatedmas_updateConstraints
After that, directly refresh the list to solve the problem.
At this time, we re-run it, and the effect is OK, but when we roll back and forth, we find that it is a bit stuck. Obviously, we have to refresh every time we scrollcell
。
If we have a cache, we know the height of the picture. Then do we not need it?reloadRowsAtIndexPaths
。
So I optimized again
// Is there a cacheBOOL hasCache = [[SDImageCache sharedImageCache] diskImageDataExistsWithKey:]; [_ImageView sd_setImageWithURL:[NSURL URLWithString:] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { if (image) { CGSize imageSize = ; CGFloat maxWidth = kSCREEN_WIDTH - 32; CGFloat height = * maxWidth / ; [ mas_updateConstraints:^(MASConstraintMaker *make) { .mas_equalTo(height); }]; // If there is a cache, don't reloadRowsAtIndexPaths if (!hasCache && ) { (height); } } }];
If we find that there are cached images, we will not refresh the list.sd_setImageWithURL
At this time, the picture is also read from the cache, and it is not loaded asynchronously, so there is no need to refresh the current one again.cell
Now.
XHWebImageAutoSize
Some people say that writing like this seems to be quite troublesome. Whether there is a good way to write it is indeed some.
That's the third-party libraryXHWebImageAutoSize, its writing method is actually usedSDWebImage
to perform optimization operations.
[_imageView sd_setImageWithURL:[NSURL URLWithString:] completed:^(UIImage * _Nullable image, NSError * _Nullable error, SDImageCacheType cacheType, NSURL * _Nullable imageURL) { if (image) { /** Cache image size */ [XHWebImageAutoSize storeImageSize:image forURL:imageURL completed:^(BOOL result) { /** reload  */ if(result && ) { (0) } ]; } }];
After cache the image, you will also refresh the cell.
[cell setHeightBlock:^(CGFloat imageHeight) { [tableView xh_reloadDataForURL:[NSURL URLWithString:]]; }];
Then reload the height.
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { ImageModel *model = _dataArray[]; return [XHWebImageAutoSize imageHeightForURL:[NSURL URLWithString:] layoutWidth:[UIScreen mainScreen].-32 estimateHeight:200] + 50; }
Added later50
is other heights, for examplecell
There is still insidetitle
, that is, the picture + other heights.
This also enables the image adaptive height.
Load only the content of the current screen
There are too many pictures lists, and they are always smooth and smooth. The picture loading speed cannot keep up with the hand speed. It feels a bit stuck. We can only load the content of the current screen. When sliding, we do not load. After the list stops, we load the content of the current screen again.
We're modeling nowmodel
Inside, add oneisLoad
Parameters, iftrue
, we only load.
Add a current screen load firstcell
method.
-(void)loadCurrentCells{ NSArray * array = [ indexPathsForVisibleRows]; for (NSIndexPath *indexPath in array) { JJTableViewCell * cell = (JJTableViewCell *)[ cellForRowAtIndexPath:indexPath]; ImageModel *model = _dataArray[]; //Set to load = YES; //Configure cell [cell configCellWithImageModel:model]; } }
cell
Insidemodel
ofisLoad
Make a judgment.
- (void)configCellWithImageModel:(ImageModel *)model { if () { [_imageView sd_setImageWithURL:[NSURL URLWithString:]]; }else { _imageView.image = [UIImage imageNamed:@"default_images_icon"]; } }
If it does not load for the time being, we can set the occupied image first.
In this way, we just need to set the content of the current page to load when the monitor stops sliding.
- (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { if (!decelerate) { [self loadCurrentCells]; } } - (void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView { [self loadCurrentCells]; }
Of course we startedreloaData
When allisload
All forfalse
, so we need to load the current onecell
content.
[ reloadData]; [self loadCurrentCells];
In this way, we can not load the picture asynchronously until we keep sliding, and then load the picture on the current screen when the slide stops.
Of course, in addition to this writing method, we can also useRunLoop
To achieve it.
Preload
The so-called preloading means sliding all the time. When we turn the page, we load the data in advance, making the user feel that there is always data. It didn't appearPull-up load more
This situation.
The overall idea is: when the sliding distance accounts for the total sliding distance%90
(Not fixed), preloading is triggered.
I won't write it here, just get the links to the boss:iOS Development TableView Network Request/Display Preload
The above is the detailed explanation of the detailed explanation of the UITableViewCell image loading optimization for ios development. For more information about ios UITableViewCell image loading, please follow my other related articles!