Swift开发iOS应用过程中的问题和解决记录

file

虚拟机里安装OSX+XCode开发环境

用真机的请直接跳过这个部分。

主要是在VitrualBox里安装mac系统和xcode,参考这篇教程,VirtualBox的版本是4.3.18 r96156,OSX版本是10.11 El Capitan,XCode版本是7.1 (7B91b)。

经过几天的初步使用,感觉用虚拟机开发iOS基本能够满足要求,i5/8g/ssd的配置目测能达到真机70%的开发效率。主要存在的问题是:1)在宽屏上无法满屏,两边会留有黑框,导致鼠标无法顺利停靠在两侧 2)键盘敲击频率过快(约5Hz)时字符乱序出现在编辑器里,例如快速输入“update”可能会得到“updaet” 3)虚拟机里的时钟有可能不准,开发过程中偶尔有问题与此相关,需要考虑在内。

调整分辨率

以管理员方式启动virtualbox和cmd命令行(重要!),执行下面的命令

cd "C:\Program Files\Oracle\VirtualBox"

VBoxManage setextradata "OSXElCapitan" VBoxInternal2/EfiGopMode 3 (注意,参数值 0=640×480, 1=800×600, 2=1024×768, 3=1280×1024, 4=1440×900, 5=1920×1200)

VBoxManage setextradata "OSXElCapitan" "CustomVideoMode1" "1360x768x32" (必须8的整数倍,我这里没有成功)

参考链接:How to Guide for Mavericks VM on Mavericks

通过Virtualbox的远程桌面连接到虚拟机

如果是NAT方式,目标地址是127.0.0.2,用guest里通过ifconfig查看到的10.0.2.xx是不行的。 远程桌面的方式比直接使用虚拟机卡不少,作为开发使用并不实用。

修饰键

苹果键盘与Windows键盘几个修饰键的对应关系如下(在设置里可以改,这里是缺省情况):

Command键(花键 ⌘):对应windows键

Control键(⌃):对应ctrl键

Shift键(⇧):对应shift键

Option键(⌥):对应alt键

两种键盘上这几个修饰键物理布局最大的区别,在于Command键与Option键位置相反,可以去“偏好设置->键盘”里改过来,这样切换两种键盘时就比较容易适应了。

OSX

常用快捷键

官方文档

跳到行首:“Command+左键”(Home键是跳到页首)

结束任务:Command+Option+Esc

XCode7快捷键

代码辅助:control+.

打开/关闭左侧Navigator边栏:Command+0(数字0)

打开/关闭右侧Utilities边栏:Option+Command+0(数字0)

快速打开文件(Open Quickly):Shift+Command+O(字母O)

转到定义(Go to Definition):Command+鼠标点击,或Option+Command+J

自动格式化代码:Control+I(需要先全选,否则只格式化当前行)

调整模拟器大小:Command+3(50%)

Swift2

一些教程

官网:swift.org

官方文档:The Swift Programming Language, 中文版

斯坦福免费视频公开课:Developing iOS 8 Apps with Swift中文翻译

国内视频教程:精通iOS移动开发(Xcode7&Swift2)(免费,内容比较初级)

cocoachina专题:从今天开始学习Swift(大量资源链接)

常量

多数项目里都需要一些常量,java里通常定义在interface里,用swift时可以定义在一个struct里,作为静态的存储成员(static let)。

类型转换

Double转Int: Int(myDouble)

保留小数点位数

方法1(3.1415926->3.14, 3->3.00):

let i = 3.1415926
let str = NSString(format:"%.2f",i)
print("\\(str)")  //will output 3.14

方法2(3.1415926->3.14, 3->3):

let nf = NSNumberFormatter()
nf.numberStyle = NSNumberFormatterStyle.DecimalStyle
nf.maximumFractionDigits = 2
print("\\(nf.stringFromNumber(3.1415926))") //will output 3.14

时间

NSDate:相当于java.util.Date,获得系统当前时间直接用NSDate()

NSTimeInterval:等同于double,NSDate.timeIntervalSince1970可以得到自1970年的秒数(注意不是java里的毫秒数)

NSDateFormatter:用来帮助在String与NSDate类型之间做转换 参考

官方文档页

嵌套struct

注意一个地方,例如struct A里定义了struct B,实例化A时,必须先执行a.property1 = value1以后再执行b.a=a,否则会发现b.a.property1=nil。

UIView

所有控件的基类。

frame与bound的区别:frame是view的边界,bound是view可以绘制的区域(bound是可以超出frame范围的)。参考链接1 参考链接2

UITableView

基本使用:可以用ViewController里放TableView,也可以直接用TableViewController,参考How to make a simple tableview with iOS 8 and Swift

使用TableViewController时显示Activity Indicator View(菊花)有问题,不太完美的解决方案见:UITableView Activity Indicator the Apple way,或使用第三方实现,例如下面会提到的SVProgressHUD

处理cell点击事件,实现tableView:didSelectRowAtIndexPath方法即可,注意看清楚别实现成tableView:didDeselectRowAtIndexPath。 参考链接

点击cell跳转(假设从A跳到B):在storyboard里,直接从A的cell到B拖拽创建一个show类型的segue并指定此segue的identity,在A代码里实现forSegue方法将要传的参数赋值给B即可。

UICollectionView

相当于Android里的GridView,可以显示多列数据,只是没有cell的默认实现,也就是必须使用自定义cell。

要让每个cell的宽度恰好等于collection view的一半,可通过实现下面的方法实现(参考链接):

func collectionView(collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAtIndexPath indexPath: NSIndexPath) -> CGSize {
  return CGSize(width: CGFloat(self.view.frame.size.width / 2), height: self.view.frame.size.height / 3) 
}

AutoLayout

假设有一个长宽都是150的image view,里面要加载一个网络图片(尺寸未知),要求网络图片能够完整显示在image view里且最长边与image view的边长相等,如何实现呢?参考以下链接:

被这个问题困扰了一段时间,以上几个链接提供的方法都没成功。后来发现,在使用autolayout的情况下,控件的width和height应该通过constraint指定(见下图),配合contentMode=scalefit即可解决。

file

顺便提一句,在storyboard里看到的控件位置并不一定是运行时的位置,因为autolayout情况下只考虑constraint,运行时的位置在storyboard里以橘黄色虚线表示(见下图)。

file

Storyboard还提供了多设备预览功能,使用方法是“打开 Main.storyboard ,然后选择 View\Assistant Editor\Show Assistant Editor ,这时编辑区会分隔为两部分。再点击顶部导航栏中的 Automatic ,在弹出菜单中选择 Preview ,最后选择 Main.storyboard (Preview) ... 点击预览界面左下角的 + 按钮,会弹出当前storyboard文件支持的各种尺寸的设备”(来源

关于"Relative to margins"选项,在xcode7里这个选项是默认勾选的,每个view默认有宽度为8的margin,可以通过“Editor->Canvas->Show Layout Rectangles”菜单项打开,margin位置显示为蓝色细线。举例来说,当勾选了“Relative to margins”选项后,如果一个子view的leading space to 父view是0,运行时会看到子view距离父view的边界还有8的空白区域(效果相当于android里给父view设置了8的padding)。这个缺省margin值可以通过下面的方法设置:

self.rootView.layoutMargins = UIEdgeInsetsMake(0, 50, 0, 0);

参考链接:

从此爱上iOS Autolayout 

Layout Margin Comes With iOS8

第三方依赖包

依赖包管理/Carthage

先安装Homebrew(osx的包管理工具),然后通过Homebrew安装Carthage(比cocoapods灵活,去中心,只支持ios8和以上版本)。

在工程目录下新建“Cartfile”文件,并填写要依赖的包,然后执行carthage update命令,此时如果提示“unable to find utility "xcodebuild", not a developer tool”,可使用"sudo xcode-select --switch"命令解决,这样就下载了依赖包。为了让xcode能用到carthage编译的framework,先从Finder把刚才生成的.framework文件拖到工程的General -> Linked Frameworks and Libraries区域(在Navigator里点击工程根目录即可看到)里,然后在Build Phases里添加一个新内容是“/usr/local/bin/carthage copy-frameworks”的Run Script,并在Input Files里增加所需的编译后的依赖包如“$(SRCROOT)/Carthage/Build/iOS/SwiftyJSON.framework”。 参考Carthage的Getting Start 

经测试还需要在工程的Build Setting -> Framework Search Path里添加“$(SRCROOT)/Carthage/Build/iOS”,否则build会失败。参考资料

依赖包管理/CocoaPods

有些第三方依赖只支持cocoapods,所以也要装一个cocoapods。cocoapods的资料比较多,例如这篇,也比较容易安装使用。一个需要注意的问题是,执行pod setup命令后提示Setting up CocoaPods master repo要等很久,大约1小时。

在swift文件里使用object-c开发的库,需要借助一个bridging文件,通常名称是“项目名-Bridging-Header.h”。可以让xcode生成这个文件,方法是在工程里创建一个空的Objective-C文件,最后一步时xcode会提示是否创建bridging文件,点YES然后再删掉这个空文件即可。在bridging文件里使用类似#import <AFNetworking/AFNetworking.h>的方式包含依赖包。

如果pod install执行很慢,可能是pod更新spec时被墙,可以加--no-repo-update参数。参考链接

pod install --verbose --no-repo-update

还可以改用国内镜像,例如:

pod repo remove master 
pod repo add master https://git.oschina.net/6david9/Specs.git 
pod reap list

无法安装Realm:ios-charts依赖Realm,安装时很慢(有时等待数小时无果,有时提示SSL Handshake错误),其实真正原因是Realm/core所在服务器被墙。可以通过1)使用VPN解决,或2)手工下载安装core(参考Download core 0.96.0 failed),或3)使用国内镜像(如果已经下载core失败过需要清除缓存,参考Core occasionally cannot be downloaded from China)。

HTTP请求/远程图片

据说SwiftHTTP是个坑,暂时绕开,使用系统提供的NSURLSession简单封装一下。使用方法参考链接

iOS9里默认要求所有http请求都使用https,如果一定要用http,在工程的info.plist里修改“App Transport Security Settings -> Allow Arbitrary Loads”为true。

AFNetworking,功能强大且被广泛使用的Http库,还带有异步加载/缓存远程图片的功能;对应Swift版本的名称是Alamofire

JSON

暂时使用SwiftyJSON,感觉还好,使用举例:

let json1 = JSON(\["param1":1\])

下拉刷新/上拉翻页

下拉刷新:iOS8起内置了UIRefreshControl可以方便的实现下拉刷新功能 用法

上拉翻页/加载更多:暂时没有发现原生的简便方法实现,第三方库倒是比较多,例如SVPullToRefreshMJRefresh

进度条

由于TableViewController显示Activity Indicator有问题,目前在用SVProgressHUD作为替代方案。

折线图/饼图

ios-chart,项目主页的Usage里说了一堆步骤其实都是针对手动安装的,如果用cocoapods直接编辑Podfile添加pod 'Charts'再执行pod install即可,bridge都不用改,在自己的.swift文件里import Charts就可以使用了。不过我遇到一个编译问题,ChartPlatform.swift这个文件编译不过去,自己在文件结尾加了个空行解决。使用方面,一个比较好的教程见这个链接

经过试用,发现ios-charts画时序图(timeseries)比较麻烦,要自己做一些计算(参考)。

替代方案:Core Plot(侧重科学绘图),ios-linechart(使用简单),JBChartView(来自Jawbone),BEMSimpleLineGraph(使用简单)。

(本文原文链接:https://www.cnblogs.com/bjzhanghao/p/5211586.html

Nutch安装配置问题和解决

file

Nutch 1.x

按官方文档NutchTutorial安装Nutch 1.11

下载的.tar.gz解压到/usr/share目录下。

Solr 4.x

nutch 1.x支持solr 4.x(来源),官方教程也是对应solr 4.x的,所以先下载solr 4.10.4来用。

注1:NutchTutorial里有几处对schema.xml文件的修改(EnglishPorterFilterFactory等等),在nutch 1.11里已经改好了,不再需要。

注2:NutchTutorial最后部分bin/nutch solrindex命令的最后一个参数crawl/segments/,经试验应为crawl/segments/*,否则会提示找不到文件错误。

启动solr内置的jetty服务器,命令:

java -jar start.jar

然后在浏览器里访问下面的地址即可管理solr:

http://localhost:8983/solr/

在浏览器里可以使用下面的链接执行查询(即solr API):

http://localhost:8983/solr/collection1/select?q=mykeyword&wt=xml&indent=true

注:如果Solr用5.4版本的,启动命令是(Nutch的文档里example/start.jar是5.2以前的solr启动方式):

bin/solr start -e cloud -noprompt

Nutch2与Solr5的集成方式在官方文档里没有详细描述,solr5的目录结构与solr4不一样(没有collection1),以下文章可参考:文章1

mmseg4j

为支持中文分词,我们使用mmseg4j项目。

从github上的mmseg4j主页下载2.3.0版本,解压后得到两个.jar文件,放在 /usr/share/solr-4.10.4/example/solr-webapp/webapp/WEB-INF/lib/ 目录下,并在schema.xml里加入mmseg4j的field types。

参考1

注意:要特别注意mmseg4j与solr的版本匹配,在mmseg4j的下载包里有说明,针对solr 4.9和4.10要使用mmseg4j的2.2.0版本。如果使用了mmseg4j 2.3.0版,分词时会提示java.lang.RuntimeException: java.lang.AbstractMethodError异常。

Nutch 2.x

首先是官方文档,实在是太简略了点,这篇文章一起参考一下。

按官方文档进行到ant runtime命令时有两个问题:1)需要等比较久且一开始的几分钟内没有进度;2)可能会警告找不到tools.jar文件,只要yum安装java-1.7.0-openjdk-devel即可(注意不要用java 1.6,版本过低会导致编译失败),JAVA_HOME环境变量在/etc/profile里指定,执行source /etc/profile以便不重启生效。

进行到bin/nutch inject urls这一步时可能会报一些找不到类异常或VerifyError错误,一般是由于nutch与hbase里一些jar包版本不一致造成的,解决方法是用hbase里的jar代替nutch里的相应jar包。主要是$hbase_home$/lib目录下的hbase*.jar、hadoop*.jar、htrace*.jar和protobuf*.jar,复制到$nutch_home$/runtime/local/lib目录下,注意先移除旧的jar包。

遇到一个不好解决的问题:ava.lang.IncompatibleClassChangeError: Found interface org.apache.hadoop.mapreduce.TaskAttemptContext, but class was expected。仔细又看了官方文档,与Nutch2配套的hbase建议是hbase-hadoop(没写hadoop1或hadoop2,原来是指hadoop1,虽然hbase的quickstart里说大部分情况用hadoop2:“in most cases, you should choose the file for Hadoop 2”),之前我是按hadoop2下载的,改为hadoop1环境即可。

改为hadoop1后,nutch inject可以正常执行了,但nutch generate时遇到java.lang.NoSuchMethodError: org.apache.hadoop.hbase.HRegionLocation.getServerAddress()异常。问题应该是gora-hbase版本,在ivy.xml里改为0.6.1,重新ant runtime,发现build出来的hbase相关的jar包自动都升级为0.98了(之前ivy.xml里是0.5,对应0.94),而且包文件名都带hadoop2!然后inject时又报java.lang.IncompatibleClassChangeError: Found interface org.apache.hadoop.mapreduce.Counter, but class was expected异常(在hadoop.log里看)。

待参考:http://www.cnblogs.com/mactech/p/4229708.html http://stackoverflow.com/questions/26236112/hadoop-2-5-1-nutch-2-2-1-found-interface-org-apache-hadoop-mapreduce-taskatte

再次查看官方文档,发现其中的nutch2下载链接有变化(也许是我记错了),以前我下载的是nutch 2.3,现在指向的是nutch 2.3.1。下载2.3.1后查看ivy.xml发现gora版本是0.6.1(nutch 2.3时对应gora 0.5),且hadoop对应2.5.2(nutch 2.3时对应hadoop 1.2.0)。重新用nutch 2.3.1按官方文档,配合hbase-0.98.8-hadoop2,所有问题解决。

solr5引入了configset的概念,所以schema.xml文件的位置与solr4有所不同。

nutch-site.xml配置文件说明:见此链接

nutch2.3.1使用crawl命令时提示“No IndexWriters activated - check your configuration”错误,解决方法是在nutch-site.xml里添加plugin.includes属性,详见此链接

nutch2.3.1里solrindex被index取代,指定solr地址改为-D solr.server.url=xxx,例如bin/nutch index -D solr.server.url=http://localhost:8983/solr 1453805148-685784700 -crawlId crawl2

nutch2.3.1的parse步骤提示“http://news.sina.com.cn/ skipped. Content of size 130163 was truncated to 65536”,在nutch-site.xml里设置http.content.limit为-1。(nutch-default.xml里可以看到所有可设置的项)

nutch2.3.1的updatedb步骤耗时过长:查看logs/hadoop.log发现无法连接到hbase在一直重试,不知道什么原因hbase停止了,$HBASE_HOME$/bin/start-hbase后updatedb继续完成。

nutch2.3.1的fetch步骤控制台里显示“... 500 URLs in 2 queues”,实际队列里的url数量超过500但无法显示,原因见这个链接

注意:两个配置文件regex-normalize.xml和regex-urlfilter.xml起作用是有先后的,normalize在前,所以filter时用来匹配的url是经过normalize的。例如http://my.website.com/product/38392/?from=mobile这样一个url,在normalize步骤有可能已经变成了http://my.website.com/product/38392/。这两个配置文件里使用的正则表达式遵守Perl5语法

seed.txt里的url可以用"#"注释

删除solr里已索引的文档:

curl http://localhost:8983/solr/collection1/update --data-binary "<delete><query>\*</query></delete>" -H 'Content-type:text/xml; charset=utf-8'
curl http://localhost:8983/solr/collection1/update --data-binary "<commit/>" -H 'Content-type:text/xml; charset=utf-8'

使用bin/crawl脚本抓取时,发现regex-urlfilter.txt没起作用,原因是bin/crawl脚本里的generate命令加了-noFilter参数,去掉后解决。 

通过solr-index命令导入solr的文档,tstamp字段值都是"1970-01-01T00:00:00Z"。根据nutch用户组里的讨论,tstamp字段应该是抓取网页的时间,不应该为空(1970)。但检查了solrindex-mapping.xml文件,里面tstamp字段的stored参数值已经是true。暂时的解决方案,在nutch-site.xml的plugin.includes里添加index-more插件,这样在solr索引的每个文档里会多出date、contentLength等若干个新字段,其中date字段可用于表示文档的抓取时间。

Nutch常用参数

1、同一服务器两次抓取间隔:nutch-site.xml里fetcher.server.delay

2、只抓取站内链接:nutch-site.xml里db.ignore.external.links

3、从页面里最多解析出多少个链接:nutch-site.xml里db.max.outlinks.per.page 

Hbase

常用命令

由于磁盘空间占满,扩容后hbase无法正常启动。查看$hbase_home$/logs/后发现ERROR master.HMasterCommandLine: Master exiting / java.io.EOFException at ...readInt,看起来像是zookeeper在读取数据文件时报的错误,可能是之前的非正常停止导致数据文件损坏,于是在$hbase_home$/conf/hbase-site.xml配置文件里将hbase.zookeeper.property.dataDir指向另一个新建的目录,再start-hbase恢复正常。

有用链接:HBase集群安装过程中的问题集锦

Nutch集群

在name节点上

首先配置hadoop,主要参考Hadoop: Setting up a Single Node Cluster,按Pseudo-Distributed Operation配置。

1.下载hadoop-2.7.2/hadoop-2.7.2.tar.gz并解压缩到/usr/share/目录下

2.编辑/etc/profile文件,在结尾处添加export $HADOOP_HOME=/usr/share/hadoop-2.7.2和export PATH=$PATH:$HADOOP_HOME/bin这两句,以便nutch脚本可以找到并执行hadoop。

3.编辑$HADOOP_HOME/etc/hadoop/hadoop-env.sh,将JAVA_HOME指到java安装目录(即使在/etc/profile里已经有JAVA_HOME,这一步也不能省略)

4.通过访问http://localhost:50070/可看到dfs信息

5.设置hbase-site.xml让hbase使用hdfs:

<property>
  <name>hbase.cluster.distributed</name>
  <value>true</value>
</property>
<property>
  <name>hbase.rootdir</name>
  <value>hdfs://cluster1:9000/hbase</value>
</property>

如果启动hbase时提示找不到JAVA_HOME,修改hbase-env.sh脚本。

6.修改yarn-site.xml:

<property>
    <name>yarn.resourcemanager.hostname</name>
    <value>cluster1</value>
</property>
<property>
    <name>yarn.nodemanager.aux-services</name>
    <value>mapreduce\_shuffle</value>
</property> 

在data节点上:

1.安装hadoop,步骤和name节点上相同。

2.将name节点的authorized_keys文件scp到data节点,确保name节点可以不用密码ssh到data节点

3.将name节点的几个配置文件复制到data节点相同目录下:

scp /usr/share/hadoop-2.7.2/etc/hadoop/core-site.xml root@cluster2:/usr/share/hadoop-2.7.2/etc/hadoop/core-site.xml
scp /usr/share/hadoop-2.7.2/etc/hadoop/hdfs-site.xml root@cluster2:/usr/share/hadoop-2.7.2/etc/hadoop/hdfs-site.xml
scp /usr/share/hadoop-2.7.2/etc/hadoop/mapred-site.xml root@cluster2:/usr/share/hadoop-2.7.2/etc/hadoop/mapred-site.xml
scp /usr/share/hadoop-2.7.2/etc/hadoop/yarn-site.xml root@cluster2:/usr/share/hadoop-2.7.2/etc/hadoop/yarn-site.xml

4.在name节点的/etc/hosts里添加data节点的ip,例如“10.0.0.2 cluster2”,否则data节点可能会无法连接到name节点(“Datanode denied communication with namenode because hostname cannot be resolved”)

5.在name节点的$HADOOP_HOME/etc/hadoop/slaves里添加data节点的ip地址

6.(如果执行job时提示找不到HBaseConfiguration等异常,说明.job文件里缺少相应的jar包),用下面的方法重新打包:

cd runtime/deploy
unzip -d apache-nutch-2.3.1 apache-nutch-2.3.1.job 
rm  apache-nutch-2.3.1.job 
cd apache-nutch-2.3.1 
rm lib/hbase-\*\*\*.jar 
cp /usr/share/hbase-0.98.8-hadoop2/lib/hbase-common-0.98.8-hadoop2.jar lib/ 
cp /usr/share/hbase-0.98.8-hadoop2/lib/hbase-client-0.98.8-hadoop2.jar lib/
cp /usr/share/hbase-0.98.8-hadoop2/lib/hbase-protocal-0.98.8-hadoop2.jar lib/
zip -r ../apache-nutch-2.3.1.job ./\* 
cd .. 
rm -r apache-nutch-2.3.1

补充:还要修改deploy里nutch-site.xml、hbase-site.xml,并打到.job包里。 

7.在hdfs上创建种子列表目录

hdfs dfs -mkdir /urls
hdfs dfs -put seed.txt /urls

参考:

Nutch and Hadoop Tutorial

Running Nutch in (pseudo) distributed-mode (Nutch1.x)

INSTALL HADOOP+HBASE+NUTCH+ELASTICSEARCH

验证hadoop

hadoop自带了一些示例应用,可以用于验证hadoop集群是否正常,以wordcount为例:

hdfs dfs -mkdir /wordcount
hdfs dfs -mkdir /wordcount/input

#编辑一个本地文件test.txt并输入一些单词或短语,例如hello word,每个占一行
vi test.txt
#输入内容(略)
hdfs dfs put test.txt /wordcount/input

#/wordcount/output目录必须“不存在”,否则会报错
hadoop jar $HADOOP\_HOME/share/hadoop/mapreduce/hadoop-mapreduce-examples-2.7.2.jar wordcount /wordcount/input/\* /wordcount/output

#查看hdfs上生成的结果
hdfs dfs -ls /wordcount/output
hdfs dfs -cat /wordcount/output/part-r-00000

另:集群里每台机器的hostname最好与/etc/hosts文件里所用的保持一致。

遇到的问题:

1、org.apache.zookeeper.ClientCnxn: Opening socket connection to server localhost/127.0.0.1:2181. Will not attempt to authenticate using SASL (unknown error)

解决:查看datanode上的$HADOOP_HOME$/etc/hadoop/logs/yarn-root-nodemanager-xxx.log文件,发现org.apache.hadoop.ipc.Client: Retrying connect to server: 0.0.0.0/0.0.0.0:8031的错误信息。参考这个帖子,在datanode的yarn-site.xml里添加了yarn.resourcemanager.hostname属性,0.0.0.0异常消失,但无法连接到2181端口问题依旧。后检查发现master上的hbase-site.xml有两个,其中一个在/usr/share/hbase-xxx目录下,另一个在nutch/runtime/deploy里,前者里没有配置hbase.zookeeper.quorum属性,添加后重启hbase问题解决(另外还添加了一个hbase.master属性值为master:60000)。

Nutch二次开发

网站内容抽取

可采用boilerpipe,一个开源的基于训练的内容抽取库。或采用针对每个网站分别定制的方案,参考链接1

支持js加载

考虑phantomjsselenium

自定义如何Parse所抓取到的网页

使用ParsingFilter和IndexingFilter,参考链接

Solr查询

Solr的查询语法很丰富,通过组合各种参数可以达到多种查询目标,官方文档可通过这个链接下载(pdf格式):Apache Solr Reference Guide

限定在指定日期范围内的文档里搜索:fq=date:[2016-02-15T00:00:00Z TO 2016-02-15T23:59:59Z]

要进行分组统计,使用facet参数,例如统计最近30天内指定关键词出现次数(注意:网上有些资料使用facet.date,这个参数已经在solr 3.1以后deprecated了,用facet.range替换):facet=true&facet.range=date&facet.range.start=NOW/DAY-31DAY&facet.range.end=NOW/DAY&facet.range.gap=%2B1DAY (%2B是URL encode后的加号)

其他爬虫工具

WebCollector

Heritrix3

(本文原始链接:https://www.cnblogs.com/bjzhanghao/p/5104653.html

使用AndroidStudio 1.3.2遇到的一些坑

以下环境为Android Studio 1.3.2,Gradle 2.7(as自带2.4,单独下载的2.7)

编译时提示Multiple dex files define: Lcom/sina/weibo/sdk/BuildConfig异常

新浪微博提供的SDK里所带的weibosdkcore.jar里包含了BuildConfig类,而api工程也会生成同名(包名也相同)类,所以有此编译异常。解决方法是用工具(如7zip)直接删除weibosdkcore.jar里的BuildConfig.class文件。还有其他解决方法,这个链接不错。

无法clean project

有时clean后仍然有文件残留(例如classes.jar),此时需要手工删除项目路径下的build目录(删除时可能会提示classes.jar被占用,多半是as自己在使用,可关闭as再重试)。比较恶心的是,clean时并不会提示你有文件无法删除。

两个project共享一个module

假设自己写了一个android library(名称library1),然后想在Project1和Project2里都使用它,但不把library1复制两份。窍门是在project2的setting.gradle文件里像下面这样引用project1里的资源:

include ':../project1/library1'

参考链接

Configuration with name 'default' not found.

检查settings.gradle文件里,include的module是否存在,通常是include了不存在的module造成的。参考链接

Proguard提示Duplicate Entry错误

多个module依赖多个相同的jar文件时会有这个问题,我当时遇到的是xutils,解决办法是在jcenter上找到了对应的repository,改为不直接使用jar而是使用repository解决。Proguard Troubleshooting

用proguardFile还是proguardFiles?

在build.gradle里指定项目proguard配置文件时,用proguardFiles可以同时指定多个,用proguardFile可指定一个(可多行),经测试效果是一样的。注意:在module settings对话框里可能会显示不出来正确的文件名。还有一个变化:比较新的as版本缺省文件名是proguard-rules.pro,以前是proguard-rules.txt。

被依赖module里BuildConfig.DEBUG的值总为false

例如module A依赖module B和module C,在Eclipse里运行时B和C里BuildConfig.DEBUG的值会是true(导出签名apk后会自动变成false);然而在Android Studio里B和C里的BuildConfig.DEBUG值总是false,A里的正常。这样就导致if(BuildConfig.DEBUG){Log.d(...)}日志无法正常显示。参考链接 参考链接2

Android 5.0/5.1开发问题专贴

注:非5.0特定的开发问题,可以在这个帖子里查:Android开发问题汇总

1、官方提供的例子android-support-v7-appcompat编译时提示android:actionModeShareDrawable属性不存在

官方例子里这个工程的target是19,需要改为21才能正确编译,否则提示

error: Error: No resource found that matches the given name: attr 'android:actionModeShareDrawable'.

。具体方法是修改project.properties文件,将target=19改为target=21,然后clean此工程或重启eclipse即可。参考链接

若仍然无法编译,可能是appcompat的版本不是最新,请通过sdk manager将support包全部升级到最新版(见下图,图片来自这里。国内用户如果无法升级,可修改hosts文件将dl-ssl.google.com静态解析到可访问的ip地址,ip地址可参考这个帖子,在超级ping里获取到)。

file

2、parseSDKContent failed问题

升级sdk到5.0以后,原来的Eclipse经常弹出parseSDKContent错误对话框,甚至有时会提示AndroidManifest file missing。

file

解决方法是删除.android目录(参考链接,在windows里这个目录是C:\Documents and Settings\YOUR_USER_NAME\.android或C:\Users\YOUR_USER_NAME\.android),不过这样会同时删除掉debug.keystore文件。也有人说不需要删除整个.android目录,更新DDMS就可以了(是指更新ADT?),但我没有试过。

3、谷歌开源的Material Design图标

file

可以从GitHub上下载,链接在此。另外,materialdesignicons.comandroidicons.com这两个网站也提供了一些不错的material design图标下载。

其他开源图标库:阿里巴巴提供的iconfont.cn,图标社区NounProject

在线LowPoly生成器:Trianglify

4、PreferenceActivity不显示actionbar

参考这个帖子,目前support包不支持PreferenceActivity(没有PreferenceActionbarActivity这样的类),所以解决方法要么是改用PreferenceFragment,要么使用第三方的补丁包(Fragment的方案),另一个补丁包(Activity的方案,但有缺陷——getPreferencesXmlId()只接受一个preference.xml文件)。

5、Dialog Theme的actionbar背景颜色显示不全

如下图所示,当使用Theme.AppCompat.Light.Dialog时发现actionbar背景色只显示出一半。根据这个帖子的讨论,可能是AppCompat的目前版本还没有做好。

file

6、使用appcompat里RecyclerView和CardView时的问题

GitHub上的这个开源项目可以帮助解决一些问题,例如添加divider、点击事件等等,但还远远不够。

CardView的多状态背景色问题,暂时没有解决,参考链接

下拉刷新:可使用android原生的SwipeRefreshLayout解决;

上拉翻页:方案1)仍使用SwipeRefreshLayout; 方案2)自己监听事件实现Endless效果;

HeaderView:RecyclerView没有像ListView那样提供addHeaderView()方法,要实现类似效果,有两种方法:1)将第一个item作为header,使用android-parallax-recyclerview这个库; 2)让第一个item完全透明,下层显示一个同高的view作为header,使用ASOV这个库。

7、实现Material Design(简称MD)的方方面面

MD是一系列UI特性的组合,阿里巴巴团队的这个帖子介绍得清晰易懂,但要在我们的应用里逐一实现这些特性就不那么容易了,特别是要兼容Android 4.x甚至2.x的时候。Google官方AppCompat v21在这方面只提供了有限的支持,例如ActionBar和侧滑菜单,而像FAB(Fixed Action Button)等等则没有包含在内。

其实在GitHub上已经有不少第三方的实现,值得一提的是,这个名为MaterialDesignCenter的项目把大量相关项目汇总在了一起供开发者参考,值得一看。以下列出我认为值得使用的第三方实现:

FAB: FloatingActionButton

对话框: material-dialogs

各类UI控件: MaterialDesignLibrary

另外几个汇集了android上各类交互效果的项目Interactive-animationawesome-android-uiandroid-open-project(300+项目,不仅限于MD),同样值得参考。

8、使用SlidingTabLayout替代Actionbar的tab导航

v7包的Actionbar对象里,与navigation有关的方法(例如setNavigationMode)都不建议使用了,应使用googleio2014提供的SlidingTabLayout实现类似功能。

参考链接1参考链接2

9、Android 5.1将AlarmManager的setInterval()最小值限制为1分钟

这个比较坑,毕竟有一些应用依赖AlarmManager机制进行更新,当设备升级到android 5.1后就会出现问题。由于开发文档里并没有提到,所以具体情况见googlecode上的讨论。讨论链接需翻墙,google主要回复如下:

“If you are trying to run more often than every 5 seconds, alarms are the wrong way to go about it. Waking up the device that often is extremely bad for battery life. If you have live UI that needs to be updated continually, use a wakelock and then schedule your activity on a handler. This is actually *more* battery efficient than setting an alarm every second.”

替代方法是在Service里使用ScheduledExecutorService实现定时任务,与AlarmManager的区别见 参考链接

10、使用Android Support Design开发包实现Material Design

Google在2015 I/O大会推出了Android Support Design开发包,方便开发者实现多种常用的MD效果。以下几个有用链接:

INTRODUCTION TO COORDINATOR LAYOUT ON ANDROID

(译)掌握 Coordinator Layout 

高逼格UI-ASD(Android Support Design)

NestedScrollView

CoordinatorLayout与滚动的处理

Android Design Support Library使用详解

(搬家前链接:https://www.cnblogs.com/bjzhanghao/p/4194164.html