iOS開發-博客導出工具開發教程(附帶源碼) – iPhone手機開發技術文章 iPhone軟體開發教學課程

前言:

作為一名學生, 作為一名iOS開發學習者, 我個人瀏覽信息包括博客, 更多的選擇移動終端。然而, csdn並沒有現成的客戶端(不過有個web版的)。

之前曾經看到一款開源的導出工具, 但是它是基於Windows平臺的。導出的也僅僅是PDF格式。而且, 對於文章的導出, 需要精確URL。無法做到邊瀏覽別導出。

另外, 我想實現的是, 可以在沒有網絡的情況下, 瀏覽自己收藏的文章。並且, 對於自己收藏的文章, 可以分類管理。

最關鍵的是, 對於自己的文章, 可以做一個備份。我曾經遇到過這樣一件事, csdn賬號密碼泄漏, 使得他人登錄我賬號發表垃圾博文, 導致我的博客被封一天。那時候, 我的博客記錄瞭170篇自己的學習點滴, 沒有備份, 可以想像那時候我有多慌。可見, 備份自己文章的重要性。

基於以上種種原因, 這款基於iOS平臺的博客導出工具應運而生。

註:

本文章正在參與2014年csdn博客大賽。如果您覺得, 對您有所幫助, 希望能投上寶貴的一票。

投票鏈接:https://vote.blog.csdn.net/Article/Details?articleid=31768677

具體功能:

支持在線瀏覽csdn博客可導類型包括: 單篇文章, 專欄, 指定作者全部文章導出方式包括: (1)導出單前瀏覽博文/專傢/專欄 (2)導出指定URL博文/專傢/專欄 導出文章分類管理導出文章查詢功能導出文章自動排版, 圖片自適應, 可放縮

運行效果:

vcD48cD48c3Ryb25nPr+0tb3V4sDvLCDI57n7xOPWu8rHz+vM5dHp0rvPwtXiuPbTptPDLCDP67+0v7TUtMLrLCDEx7/J0tS0087StcRHaXRodWLW0M/C1Niho8HtzeIsILXa0ruw5tLRvq3Jz7Srtb1BcHAgU3RvcmXJz8ilwcuhoyDV/dTatci0/cnzusuhozwvc3Ryb25nPjwvcD48cD48c3Ryb25nPmh0dHBzOi8vZ2l0aHViLmNvbS9jb2xpbjE5OTQvY3NkbkJsb2cuZ2l0PGJyIC8+PC9zdHJvbmc+PC9wPjxwPjxiciAvPjwvcD48cD7I57n7xOPP68HLveLPwtX7zOW/qreiuf2zzCwgu7bTrbzM0PjN+c/Cv7ShozxzdHJvbmc+zca89s/C1NjBy9S0wussILbU1dXXxb+0PC9zdHJvbmc+oaM8L3A+PGgxPsTjvavRp7W9OjwvaDE+PHA+PC9wPjxzdHJvbmc+19S2qNLlxvS2r7avu608L3N0cm9uZz48c3Ryb25nPs34wue7t76zxdC2zyjKx7fxysdXaS1Gade0zKwpPC9zdHJvbmc+PHN0cm9uZz5JT1PT60phdmFTY3JpcHS1xL27u6U8L3N0cm9uZz48c3Ryb25nPtfUtqjS5UhVRLzT1NjQp7n7KLfHtKvNs77Vu6gpPC9zdHJvbmc+PHN0cm9uZz5VSVRhYmxlVmlld8HQse27+bG+stnX9zwvc3Ryb25nPjxzdHJvbmc+wdCx7bnYvPzX1sSjuv2y6dGvPC9zdHJvbmc+PHN0cm9uZz7NvMasu/mxvrLZ1/c8L3N0cm9uZz7PwsPm1vDSu7340NC31s72oaM8YnIgLz48aDI+KNK7KSDX1Lao0uXG9Lavtq+7rTwvaDI+srvNrNPrtKvNs7XE0N64xExhdW5jaEltYWdlwLS809TY0ru49r6yzKy1xM28xqzX986qztLDx7XEu7bTrb3nw+YsIDxzdHJvbmc+ztLV4sDvvPK1pbXEyrXP1sHLzbzGrMv1t8UsIM7E19a9pb2lz9TKvrXE0Ke5+6GjPC9zdHJvbmc+z+C21MC0y7UsILj8vNPDwLnbLCDO0sPHxNzX9rXEstnX99KyuPy807bgoaM8YnIgLz608r+qQXBwRGVsZWdhdGUuaM7EvP4sIMn5w/fSu7j2seTBvywg08PT2s/Uyr7O0sPHtcTK0828oaM8cHJlIGNsYXNzPQ==”brush:java;”>@property (strong, nonatomic) UIImageView *splashView;

打開AppDelegate.m文件, 加入具體實現過程。

1.添加啟動動畫

    //添加啟動動畫
    [self.window makeKeyAndVisible];

    splashView = [[UIImageView alloc]initWithFrame:CGRectMake(0, 0, 320, Screen_height)];
    
    if ([[UIScreen mainScreen] bounds].size.height == 568)
    {
        [splashView setImage:[UIImage imageNamed:@"bgBlog-568"]];
    }
    else
    {
        [splashView setImage:[UIImage imageNamed:@"bgBlog"]];

    }
    
    [self.window addSubview:splashView];
    [self.window bringSubviewToFront:splashView];
    
    [self performSelector:@selector(scale) withObject:nil afterDelay:0.0f];
    [self performSelector:@selector(showWord) withObject:nil afterDelay:2.5f];

2.動畫具體實現

-(void)scale
{
    UIImageView *logo_ = [[UIImageView alloc]initWithFrame:CGRectMake(119, 88, 82, 82)];
    logo_.image = [UIImage imageNamed:@"csdnLogo"];
    [splashView addSubview:logo_];
    [self setAnimation:logo_];
}

-(void)setAnimation:(UIImageView *)nowView
{
    
    [UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionCurveLinear
                     animations:^
     {
         // 執行的動畫code
         [nowView setFrame:CGRectMake(nowView.frame.origin.x- nowView.frame.size.width*0.1, nowView.frame.origin.y-nowView.frame.size.height*0.1, nowView.frame.size.width*1.2, nowView.frame.size.height*1.2)];
     }
                     completion:^(BOOL finished)
     {
         // 完成後執行code
         [nowView removeFromSuperview];
     }
     ];
    
}

-(void)showWord
{
    
    UIImageView *word_ = [[UIImageView alloc]initWithFrame:CGRectMake(75, Screen_height-100, 170, 29)];
    word_.image = [UIImage imageNamed:@"word_"];
    [splashView addSubview:word_];
    
    word_.alpha = 0.0;
    [UIView animateWithDuration:1.0f delay:0.0f options:UIViewAnimationOptionCurveLinear
                     animations:^
     {
         word_.alpha = 1.0;
     }
                     completion:^(BOOL finished)
     {
         // 完成後執行code
         [NSThread sleepForTimeInterval:1.0f];
         [splashView removeFromSuperview];
     }
     ];
}

(二)網絡環境判斷(是否是Wi-Fi狀態)

這個需要導入Wi-Fi文件夾下的Reachability.h / .m文件。 這是從蘋果官方下載的。一個用來判斷網絡環境的文件。我們之所以要判斷是否在Wi-Fi環境下, 是因為導出文章可能使用的流量較大, 我們需要提示用戶開啟Wi-Fi來下載。

1.導入Reachability.h / .m文件

2.添加頭文件

#import "Reachability.h"            //Wi-Fi

3.判斷網絡環境

    if ([Reachability reachabilityForInternetConnection].currentReachabilityStatus == ReachableViaWiFi)
    {
        //添加你想做的事情
    }

(三)IOS與JavaScript的交互

UIWebView是iOS最常用的SDK之一,它有一個stringByEvaluatingJavaScriptFromString方法可以將javascript嵌入頁面中,通過這個方法我們可以在iOS中與UIWebView中的網頁元素交互。
常見的幾種使用途徑:1、獲取當前頁面的url。

- (void)webViewDidFinishLoad:(UIWebView *)webView {  
  NSString *currentURL = [webView stringByEvaluatingJavaScriptFromString:@"document.location.href"];
}

2、獲取頁面title。

- (void)webViewDidFinishLoad:(UIWebView *)webView {  
   NSString *currentURL = [webView stringByEvaluatingJavaScriptFromString:@"document.location.href"];

   NSString *title = [webview stringByEvaluatingJavaScriptFromString:@"document.title"]; 
}

3、修改界面元素的值。

NSString *js_result = [webView stringByEvaluatingJavaScriptFromString:@"document.getElementsByName('q')[0].value='Colin';"];

4、表單提交:

 NSString *js_result2 = [webView stringByEvaluatingJavaScriptFromString:@"document.forms[0].submit(); "];

當然, 還有更多的功能, 需要你自己去學習。
我們這個工具所要做的是, 獲取到博文的主要內容及其標題。以導出單篇為例。我們打開一個博文, 顯示頁面源代碼, 可以看到下面這樣的內容。

其中的”article_content” 就對應著csdn博文的正文內容. 這是我們導出過程中需要的。(你肯定也不希望導出的文章裡面嵌套著廣告吧…)所以, 我們可以通過簡單的兩行代碼獲取我們需要的內容:

//獲取詳細內容
NSString *lJs = @"document.getElementById(\"article_content\").innerHTML";
NSString *lHtml1 = [webView stringByEvaluatingJavaScriptFromString:lJs];

同理, 文章標題可以這樣獲得:

//獲取標題
NSString *lJs2 = @"document.getElementById(\"article_details\").getElementsByClassName(\"article_title\")[0].getElementsByTagName(\"a\")[0].innerText";
NSString *lHtml2 = [webView stringByEvaluatingJavaScriptFromString:lJs2];

再深入一點, 我們甚至可以修改顯示網頁的圖片大小

//修改圖片大小
if ([lHtml1 rangeOfString:@"<img"].location != NSNotFound)
{
        NSScanner *myScanner = [NSScanner scannerWithString:lHtml1];
        NSString *myText = nil;
        while ([myScanner isAtEnd] == NO)
        {
             [myScanner scanUpToString:@"<img" intoString:nil];
             [myScanner scanUpToString:@"s" intoString:&myText];
                    
             lHtml1 = [lHtml1 stringByReplacingOccurrencesOfString:[NSString stringWithFormat:@"%@s",myText] withString:@"<img style=\"width:300px;height:this.offsetHeight;\" s"];
         }
}

(四)自定義HUD加載效果(非傳統菊花)

iOS自帶的加載效果是個轉圈的菊花…想必大傢都清楚瞭。不過說實話, 那玩意確實夠難看的。選擇我們要做的是, 顯示一個不封閉的圈, 並且背景視圖暗一點, 突出加載過程。效果如下:

1.導入文件夾SVProgressHUD

2.添加頭文件

#import "SVProgressHUD.h"           //HUD 加載顯示

3.顯示HUD

//顯示HUD
[SVProgressHUD showWithMaskType:SVProgressHUDMaskTypeGradient];

4.移除HUD

//移除HUD
[SVProgressHUD dismiss];

(五)UITableView列表基本操作

這個是基礎內容瞭, 具體可以看blogExportedList.m這裡. 有詳細講解。這裡著重介紹下左滑刪除操作。1.開啟運行刪除模式2.響應刪除的時候, 需要做到 (1) 從列表中移除 (2)從數據中移除 (3)刷新列表

//刪除
-(UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return UITableViewCellEditingStyleDelete;
}

/*改變刪除按鈕的title*/
-(NSString *)tableView:(UITableView *)tableView titleForDeleteConfirmationButtonForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return @"刪除";
}

/*刪除用到的函數*/
-(void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (editingStyle == UITableViewCellEditingStyleDelete)
    {
        //獲取完整路徑 以及字典和數組的初始化
        NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
        NSString *documentsDirectory = [paths objectAtIndex:0];
        NSString * namePath = [documentsDirectory stringByAppendingPathComponent:@"csdnInfo.plist"];
        
        [blogArr removeObjectAtIndex:indexPath.row];
        
        [blogArr writeToFile:namePath atomically:YES];
        
        [nameList removeObjectAtIndex:indexPath.row];
        
        [myTableView deleteRowsAtIndexPaths:[NSMutableArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationAutomatic];  //刪除對應數據的cell
    }
}

(六)列表關鍵字模糊查詢

搜索的話, 是個很常用的功能。如果簡單的關鍵字搜索, 想必大傢都會. 但是我們需要的是模糊查詢。 比如要查詢 “iOS開發” 當你輸入i, o開, 等等, 都能找到對應的數據。

1.導入查詢字列表文件夾

2.添加頭文件

//查詢子列表
#import "DDList.h"
#import "PassValueDelegate.h"

3.初始化查詢列表

//查詢列表初始化
    nameList = [[NSMutableArray alloc]init];
    for (int i =0; i<[blogArr count]; i++)
    {
        [nameList addObject:[[blogArr objectAtIndex:i]objectForKey:@"name"]];
    }
    
    //初始化查詢的字符串
	_searchStr = @"";
	
    //初始化提醒視圖
	_ddList = [[DDList alloc] initWithStyle:UITableViewStylePlain];
	_ddList._delegate = self;
	[self.view addSubview:_ddList.view];
	[_ddList.view setFrame:CGRectMake(30, 108, 200, 0)];
    _ddList._totalList = nameList;

4.響應查詢

具體可以看代碼, 這裡強調一個。 當查到數據點擊的時候, 我們需要自動跳轉到指定的位置。 不然查詢也沒用瞭..

//隱藏提醒視圖
- (void)setDDListHidden:(BOOL)hidden
{
	NSInteger height = hidden ? 0 : 180;
	[UIView beginAnimations:nil context:nil];
	[UIView setAnimationDuration:.2];
	[_ddList.view setFrame:CGRectMake(30, 108, 200, height)];
	[UIView commitAnimations];
}

//單例,傳回選中提醒框中的結果
#pragma mark -
#pragma mark 傳回數據
- (void)passValue:(NSString *)value
{
    //如果有選中,則修改當前搜索內容為返回結果,調用結束函數searchBarSearchButtonClicked
	if (value)
    {
		_searchBar.text = value;
		[self searchBarSearchButtonClicked:_searchBar];
	}
	else {
		
	}
}

//搜索框中的字符改變時候調用
#pragma mark -
#pragma mark SearchBar Delegate Methods
- (void)searchBar:(UISearchBar *)searchBar textDidChange:(NSString *)searchText
{
    //如果搜索框有內容,更新提示列表
	if ([searchText length] != 0) {
		_ddList._searchText = searchText;
		[_ddList updateData];
		[self setDDListHidden:NO];
	}
	else
    {
		[self setDDListHidden:YES];  //否則隱藏
	}
    
}

//文本框彈出,開始搜索
- (BOOL)searchBarShouldBeginEditing:(UISearchBar *)searchBar
{
	searchBar.showsCancelButton = YES;
	for(id cc in [searchBar subviews])
    {
        if([cc isKindOfClass:[UIButton class]])
        {
            UIButton *btn = (UIButton *)cc;
            [btn setTitle:@"取消"  forState:UIControlStateNormal];
        }
    }
	return YES;
}

//開始搜索響應。
- (void)searchBarTextDidBeginEditing:(UISearchBar *)searchBar
{
	searchBar.text = @"";
}

//結束文本框輸入
- (void)searchBarTextDidEndEditing:(UISearchBar *)searchBar
{
	searchBar.showsCancelButton = NO;
	searchBar.text = @"";
}

//當選中瞭提示列表中的某個,搜索結束,選中結果,並且高亮
- (void)searchBarSearchButtonClicked:(UISearchBar *)searchBar
{
	[self setDDListHidden:YES];  //隱藏提示視圖
	_searchStr = [searchBar text]; //獲得查詢結果
	[searchBar resignFirstResponder];  //收回鍵盤
    
    for (int i = 0; i<[blogArr count]; i++)  //從列表中查找結果,選中
    {
        if ([[[blogArr objectAtIndex:i]objectForKey:@"name"] isEqualToString:_searchStr])
        {
            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
            [myTableView reloadData];
            [myTableView scrollToRowAtIndexPath:indexPath     //滾動視圖
                              atScrollPosition:UITableViewScrollPositionMiddle
                                      animated:YES];
            [myTableView selectRowAtIndexPath:indexPath       //選中高亮
                                    animated:YES
                              scrollPosition:UITableViewScrollPositionMiddle];
        }
    }
    
    
}

//取消搜索響應
- (void)searchBarCancelButtonClicked:(UISearchBar *)searchBar
{
	[self setDDListHidden:YES];
	[searchBar resignFirstResponder];
}

(七)圖片基本操作

這裡我們需要做的是, 點擊一個圖片, 跳轉到另外一個視圖, 這裡視圖允許對圖片進行常規編輯。包括圖片的縮放…具體可以看MRZoomScrollView.h / .m這兩個文件。下面解釋下實現方法。

1.添加手勢。

    // Add gesture,double tap zoom imageView.
    UITapGestureRecognizer *doubleTapGesture = [[UITapGestureRecognizer alloc] initWithTarget:self
                                                                                action:@selector(handleDoubleTap:)];
    [doubleTapGesture setNumberOfTapsRequired:2];
    [imageView addGestureRecognizer:doubleTapGesture];

我們的放縮都是通過手勢識別來實現的。 比如, 你雙指拖拉, 就是放縮。 雙指點擊是自動放縮, 單指點擊是退出圖片瀏覽。

2.響應手勢操作

#pragma mark - Zoom methods

- (void)handleDoubleTap:(UIGestureRecognizer *)gesture
{
    float newScale = self.zoomScale * 1.5;
    CGRect zoomRect = [self zoomRectForScale:newScale withCenter:[gesture locationInView:gesture.view]];
    [self zoomToRect:zoomRect animated:YES];
}

- (CGRect)zoomRectForScale:(float)scale withCenter:(CGPoint)center
{
    CGRect zoomRect;
    zoomRect.size.height = self.frame.size.height / scale;
    zoomRect.size.width  = self.frame.size.width  / scale;
    zoomRect.origin.x = center.x - (zoomRect.size.width  / 2.0);
    zoomRect.origin.y = center.y - (zoomRect.size.height / 2.0);
    return zoomRect;
}


至此, 這篇簡單的教程就結束瞭。希望, 能給您帶來一點收獲。
ps:

本文章正在參與2014年csdn博客大賽。如果您覺得, 對您有所幫助, 希望能投上寶貴的一票。

投票鏈接:https://vote.blog.csdn.net/Article/Details?articleid=31768677

學習的路上, 與君共勉。

You May Also Like