從今天開始,在我的博客上開辟工作項目專欄,來總結記錄項目中的開發難點。第一篇記錄的是電子書模塊。
一級界面:1.側滑菜單、2.書籍列表、3.上拉加載
二級界面:1.頭部書籍信息、2.書籍簡介、3.評價列表、4.評價功能(彈出評價界面)5.底部下載/閱讀功能
下載管理界面:1.下載的書籍信息、2.可側滑刪除
閱讀界面:1.電子書自適應大小(pdf文件)、2.翻頁 、3.記錄頁
0.0
vcTRteOjurDRttTTprXE19PA4LC0y7PQ8rfFtb221NOmtcS4uMDgz8I8YnIgLz4NCiq94r72t723qKO6PC9wPg0KPHByZSBjbGFzcz0="brush:java;">
NSMutableArray *allArrM = [NSMutableArray array];
NSMutableArray *childArrM = [NSMutableArray array];
for (BookMenuEntity *menu in result) {
/**
* pid為1的是父類
*/
if ([menu.pid isEqual:@1]) {
[allArrM addObject:menu];
}
else
[childArrM addObject:menu];
}
/**
*所有父類+排序
*/
NSSortDescriptor *allSn = [[NSSortDescriptor alloc] initWithKey:@"sn" ascending:YES];
NSArray *newAllResult= [allArrM sortedArrayUsingDescriptors:@[allSn]];
/**
*所有子類+排序
*/
NSSortDescriptor *childSn = [[NSSortDescriptor alloc] initWithKey:@"sn" ascending:YES];
NSArray *childResult= [childArrM sortedArrayUsingDescriptors:@[childSn]];
/*
對應父類有幾個,這個可變數組救添加幾個數組
*/
NSMutableArray *newChildResult = [NSMutableArray array];
for (int i =0; i
1.1
1.1.1
因為要讓菜單欄彈出時書籍列表(UICollectionViewController)不可操作,所以加了背景遮罩。
backView = [[UIView alloc] initWithFrame:CGRectMake(0, HEADER, self.view.frame.size.width, self.view.frame.size.height)];
backView.backgroundColor = [UIColor colorWithRed:0 green:0 blue:0 alpha:0.3];
//加到標簽欄上
[self.tabBarController.view addSubview:backView];
//單擊手勢,讓菜單收起
tapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(tapGestureAction:)];
[tapGesture setNumberOfTapsRequired:1];
[backView addGestureRecognizer:tapGesture];
//為了讓菜單的透明度和背景區分,再加個小的背景
view = [[UIView alloc] initWithFrame:CGRectMake(0, HEADER, self.view.frame.size.width/2.5, backView.frame.size.height)];
view.backgroundColor = [UIColor blackColor];
view.alpha = 0.7;
[view addSubview:self.menuTableView];
[self.tabBarController.view addSubview:view];
//沒有點擊菜單按鈕,默認為隱藏
backView.hidden = YES;
view.hidden = YES;
1.1.2
*遇到難點:(1)剛開始時,菜單能正常加到tabBarController.view上,後來push到二級界面後,就不能加到tabBarController.view上(presentd的可以)。
*解決方法:
[self.tabBarController.view bringSubviewToFront:backView];
[self.tabBarController.view bringSubviewToFront:view];
1.1.3
菜單點擊需求。1??點到誰,誰就變紅(表示選中,父類也可以被選中並進行數據加載)2??選中以後,再點擊,不進行數據請求3??點擊一個父類,其它父類子菜單要全部收起
思路:用一個數組來記錄點擊選中狀態、以及展開閉合狀態
/**
* 1展開,0收起
*/
- (void)loadMenuData {
//用0代表收起,非0(不一定是1)代表展開,默認都是收起的
for (int i = 0; i < self.allMenuArrM.count; i++) {
[self.isExpland addObject:@0];
}
if (self.isExpland.count != 0) {
[self.menuTableView reloadData];
}
}
#pragma mark 加載菜單欄父類是否被選中的數據
/**
* 默認第一個父類被選中,1被選中,0沒有
*/
- (void)parentChooseAction{
for (int j=0; j
1.1.4
*遇到難點:(4)因為菜單涉及到很多數據,然後進行多次表格刷新。所以容易出現數組越界
*解決方法:數組為空的時候可能進行了reloadTableView,進行判空操作。盡量減掉重復的reloadTabelView(一開始有四處,後來減到兩處)
1.2
1.2.1
*遇到難點:(1)布局collectionViewCell
*解決方法:其它都好弄,但在解決每個cell的間距的時候一定要記住一個屬性:minimumInteritemSpacing,不設置它,cell的間距調不了。記得代理UICollectionViewDelegateFlowLayout。
UICollectionViewFlowLayout *flowLayout = [[UICollectionViewFlowLayout alloc] init];
[flowLayout setScrollDirection:UICollectionViewScrollDirectionVertical];
self.collectionView.collectionViewLayout = flowLayout;
flowLayout.minimumInteritemSpacing = 12.5;
[self.collectionView registerClass:[EBookCollectionViewCell class] forCellWithReuseIdentifier:reuseIdentifier];
/*
設置cell的大小
*/
- (CGSize)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout sizeForItemAtIndexPath:(NSIndexPath *)indexPath {
return CGSizeMake(90, 202);
}
/*
cell的布局上左下右的屏幕間距
*/
- (UIEdgeInsets)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout insetForSectionAtIndex:(NSInteger)section {
return UIEdgeInsetsMake(10, 12.5, 10,12.5);
}
1.2.2
*遇到難點:(2)書籍介紹需求默認可以顯示三行,但是字不夠的時候,如何讓字頂住左上角
*解決方法:
_introduceLabel.lineBreakMode = NSLineBreakByWordWrapping;//一定要設置這個屬性
cell.introduceLabel.text = [NSString stringWithFormat:@"%@\n\n",@"哈哈哈"];
1.2.3
*遇到難點:(3)字體天空藍
*解決方法:推薦一個好用的第三方顏色器(都調好了)http://download.csdn.net/detail/xj_love/9542251
_introduceLabel.textColor = [UIColor colorWithRed:0/255.0f green:178/255.0f blue:238/255.0f alpha:1.0];
2.二級界面
2.1
2.1.1
!
//注意書籍名標簽字的位置1.2.2的難點(2)一樣
2.1.2
!
公司用autoLayout進行布局。
*遇到難點:(1)評價內容Label高度自適應(2)cell高度自適應
*解決方法:1??獲取文字高度:
/*.h文件*/
@property (strong, nonatomic) IBOutlet NSLayoutConstraint *reviewLabelHeight;
/*.m文件*/
- (void)layoutSubviews{
CGSize size = [_review_content.text boundingRectWithSize:CGSizeMake(300, 1000) options: NSStringDrawingTruncatesLastVisibleLine"NSStringDrawingUsesLineFragmentOrigin attributes:@{NSFontAttributeName:[UIFont systemFontOfSize:13.0]} context:nil].size;
_reviewLabelHeight.constant = size.height;
}
2.2
2.2.1
同樣的,弄個背景View加到self.view上。添加單擊手勢。
2.2.2
*遇到難點:(1)在textView上加一個類似placheholder的提示語。(textfile的有這個屬性,textView沒有)
*解決方法:在textview上加一個Label,然後在textView的代理方法中 #pragma mark textView代理方法
- (void)textViewDidBeginEditing:(UITextView *)textView {
self.promptLabel.hidden = YES;
2.2.3
*遇到難點:(2)怎樣判斷textView沒有輸入內容已經輸入的為空格。
*解決方法:
/*
//進行一個過濾,找出空格
NSCharacterSet *set = [NSCharacterSet whitespaceAndNewlineCharacterSet];
NSString *trimedString = [self.textView.text stringByTrimmingCharactersInSet:set];
*/
if (self.textView.text.length !=0&&trimedString.length !=0) {
}
3.下載管理界面
3.1
3.1.1
*遇到難點:書名高度自適應,cell高度自適應
*解決方法:參考2.1.2
3.1.2
實現側滑刪除:
/**
* 1.開啟允許編輯
* 2.提交編輯
* 3.把英文轉換成中文
*/
- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{
return YES;
}
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath{
if (editingStyle == UITableViewCellEditingStyleDelete) {
DownBookInfoEntity *listModel = self.downloadArrM[indexPath.row];
[DAO_DownBook deleteBookInfoWithBookID:(NSString *)listModel.ID];
NSString *bookUrl = [NSString stringWithFormat:@"%@%@",Host1,listModel.file];
NSString *path = [MANAGER_FILE.CSDownloadPath stringByAppendingPathComponent:[NSString stringWithFormat:@"file/%@", [bookUrl lastPathComponent]]];
/*從數據庫刪除*/
[MANAGER_FILE deleteFolderPath:path];
[self.downloadrrM removeObjectAtIndex:indexPath.row];
//數組是[indexPath]的數組
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
}
}
- (NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
return @"刪除";
}
4.電子書閱讀
用我的方法,就不用管電子書的寬高,它會自適應。
其實電視書是把一個UIScrollView加到控制器上,然後把pdfView加到UIScrollView上。
/*獲取pdf文件*/
pdf = CGPDFDocumentCreateWithURL((CFURLRef)url);
/*獲取文件總頁數*/
pageCount = (int)CGPDFDocumentGetNumberOfPages(pdf);
-(void)drawInContext:(CGContextRef)context atPageNo:(int)page_no{
CGContextSetRGBFillColor(context, 1.0, 1.0, 1.0, 1.0);
CGContextFillRect(context,self.bounds);
CGContextTranslateCTM(context, 0.0, self.bounds.size.height);
CGContextScaleCTM(context, 1.0, -1.0);
if (self.pageNO == 0) {
self.pageNO = 1;
}
CGPDFPageRef page = CGPDFDocumentGetPage(self.pdfDocument, self.pageNO);
CGContextSaveGState(context);
CGAffineTransform pdfTransform = CGPDFPageGetDrawingTransform(page, kCGPDFCropBox, self.bounds, 0, true);
CGContextConcatCTM(context, pdfTransform);
CGContextDrawPDFPage(context, page);
CGContextRestoreGState(context);
}
四.其它總結
1.文件下載
ASIHttpRequest很好用的網絡請求第三方。可以get,post請求,支持斷點下載。
/**
* 下載文件
* @param urlStr 文件路徑
* @param block 回調
*/
- (void)downloadFile:(NSString *)urlStr withType:(int)type finishCallbackBlock:(void (^)(BOOL result))block {
-
ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:urlStr]];
NSString *filename = [urlStr lastPathComponent];
//下載後存儲文件名
NSString *savePath = [MANAGER_FILE.CSDownloadPath stringByAppendingPathComponent:[NSString stringWithFormat:@"file/%@", filename]];
NSString *tempPath = [MANAGER_FILE.CSDownloadPath stringByAppendingPathComponent:[NSString stringWithFormat:@"temp/%@", filename]];
[request setDownloadDestinationPath:savePath];
[request setTemporaryFileDownloadPath:tempPath];
[request setShouldContinueWhenAppEntersBackground:YES];
[request setDownloadProgressDelegate:self];
[MANAGER_SHOW showProgressWithInfo:@"下載中..."];
[request setCompletionBlock:^{
[MANAGER_SHOW setProgress:1.0];
if ([MANAGER_FILE fileExists:savePath]) {
block(YES);
}else {
block(NO);
}
}];
[request setFailedBlock:^{
[MANAGER_SHOW setProgress:1.0];
block(NO);
}];
[request startAsynchronous];
}
2.get請求
/*
typedef void (^GetBackBlock)(id obj);
typedef void (^GetFailBlock)(NSError *error);
*/
- (void)doGetJson:(NSString *)urlstr withCompletionBlock:(GetBackBlock)completionBlock withFailBlock:(GetFailBlock)failBlock {
ASIHTTPRequest *request = [[ASIHTTPRequest alloc] initWithURL:[NSURL URLWithString:urlstr]];
[request startAsynchronous];
__block ASIHTTPRequest *_request = request;
[request setCompletionBlock:^{
switch ([_request responseStatusCode]) {//HTTP狀態碼
case 404://Not Found 無法找到指定位置的資源
case 500://Internal Server Error 服務器遇到了意料不到的情況
failBlock([_request error]);
break;
case 200://OK 一切正常
completionBlock([_request responseData]);
[MANAGER_SHOW dismiss];
break;
default:
failBlock([_request error]);
break;
}
}];
[request setFailedBlock:^{
failBlock([_request error]);
[MANAGER_SHOW dismiss];
}]
}
3.post傳輸
- (void)doPostJson:(PostModel *)model withSuccessBlock:(GetBackBlock)successBlock withFailBlock:(GetFailBlock)failBlock {
ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:[NSURL URLWithString:[model.urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];
[request setRequestMethod:@"POST"];
for (NSString *key in [model.params allKeys]) {
[request setPostValue:[model.params objectForKey:key] forKey:key];
}
[request buildPostBody];
[request startAsynchronous];
__block ASIFormDataRequest *_request = request;
[request setCompletionBlock:^{
[MANAGER_SHOW dismiss];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
BLOCK_SUCCESS([_request responseData]);
});
}];
[request setFailedBlock:^{
[MANAGER_SHOW dismiss];
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.2f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
BLOCK_FAILURE([_request error]);
});
}];
}