我今天主要說的電子書閱讀器源碼如下:https://github.com/GGGHub/Reader。首先要感謝原作者的分享,有一個完整的,能運行的電子書閱讀器demo。讓我們爲作者的這種開源精神點贊
雖然這個電子書閱讀器demo是衆多開源中相對比較完善的一個,但是也已經有兩年沒有更新了。也存在了一些問題急需要解決。我把存在的問題梳理如下:
沒有重用機制,內存開銷大,滑動起來反應特別慢
某些情況下存在閃退,崩潰現象
每次打開電子書都需要解壓,解壓時間比較長
當然了還有一些細節的小問題,我這裏就不再一一的列舉了。
沒有重用機制,內存開銷大,滑動起來反應特別慢
沒有重用機制,對於一個電子書閱讀器來說應該是最大的一個軟肋,因爲用戶看小說的時候事件比較長,在這段連續的時間內,用戶已經連續翻頁,劃過了很多頁面,如果沒有重用機制的話,就會造成內存爆增,app出現卡頓現象,如果滑動比較快的話,內存不夠,app就會被殺死造成閃退。
解決思路:我這邊從時間成本上考慮,直接使用UIcollectionView來進行復用。
同時每一個頁面就是一個單獨的cell。關鍵代碼如下:
#pragma mark - - - - UIScrollViewDelegate - - - -
-(void)scrollViewDidEndDecelerating:(UIScrollView *)scrollView{
NSInteger index = scrollView.contentOffset.x/ scrollView.bounds.size.width;
if (index == self.cellCount-1 || index == 0) {
[self scrollToOriginCell];
}
}
#pragma mark - - - - UICollectionViewDataSource - - - -
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath*)indexPath {
JKPageCollectionCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:[JKPageCollectionCell CellIndentifier] forIndexPath:indexPath];
[self refreshTheReadModelWithIndex:indexPath.item];
NSInteger count = indexPath.item - self.middleIndex;
if (count >= [self eyeProductCellCount]) {
self.eyeProductView.backgroundColor = [LSYReadConfig shareInstance].theme;
self.eyeProductView.hidden = NO;
}
self.lastPageIndex = indexPath.item;
[cell updateViewWithModel:self.model];
return cell;
}
我這邊cellCount設置的比較大是1000.方便用戶體驗,用戶滑動到500頁的時候,會給用戶彈出一個護眼提醒。同時將cell滾動到最初的頁面,給用戶一個可以無限滑動的假象。哈哈
但是在實際的操作中卻發現,左右滑動切換的時候出現了頁面數據刷新的不準確的情況。經過排查發現iOS 10 以後,collectionView優化造成的,我這邊處理代碼如下:
if (@available(iOS 10.0,*)) {
self.collectionView.prefetchingEnabled = NO;
}
某些情況下存在閃退,崩潰現象
存在閃退,崩潰現象,剛開始優化之前還是比較頻繁的,統計下來主要體現在兩個方面,第一就是沒有重用機制,內存緊張造成的app閃退。第二就是frameRef對象無法歸檔造成的,繪製是,內容確實造成的crash。第一種情況通過重用已經能夠得到解決,第二種情況我這邊主要是在對epub格式的文件處理時,考慮到framRef的對象無法歸檔,我這邊重新進行了一次的解壓,獲取相關的chapters信息,具體代碼如下:
+(id)getLocalModelWithURL:(NSURL *)url
{
NSString *key = [url.path lastPathComponent];
NSData *data = [[NSUserDefaults standardUserDefaults] objectForKey:key];
if (!data) {
if ([[key pathExtension] isEqualToString:@"txt"]) {
LSYReadModel *model = [[LSYReadModel alloc] initWithContent:[LSYReadUtilites encodeWithURL:url]];
model.resource = url;
[LSYReadModel updateLocalModel:model url:url];
return model;
}
else if ([[key pathExtension] isEqualToString:@"epub"]){
LSYReadModel *model = [[LSYReadModel alloc] initWithePub:url.path];
model.resource = url;
[LSYReadModel updateLocalModel:model url:url];
return model;
}
else{
@throw [NSException exceptionWithName:@"FileException" reason:@"文件格式錯誤" userInfo:nil];
}
}
NSKeyedUnarchiver *unarchive = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
//主線程操作
LSYReadModel *model = [unarchive decodeObjectForKey:key];
if ([[key pathExtension] isEqualToString:@"epub"]){
model.chapters = [LSYReadUtilites ePubFileHandle:url.path];//重新從path下解析獲取epubchapter的內容。
}
model.record.chapterModel = model.chapters.firstObject;
return model;
}
每次打開電子書都需要解壓,解壓時間比較長
針對這一種情況,我個人覺得, 完全沒有必要每次都解壓,只需一次解壓,然後保存解壓後的文件,然後每次從指定的文件夾打開就OK了,但是有由於存在電子書名字相同的情況,可能會出現bug,針對這一種情況。我這邊的解決方案是在電子書下載到app內的時候,自動的在電子書名字後面通過特殊分隔符號,添加一個時間戳,來進行標記,這樣可以很好的解決電子書重名的問題。
當然了,上面的解決方案只是自己在開發過程中,自己的個人觀點,可能不是特別的完美,歡迎大家的批評指正。如果大家對電子書開發感興趣的話,可以用QQ掃描下方的二維碼
更多優質文章,可以微信掃碼關注: