XCode 项目配置说明
基本项(Basic)
1、Architectures(指令集)
(1)armv7,支持的机器iPhone4,iPhone4S
(2)armv7s,支持的机器iPhone5,iPhone5C
(3)arm64,支持的机器:iPhone5S及之后版本
Build Active Architecture Only :是否只编译当前适用的指令集。
Valid architectures :指即将编译的指令集。
Base SDK----当前编译用的SDK版本
iPhone OS Deployment Target----指的是编译出的程序将在哪个系统版本上运行。
Localizations:定义了我们应用的本地化语言
2、Build Options:
validate Built Product:boolean 类型,指定是否执行产品验证测试(就是说是否使用你的证书进行验证测试)。一般在Debug版本设置成NO,release版本设置成Yes。
3、Code Signing 代码签名
Code Signing Identity-----代码签名的身份,即选择签名证书,一是开发证书,二是发布证书。
4、Search Paths 查询路径
Always Search User Paths--- 是否搜索用户路径
Header Search Paths (HEADER_SEARCH_PATHS)
TARGET的配置配置,主要分为5大部分GeneralCapabilitiesInfoBuild SettingsBuild Phases和Build Rules。
General:通用配置里面包括了一些应用基本信息的配置。这个里面着重介绍一下下面的着几个配置。
version & build:从名字上来看就可以很清楚的区分这两个字段的不同:一个是当前的版本号,对应Info.plist里面的CFBundleShortVersionString字段;另一个是你当前版本的编译次数,对应Info.plist里面的CFBundleVersion字段。
Deployment Target:定义了我们这个应用允许在哪个iOS SDK版本以上才可以安装或升级。
General:通用配置里面包括了一些应用基本信息的配置。
version & build:一个是当前的版本号,对应Info.plist里面的CFBundleShortVersionString字段;另一个是你当前版本的编译次数,对应Info.plist里面的CFBundleVersion字段。
Deployment Target:定义了我们这个应用允许在哪个iOS SDK版本以上才可以安装或升级。
Info:这里面定义了我们应用里面用到的所有信息。
Custom iOS Target Properties:从上图中我们可以看出,Custom iOS Target Properties就是Info.plist里面的内容。在这个里面,我们可以更改:Bundle name(iOS桌面上显示的名字);Bundle identifier等...
URL Types:我们的程序可以向系统注册自己的URL Scheme,来使得另外一个App可以通过这个 URL Scheme 来打开我们的应用。
Build Settings:这里面包括了我们在编译过程中会用到的所有配置。
Code Signing Idenity:这个选项是用来告诉 Xcode,你编译的时候是用哪个证书来签名的。通常情况下,Debug 可以选择 iOS Developer; Release 可以选择 iOS Distribution;
Preprocessor Macros:可以这个里面定义一些预处理的宏。例如,Xcode 自动帮你在 Debug 里面定了一个宏DEBUG=1,这样就可以用这个宏来判断当前的App是不是Debug版本了。也可以用它来为你的内部版本增加一些测试功能。
Search Path:可以用来指定你的工程可以在哪个目录下,搜索头文件、Framework或者库。
Build Phases:是应用管理源文件、资源和依赖的地方。主要分为下面的这四个部分:
Target Dependencies:是用来管理你的Target依赖的。在几年前,基本上都是使用它来做第三方工程依赖的。现在基本上都是使用Cocoapods来引导第三方的项目了。
Compile Sources:是用来管理你这个应用里面需要编译的所有源文件的。所以,一个Target里面并不一定要编译和使用左侧工程里面的所有源文件。
Link Binary With Libraries:是用来管理二进制库和Framework的。
Copy Bundle Resources:是用来设置你需要拷贝到Main Bundle里面的资源文件的,里面可能会包括 storyboard,xib,图片文件,JS 文件,CSS 文件,其他的资源包 等等。
Other
Charles:移动端抓包工具
通信安全工具:
IP*Works! Internet Toolkit v9.0
IP*Works! EDI/AS2 v9.0
IP*Works! S/MIME v9.0IP*Works! SSHIP*Works! SSL
代码混淆工具:
.NET Reactor v4.9DotfuscatorDashO Pro v7.3
Zend Guard
MACターミナルの主要コマンド
mkdir
「mkdir 作成したいディレクトリ名」で実行します。
rm
「rm ファイル名」で実行します。
rm -R "削除するディレクトリの最上位にあたるディレクトリのパス"
mv
「mv AAA BBB」
cp
「cp AAA BBB」と入力すると、AAAというファイルがBBBという名前でコピーされます。
man
「man マニュアルを開きたいコマンド名」で実行します。
find
「find 検索する場所 -name 検索するファイル名」で実行します。
open
open "ファイルのパス”
rmdir
rmdir "削除するディレクトリのパス
sudo
指定したコマンドをroot権限で実行する。
sudo "コマンド名"
whites
指定したコマンドの概略機能を表示する。
whatis "コマンド名"
chmod
其语法格式为:chmod [who] [opt] [mode] 文件/目录名
其中who表示对象,是以下字母中的一个或组合:
u:表示文件所有者
g:表示同组用户
o:表示其它用户
a:表示所有用户
opt则是代表操作,可以为:
+:添加某个权限
-:取消某个权限
=:赋予给定的权限,并取消原有的权限
而mode则代表权限:
r:可读
w:可写
x:可执行
sudo chmod -R 777
yum -y install wget
MAC下SVN的常用命令
1、checkout
svncheckoutsvn地址,简写:svncosvn地址
2、添加文件
svnadd test.txt 添加单一文件
svnadd *.* 添加所有文件
svnadd *.php 添加所有后缀为php的文件
3、提交文件
svnci -m “描述(可留空)” 文件名 提交单一文件
svnci -m “描述(可留空)” 提交所有文件
4、删除文件
svndelete 文件名
简写:svn(del, remove, rm)
5、加锁/解锁
svnlock -m “LockMessage“ [--force] PATH
svnunlock -m “LockMessage“ [--force] PATH
6、svnupdate,简写svnup
svnupdate 更新所有文件
svnupdate -r 200 test.php (将版本库中的文件test.php还原到版本200)
svnupdate test.php (更新单一文件,于版本库同步。如果在提交的时候提示过期的话,是因为冲突,需要先update,修改文件,然后清除svnresolved,最后再提交commit)
7、查看文件详细信息
svninfo 文件名
8、查看日志
svnlog 文件名
9、svnstatus [path]其字符的含义如下:
简写:svnst
‘ ‘ no modifications. 没有改动
‘A’ Added. 新增加的项目
‘C’ Conflicted. 项目内容与更新得到的数据冲突了
‘D’ Deleted. 要删除的项目
‘I’ Ignored. 已忽略
‘M’ Modified. 内容有改动
‘R’ Replaced. 在svn仓库中是一个目录, 在本地是一个同名的文件. 反之亦然.
‘X’ 项目未版本化, 与外部连接相关
‘?’ 未版本化的文件
‘!’ 项目丢失, 或者说目录不完整
‘~’ 本地有一个未版本化的项目, 在svn仓库里有一个同名项目
10、比较差异
svndiff path
例如:svndiff test.php
svndiff -r m:n path(对版本m和版本n比较差异)
例如:svndiff -r 200:201 test.php
简写:svndi
$ svn log -r 20 touched.txt --diff
11、将两个版本之间的差异合并到当前文件
svnmerge -r m:n path
例如:svnmerge -r 200:205 test.php(将版本200与205之间的差异合并到当前文件,但是一般都会产生冲突,需要处理一下)
12、SVN帮助
svnhelp
svnhelp ci
svn revert --depth=infinity 对文件夹里所有文件进行revert
利用可能なサブコマンド:
add
blame (praise, annotate, ann)
cat
changelist (cl)
checkout (co)
cleanup
commit (ci)
copy (cp)
delete (del, remove, rm)
diff (di)
export
help (?, h)
import
info
list (ls)
lock
log
merge
mergeinfo
mkdir
move (mv, rename, ren)
propdel (pdel, pd)
propedit (pedit, pe)
propget (pget, pg)
proplist (plist, pl)
propset (pset, ps)
resolve
resolved
revert
status (stat, st)
switch (sw)
unlock
update (up)
実際のコマンド使用例
ではでは、個人的によく使う svn コマンドの使用例です。勝手に分類してご紹介します。
作業コピー操作系
作業コピーのチェックアウト。
svn co http://example.com/subversion/repository/trunk /var/www/working_copy
作業コピーの更新。
svn up /var/www/working_copy
ファイルの追加。--parents オプションを付けるとファイルまでのディレクトリで追加されていないものがあれば一緒に追加してくれます。
svn add --parents /var/www/working_copy/htdocs/index.html
変更点のチェックイン(コミット)。-m オプションはコミット時のコメントを指定するのに使います。
svn ci -m "index.html を追加。" /var/www/working_copy/htdocs/index.html
作業コピー上での変更を取り消す。
svn revert /var/www/working_copy/htdocs/index.html
作業コピーのクリーンアップ。
svn cleanup /var/www/working_copy
作業コピーの切り替え。
svn sw http://example.com/subversion/repository/branches/20100908 /var/www/working_copy
--relocate オプションで別リポジトリへの切り替えが可能です。(リポジトリの移行時など)
svn sw --relocate http://old.example.com/subversion/repository/trunk http://new.example.com/subversion/repository/trunk /var/www/working_copy
リポジトリ操作系
trunk をコピーして新しい branch を作成。
svn cp -m "2010/09 作業分の branch 作成。" http://example.com/subversion/repository/trunk http://example.com/subversion/repository/branches/201009
trunk を branch に移動。
svn mv -m "2010/09 時点での trunk を branch に移動。" http://example.com/subversion/repository/trunk http://example.com/subversion/repository/branches/201009
古い branch を削除。
svn rm -m "一年前の branch を削除。" http://example.com/subversion/repository/branches/200909
情報参照系
作業コピーの情報を確認。
svn info /var/www/working_copy
変更履歴を表示。
svn log /var/www/working_copy/htdocs/index.html
リポジトリと差分のあるファイル一覧を表示。
svn stat -u /var/www/working_copy/
リポジトリとの差分を表示。
svn di /var/www/working_copy/htdocs/index.html
-r オプションで指定したリビジョンとの差分を見れます。
svn di -r 10 /var/www/working_copy/htdocs/index.html
svn:mergeinfo や svn:ignore などの属性情報を表示。
svn pl -v /var/www/working_copy
branch から trunk の作業コピーにマージ系
リビジョンを指定してマージ。
svn merge -c 10,12,18 http://example.com/subversion/repository/branches/201009 /var/www/working_copy
-r でリビジョン範囲を指定できます。
svn merge -r 10:18 http://example.com/subversion/repository/branches/201009 /var/www/working_copy
適用されていない変更点を全てマージ。
svn merge --reintegrate http://example.com/subversion/repository/branches/201009 /var/www/working_copy
ちなみに --dry-run オプションでマージ対象のファイルの一覧が見れます。
svn merge --dry-run --reintegrate http://example.com/subversion/repository/branches/201009 /var/www/working_copy
instruments学习笔记(一)
//调用外部js
#import “../common/common.js”
//导航栏操作
UIATarget.localTarget().frontMostApp().navigationBar().leftButton().tap(); //点击左侧按钮
UIATarget.localTarget().frontMostApp().navigationBar().rightButton().tap(); //点击右侧按钮
//按钮点击
UIATarget.localTarget().frontMostApp().mainWindow().buttons()[“xxxxx”].tap();
//坐标点击
UIATarget.localTarget().tap({x:30,y:131});
//等待n秒,delay(n)
UIATarget.localTarget().delay(3);
//截图
UIATarget.localTarget().captureScreenWithName(“picname”);
//获取对象数组长度,length
UIATarget.localTarget().frontMostApp().mainWindow().buttons().length;
//获取文本字符串,value()
UIATarget.localTarget().frontMostApp().mainWindow().scrollViews()[0].staticTexts()[0].value();
//滚轮滚动,dragInsideWithOptions()
UIATarget.localTarget().frontMostApp().mainWindow().pickers()[0].wheels()[0].dragInsideWithOptions({startOffset:{x:0.38, y:0.66}, endOffset:{x:0.38, y:0.12}, duration:1.6});
//根据name模糊查询控件,firstWithPredicate(“name beginswith ‘xxx'”)
obj= window.tableViews()[0].cells().firstWithPredicate(“name beginswith ‘hello'”);
//根据name完全匹配,firstWithName(“xxxx”)
obj= window.tableViews()[0].cells().firstWithName(“hello world”);
//根据key值匹配,firstWithValueForKey(value,key)
obj= window.tableViews()[0].cells().firstWithValueForKey(“hello world”,”name”);
//拖动
window.tableViews()[0].scrollDown();
window.tableViews()[0].scrollUp();
window.tableViews()[0].scrollLeft();
window.tableViews()[0].scrollRight();
//打印当前屏幕所有空间信息
UIATarget.localTarget().logElementTree();
//记录日志
UIALogger.logStart(“start”);
UIALogger.logPass(“pass”);
UIALogger.logWarning(“warning”);
UIALogger.logFail(“fail”);
UIALogger.logMessage(“message”);
UIALogger.logError(“error”);
UIALogger.logDebug(“debug”);
UIALogger.logIssue(“issue”);
//九宫格搜索输入框
UIATarget.localTarget().frontMostApp().mainWindow().searchBars()[0]
//模拟键盘操作,keyboard().typeString(“xxx”)
UIATarget.localTarget().frontMostApp().keyboard().typeString(“aaa\n”);
\n=回车
//输入框输入,setValue()
UIATarget.localTarget().frontMostApp().mainWindow().tableViews()[“Empty list”].cells()[“用户名:”].textFields()[0].setValue(“abcd”);
instruments如何处理alert对话框
被测应用中有出现alert对话框,需要点击处理。绕了很多弯路,回头想想其实很简单。
1. onAlert事件要放在执行代码前面
2. onAlert事件中return值需要为true。如果是false,系统自动点击cancel按钮,如果cancel按钮不存在,则点击默认按钮。
3. 按顺序写执行代码即可
var target = UIATarget.localTarget();
UIATarget.onAlert = function onAlert(alert) {
var title = alert.name();
UIALogger.logWarning(“Alert with title ‘” + title + “‘ encountered.”);
// return false to use the default handler
return true;
}
target.frontMostApp().mainWindow().tableViews()[“空列表”].cells()[“xxx, 用户注销”].tap();
// Alert detected. Expressions for handling alerts should be moved into the UIATarget.onAlert function definition.
target.frontMostApp().alert().defaultButton().tap();
1.消息及执行结果打印――UIALogger
UIALogger.logMessage(commonMsg);
UIALogger.logPass(testApp);
UIALogger.logFail(testApp);
UIALogger.logWarning(warningMsg);
2.文本框输入
app.keyboard().typeString(englishOnly);
window.textFields()[index].setValue(englishChinessMixed);
3.隐藏键盘
app.keyboard().typeString("\n");
app.keyboard().buttons()["搜索"].tap();
4.判断staticText存在与否(不同布局存在差异,以下仅为一种方式)
if (window.elements()["待判断关键字"]) {
UIALogger.logMessage("存在关键字");
} else {
UIALogger.logMessage("不存在关键字");
}
5.tableView关键字判断(不同布局存在差异,以下仅为一种方式)
if(window.tableViews()[0].cells()["关键字"].isVisible()) {
UIALogger.logMessage("存在关键字");
} else {
UIALogger.logMessage("不存在关键字");
}
6.scrollView控件选取(不同布局存在差异,以下仅为一种方式)
window.scrollViews()[0].button()[1].tap()
某些有name属性的element不可见,故不可tap,无name属性的element只能使用index索引,如上的imagebutton,虽其image有
name属性但不可见,故只能选取button进行tap操作
7.navigationBar关键字判断(不同布局存在差异,以下仅为一种方式)
if(nvgBar.staticTexts()["关键字"].isVisible()) {
UIALogger.logMessage("关键字存在");
} else {
UIALogger.logMessage("关键字不存在");
}
注:有时isVisible()不可用,可换用isValid()尝试,虽然有些元素在界面上确实not visible,但是脚本调试可看出isVisible()返回值是true,此种情况可能就是图层覆盖了,可多尝试几种判断方法。
8.tabBar控件选取(不同布局存在差异,以下仅为一种方式)
tabBar.buttons()["关键字"];
9.判断tarBar当前所选控件
var selectedBtn = tabBar.selectedButtons()["关键字"].value();
if (selectedBtn == "关键字") { }
注:有时直接使用上述已定义的nvgBar.***和tabBar.***会出错,换用app.navigationBar().***和app.tabBar().***则正常,尚不明所以……可能还是跟应用不规范有关系。
10.截屏
target.captureScreenWithName("screenshot1.png");
11.旋转
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_LANDSCAPELEFT);
UIALogger.logMessage("Current orientation is " + app.interfaceOrientation());
target.setDeviceOrientation(UIA_DEVICE_ORIENTATION_PORTRAIT);
UIALogger.logMessage("Current orientation is " + app.interfaceOrientation());
12.后台运行再进入(模拟home键)
target.deactivateAppForDuration(int second);
13.处理提示框
忽略所有提示框:
UIATarget.onAlert = function onAlert(alert) {
var title = alert.name();
UIALogger.logWarning("Alertwithtitle ’" + title + "’ encountered!");
return false; // use default handler
}
处理特定提示框,忽略其他提示框:
UIATarget.onAlert = function onAlert(alert) {
var title = alert.name();
UIALogger.logWarning("Alertwithtitle ’" + title + "’ encountered!");
if (title == "Add Something") {
return true; // bypass default handler
}
return false; // use default handler
}
最后,总结Automation图形化界面的编辑快捷键:
End:Ctrl+E
Home:Ctrl+A
Delete:Ctrl+D
Backspace:Ctrl+H
Copy:Win+C
Paste:Win+V
Cut:Win+X
左移1:Ctrl+B
下移1:Ctrl+N
上移1:Ctrl+P
右移1:Ctrl+F
删除当前行(光标后面数据):Ctrl+K
PgDn:Ctrl+V
Ctrl+Y:恢复粘贴Ctrl+K最后一次删除的数据