iOS测试UI的工具——Automation

一直被我们忽视的工具。

屏幕快照 2014-04-15 下午3.34.55

一直隐藏在Instruments中,大概是iOS4 or 5才出现的。

有点类似按键精灵,可以录制一个脚本,然后不断的重复测试。能用出来什么样的效果,可以深度挖掘一下。

屏幕快照 2014-04-15 下午3.35.45
取消左上角的录制按钮,在下面的脚本录制按钮就可以用了。点击就可以录制。

屏幕快照 2014-04-15 下午3.36.40
我使用的是模拟器,在模拟器中的操作都会被录制下来,接下来就可以随意修改脚本以供以后测试了。

官方关于Automation的api介绍:
https://developer.apple.com/library/ios/documentation/DeveloperTools/Reference/UIAutomationRef/_index.html

最后附一个gif动图

App Store上传更新报错的排除步骤

关于缺少文件、文件无效之类的错误,看错误日志可以很轻易的定位,所以本文就不再讨论。本文主要介绍的是证书配置问题的排查步骤。

最近需要上传一个更新版本,总是上传不成功。下面写一下在碰到问题时的排查步骤。
在碰到问题时总是第一反应,“我没做过啥啊”,这主观思想导致了排查问题更加困难。

screenshot1

上传之后出现如图错误,”error itms-9000 the bundle at bundle path is not signed using an apple submission certificate”

由于最近某些原因,我将keychain给重置了一下,当时申请的CertificateSigningRequest.certSigningRequest文件也已失效,再看错误日志,我怀疑是证书的问题。
随后将所有的证书重新搞了一遍。问题依然存在。

接着用继续排查,用release证书打包出来一个.app,举例如AppName.app
然后用命令行来检测证书

$codesign -vvvv AppName.app
AppName.app: CSSMERR_TP_NOT_TRUSTED

OK,终于找到了明确的错误代码了。google了一下发现是因为缺少了“Apple Woldwide Developer Relations Certification Authority”这个证书导致。

接着查看keychain,发现证书存在。只不过由于我之前折腾的时候把证书信任权限给改了,接着就出现了问题。
屏幕快照 2014-04-15 上午11.40.10

将“使用此证书”改回“使用系统默认”

再次编译,检测一下证书

$codesign -vvvv AppName.app
AppName.app: valid on disk
AppName.app: satisfies its Designated Requirement

OK,问题解除。

Core Text在绘制的时候碰到行间距问题的原因及解决办法

实在受不了目前没有一个比较完善的库来解决@人名、链接及表情的混排问题。
fork了一下TTTAttributedLabel修改了一下https://github.com/qdvictory/TTTAttributedLabel
pull回去已经被commit了,可以直接查看https://github.com/mattt/TTTAttributedLabel

在解释原因之前,需要先提出几个属性。
CLLine CTLineGetTypographicBounds 取出的 ascent descent leading
UIFont 取出的lineHeight descender ascender leading 特别提一下,descender为负值,ascender为正值

关于相关的属性解释,用一张图来展示

在Core Text中,UIFont及CLLineRef都会有一套自己的间距数据。问题就出在了CLLine上。
利用CTLineGetTypographicBounds取出的descender、ascender、leading会根据当前行里面含有字符计算出来。当此行中含有emoji或中英文之后,计算出来的数值必然与其它行有出入,出现行距不统一的问题。
我们要做的就是要将每行重新对齐。
设想一下CLLine每行都有一条基线,如果让每行都以底对齐,那么就是在CLLine的绘制原点减去descent,此时当前行就为底对齐。
接下来的问题又出现了,如果只是单纯这样操作的话,(因为进行了坐标转换)每行都会下降n像素,肯定会超出label的下范围,所以我们需要再给他一个下行的距离,而这个距离最理想的数值就是font.descender。
因而就有了代码

CGContextSetTextPosition(c, lineOrigin.x, lineOrigin.y-descent-self.font.descender);

由此我们的目的就达到了,同时也希望以后遇到此问题的人有些参考。
附2张效果图。

默认情况下

默认情况下

修改之后

修改之后

使用sphinx输出django文档

用autodoc输出的时候总是提示

environment variable DJANGO_SETTINGS_MODULE is undefined.

只要设置一下环境变量就可以顺利创建文档了。

export PYTHONPATH=$PYTHONPATH:/home/local/Projects:/home/local/Projects/projectname
export DJANGO_SETTINGS_MODULE=projectname.settings

具体步骤:
1.安装sphinx
2.进入准备存放文档的目录

sphinx-quickstart

按步骤输入内容,在autodoc那输入y表示同意。
3.进入source/index.rst里面配置,举个例子,添加如下代码

.. automodule:: minroadapp.api
   :members:

4.执行完后在build/html里面就是文档目录了

make html

sphinx带有很多主题,http://sphinx-doc.org/theming.html
只要修改conf.py然后重新make html就可以

html_theme = 'nature'

iOS开发包一键分发fir.im版,无需配置服务器,零成本。

很高兴之前写的iOS测试包分发又有了新版本。这版本是去除了服务器配置,直接使用http://fir.im来做文件存储。

相关代码在github上也放了份,有兴趣可以star下https://github.com/qdvictory/EasyToMore

xcode中添加run script,复制所有代码。只要修改一下icon地址就可以了。

因为经常完善功能,代码有所改动,建议前往github查看最新代码

#/bin/sh
# Date: 2013-06-20
# Author: Seamus
# Sina Weibo: @qdvictory

# compress application.
if [ "${CONFIGURATION}" = "Debug" ]; then

############################开发者配置#################################
#icon地址(相对于项目根目录)
pathtoartwork="iFurniture/icon/120.png"
#####################################################################

#获取app名
ipaname=`/usr/libexec/PlistBuddy -c "Print :CFBundleDisplayName $REV" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"`
#获取版本号
version=`/usr/libexec/PlistBuddy -c "Print :CFBundleVersion $REV" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"`
#appid
appid=`/usr/libexec/PlistBuddy -c "Print :CFBundleIdentifier $REV" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}"`

#打包.ipa
/bin/mkdir $CONFIGURATION_BUILD_DIR/Payload

/bin/cp -R $CONFIGURATION_BUILD_DIR/${ipaname}.app $CONFIGURATION_BUILD_DIR/Payload

/bin/cp ${pathtoartwork} $CONFIGURATION_BUILD_DIR/iTunesArtwork

cd $CONFIGURATION_BUILD_DIR

# zip up the Instasoccer directory
/usr/bin/zip -r ${ipaname}.ipa Payload iTunesArtwork

#fir.im上传第一步
d=`curl "http://fir.im/api/upload_url?appid="${appid}`
#fir.im上传第二步
postFile=`echo ${d}| ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['postFile'];"`
postIcon=`echo ${d}| ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['postIcon'];"`
shorturl=`echo ${d}| ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['short'];"`
curl -T ${ipaname}.ipa ${postFile} -X PUT
curl -T $CONFIGURATION_BUILD_DIR/iTunesArtwork ${postIcon} -X PUT
#fir.im上传第三步
postData='appid='${appid}'&short='${shorturl}'&version='${version}'&name='${ipaname}
r=`curl -X POST -d ${postData} -H "Content-Type: application/x-www-form-urlencoded; charset=utf-8" "http://fir.im/api/finish"`
short=`echo ${r}| ruby -e "require 'rubygems'; require 'json'; puts JSON[STDIN.read]['short'];"`
#输出url
`osascript -e 'tell app "System Events" to (display dialog "恭喜您,IPA上传完成。复制地址即可下载。\nhttp://fir.im/'${short}'" with title "IPA一键分享" buttons {"ok"})'`

#删除临时文件
rm -R $CONFIGURATION_BUILD_DIR/Payload
rm ${ipaname}.ipa

fi
exit 0

配置完成后,编译,OK。
Screen Shot 2013-11-06 at 1.27.03 PM

优化mysql——定时抓取processlist快照

有时开启了slow_log依然不能找到mysql的问题所在,而又不能时刻在电脑前,来一个简单的cron,定时抓取processlist快照

例子中创建process权限的mysql用户”mysqluser”,密码”mysqlpwd”,当show full processlist条数大于10时才会在路径中显示快照

创建文件cronprocesslist.sh,记得修改权限,不然无法执行.

chmod 777 cronprocesslist.sh
#!/bin/bash
[ $(/usr/local/bin/mysql -umysqluser -pmysqlpwd -h mysqlhost -e "show full processlist" | tee /pathto/plist-`date +%F-%H-%M-%S`.log | wc -l) -lt 10 ] && rm /pathto/plist-`date +%F-%H-%M-%S`.log

cron中添加

*/1 * * * * /path/cronprocesslist.sh

自动分发,一键安装v2版,部署更简单,多版本同时显示

建议先阅读第一版本,了解一下流程。本文只讲解主要配置流程。

这次版本需要安装python,mac os自带,所以用本机做分发的不需要担心。

runserver.py
这次服务器部置只要一个py文件就可以完全搞定。

py文件中只需要修改这几行

host = "http://192.168.1.188:8080/"#服务器ip
ipaname = "InstaSoccer"#与xcode打包时代码的ipa名相同
bundleid = "com.minroad.appid"#bundle id
appname = "一键安装" #app name

在xcode里run script里面加入如下代码,scp是将ipa上传到与py文件同一目录下

# Date: 2013-06-20
# Author: Seamus
# Sina Weibo: @qdvictory

# compress application.
if [ "${CONFIGURATION}" = "ad_hoc" ]; then

#.app名,默认与target name一致
ipaname="InstaSoccer"
#工程所在目录为根目录
pathtoartwork="isoccer/icon/iTunesArtwork"
#scp上传用户名及ip
sshhost="sshuser@192.168.1.188"


/bin/mkdir $CONFIGURATION_BUILD_DIR/Payload

/bin/cp -R $CONFIGURATION_BUILD_DIR/${ipaname}.app $CONFIGURATION_BUILD_DIR/Payload

/bin/cp ${pathtoartwork} $CONFIGURATION_BUILD_DIR/iTunesArtwork

cd $CONFIGURATION_BUILD_DIR

# zip up the Instasoccer directory

/usr/bin/zip -r ${ipaname}.ipa Payload iTunesArtwork

#rm -R $CONFIGURATION_BUILD_DIR/Payload 放到上传ipa之后,否则会提示签名错误

/usr/bin/scp ${ipaname}.ipa ${sshhost}:~/ipa_publish/${ipaname}_`date +%Y%m%d%H%M`_$(/usr/libexec/PlistBuddy -c "Print :CFBundleVersion $REV" "${TARGET_BUILD_DIR}/${INFOPLIST_PATH}").ipa

rm -R $CONFIGURATION_BUILD_DIR/Payload
rm ${ipaname}.ipa

fi

exit 0

如果想要下载时有图标的话,在py文件同目录下添加Icon.png文件就可以

接下来,启动Server

nohup python runserver.py 8080 > /dev/null 2>&1 &

手机访问服务器ip,一切ok
Screenshot 2013.06.20 11.38.21