您可以捐助,支持我们的公益事业。

1元 10元 50元





认证码:  验证码,看不清楚?请点击刷新验证码 必填



  求知 文章 文库 Lib 视频 iPerson 课程 认证 咨询 工具 讲座 Modeler   Code  
会员   
 
   
 
 
     
   
 订阅
  捐助
iOS开发-博客导出工具开发教程
 
作者 Colin-的博客,火龙果软件    发布于 2014-09-19
   次浏览      
 

前言:

作为一名学生, 作为一名iOS开发学习者, 我个人浏览信息包括博客, 更多的选择移动终端。然而, csdn并没有现成的客户端(不过有个web版的)。

之前曾经看到一款开源的导出工具, 但是它是基于Windows平台的。导出的也仅仅是PDF格式。而且, 对于文章的导出, 需要精确URL。无法做到边浏览别导出。

另外, 我想实现的是, 可以在没有网络的情况下, 浏览自己收藏的文章。并且, 对于自己收藏的文章, 可以分类管理。

最关键的是, 对于自己的文章, 可以做一个备份。我曾经遇到过这样一件事, csdn账号密码泄漏, 使得他人登录我账号发表垃圾博文, 导致我的博客被封一天。那时候, 我的博客记录了170篇自己的学习点滴, 没有备份, 可以想像那时候我有多慌。可见, 备份自己文章的重要性。

基于以上种种原因, 这款基于iOS平台的博客导出工具应运而生。

具体功能:

1.支持在线浏览csdn博客

2.可导类型包括: 单篇文章, 专栏, 指定作者全部文章

3.导出方式包括: (1)导出单前浏览博文/专家/专栏 (2)导出指定URL博文/专家/专栏

4.导出文章分类管理

5.导出文章查询功能

6.导出文章自动排版, 图片自适应, 可放缩

运行效果:

看到这里, 如果你只是想体验一下这个应用, 想看看源码, 那可以从我的Github中下载。另外, 第一版已经上传到App Store上去了。 正在等待审核。

如果你想了解下整体开发过程, 欢迎继续往下看。推荐下载了源码, 对照着看。

你将学到:

1.自定义启动动画

2.网络环境判断(是否是Wi-Fi状态)

3.IOS与JavaScript的交互

4.自定义HUD加载效果(非传统菊花)

5.UITableView列表基本操作

6.列表关键字模糊查询

7.图片基本操作

下面逐一进行分析。

(一) 自定义启动动画

不同与传统的修改LaunchImage来加载一个静态的图片作为我们的欢迎界面, 我这里简单的实现了图片缩放, 文字渐渐显示的效果。
相对来说, 更加美观, 我们能做的操作也更加多。

打开AppDelegate.h文件, 声明一个变量, 用于显示我们的视图。

@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;
}

至此, 这篇简单的教程就结束了。希望, 能给您带来一点收获。

   
次浏览       
 
相关文章

手机软件测试用例设计实践
手机客户端UI测试分析
iPhone消息推送机制实现与探讨
Android手机开发(一)
 
相关文档

Android_UI官方设计教程
手机开发平台介绍
android拍照及上传功能
Android讲义智能手机开发
相关课程

Android高级移动应用程序
Android系统开发
Android应用开发
手机软件测试
最新活动计划
LLM大模型应用与项目构建 12-26[特惠]
QT应用开发 11-21[线上]
C++高级编程 11-27[北京]
业务建模&领域驱动设计 11-15[北京]
用户研究与用户建模 11-21[北京]
SysML和EA进行系统设计建模 11-28[北京]

android人机界面指南
Android手机开发(一)
Android手机开发(二)
Android手机开发(三)
Android手机开发(四)
iPhone消息推送机制实现探讨
手机软件测试用例设计实践
手机客户端UI测试分析
手机软件自动化测试研究报告
更多...   


Android高级移动应用程序
Android应用开发
Android系统开发
手机软件测试
嵌入式软件测试
Android软、硬、云整合


领先IT公司 android开发平台最佳实践
北京 Android开发技术进阶
某新能源领域企业 Android开发技术
某航天公司 Android、IOS应用软件开发
阿尔卡特 Linux内核驱动
艾默生 嵌入式软件架构设计
西门子 嵌入式架构设计
更多...