標準充電方式
也就是說,如果電池在電量 40% 的狀態卸下,並在 25 度常溫保存一年後,電量還有 38.4 %
1. 快速调整 Dock 栏大小
7. Spotlight 快捷键
很多人用 Mac 时间长了之后都会养成从 Spotlight 启动应用程序的习惯,其实如果你用快捷键 control+空格键来启动 Spotlight 的话效率会更高,并且将鼠标指针移动到 Spotlight 搜索项的文件上,还可以预览内容。
8. 调整鼠标指针大小
进入「系统偏好设置」——「万能辅助」——「鼠标与触摸板」中,就可以调整鼠标指针大小了。
9. 快速截屏
按 command+shift+3 截取全屏图像,按command+shift+4截取指定大小图像或者窗口图像。
10. 音量微调
要使用快捷键或组合键,您可以同时按修饰键和字符键。例如,同时按下 Command 键(标有 符号的按键)和“c”键会将当前选中的任何内容(文本、图形等等)拷贝至夹纸板。这也称作 Command-C 组合键(或快捷键)。
许多组合键中都包含修饰键。修饰键将改变 Mac OS X 对其他按键或鼠标点按动作的解释方式。修饰键包括 Command、Control、Option、Shift、Caps Lock 和 fn 键(如果您的键盘有 fn 键)。
以下是出现在 Mac OS X 菜单中的修饰键符号:
(Command 键) - 在某些 Apple 键盘上,此键也可能带有 Apple 标志()
(Control 键)
(Option 键)-“Alt”可能也出现在此键上
(Shift 键)
(Caps Lock 键)- 切换 Caps Lock 开或关
fn(功能键)
启动快捷键
按下按键或组合键,直到所需的功能出现(例如,在启动过程中按住 Option 直到出现“启动管理程序”,或按住 Shift 直到出现“安全启动”)。提示:如果启动功能未起作用,而您使用的是第三方键盘,请连接 Apple 键盘,然后再试一次。
按键或组合键 功能
Option 显示所有可引导宗卷(启动管理程序)
Shift 执行安全启动(以安全模式启动)
C 从可引导磁盘启动(DVD、CD)
T 以 FireWire 目标磁盘模式启动
N 从 NetBoot 服务器启动
X 强制 Mac OS X 启动(如果存在非 Mac OS X 启动宗卷)
Command-V 以详细模式启动
Command-S 以单用户模式启动
Finder 快捷键
组合键 功能
Command-A 选中最前面的 Finder 窗口中的所有项(如果未打开任何窗口则选中桌面内容)
Option-Command-A 取消选择所有项
Shift-Command-A 打开“应用程序”文件夹
Command-C 拷贝所选项/文本至夹纸板
Shift-Command-C 打开“电脑”窗口
Command-D 复制所选项
Shift-Command-D 打开桌面文件夹
Command-E 推出
Command-F 查找任何匹配 Spotlight 属性的内容
Shift-Command-F 查找 Spotlight 文件名匹配项
Option-Command-F 导航到已打开的 Spotlight 窗口中的搜索栏
Shift-Command-G 前往文件夹
Shift-Command-H 打开当前所登录用户帐户的个人文件夹
Command-I 显示简介
Option-Command-I 显示检查器
Control-Command-I 获得摘要信息
Shift-Command-I 打开 iDisk
Command-J 调出“显示”选项
Command-K 连接服务器
Shift-Command-K 打开“网络”窗口
Command-L 为所选项制作替身
Command-M 最小化窗口
Option-Command-M 最小化所有窗口
Command-N 新建 Finder 窗口
Shift-Command-N 新建文件夹
Option-Command-N 新建智能文件夹
Command-O 打开所选项
Shift-Command-Q 注销
Option-Shift-Command-Q 立即注销
Command-R 显示(替身的)原身
Command-T 添加到工具条
Shift-Command-T 添加到个人收藏
Option-Command-T 在 Finder 窗口中隐藏工具栏/显示工具栏
Shift-Command-U 打开“实用工具”文件夹
Command-V 粘贴
Command-W 关闭窗口
Option-Command-W 关闭所有窗口
Command-X 剪切
Option-Command-Y 幻灯片显示(Mac OS X 10.5 或更高版本)
Command-Z 还原/重做
Command-1 以图标显示
Command-2 列表方式显示
Command-3 以分栏方式显示
Command-4 以 Cover Flow 方式显示(Mac OS X 10.5 或更高版本)
Command-,(Command 加逗号键) 打开 Finder 偏好设置
Command-`(重音符键 - 美式英语键盘布局中 Tab 键的上方) 循环显示打开的 Finder 窗口
Command-Shift-? 打开 Mac 帮助
Option-Shift-Command-Esc(按住三秒钟)- 仅 Mac OS X v10.5、v10.6 或更高版本 强制退出最前面的应用程序
Command-[ 后退
Command-] 前进
Command-上箭头 打开所含文件夹
Control-Command-上箭头 在新窗口中打开所含文件夹
Command-下箭头 打开高亮显示的项
Command-Tab 切换应用程序 - 向前循环
Shift-Command-Tab 切换应用程序 - 向后循环
Command-Delete 移到废纸篓
Shift-Command-Delete 清倒废纸篓
Option-Shift-Command-Delete 清倒废纸篓(不显示确认对话框)
空格键(或 Command-Y) 快速查看(Mac OS X 10.5 或更高版本)
拖移时按 Command 键 将拖移的项移到其他宗卷/位置(按住按键时指针图标发生变化 - 请参阅此文章)
拖移时按 Option 键 拷贝拖移的项(按住按键时指针图标发生变化 - 请参阅此文章)
拖移时按 Option-Command 组合键 为拖移的项制作替身(按住按键时指针图标发生变化 - 请参阅此文章)
应用程序和其他 Mac OS X 键盘命令
注:有些应用程序可能不支持以下所有应用程序组合键。
组合键 功能
Command-空格键 显示或隐藏 Spotlight 搜索栏(如果安装了多语种,则可能循环显示启用的语系)
Control-A 移到行/段落的开头
Control-B 向后移动一个字符
Control-D 删除光标前的字符
Control-E 移到行/段落的结尾
Control-F 向前移动一个字符
Control-H 删除光标后的字符
Control-K 删除从光标前的字符到行/段落结尾的所有内容
Control-L 将光标/所选内容置于可见区域中央
Control-N 下移一行
Control-O 在光标后插入一行
Control-P 上移一行
Control-T 移调光标前后的字符
Control-V 下移一个页面
Option-Command-空格键 显示 Spotlight 搜索结果窗口(如果安装了多语种,则可能循环显示某一语系下的键盘布局和输入法)
Command-Tab 在打开的应用程序列表中,向下移动到下一个最近使用的应用程序
Shift-Command-Tab 在打开的应用程序列表中向上移动(按最近使用时间排序)
Shift-Tab 按反方向浏览各控件
Control-Tab 聚焦对话框中的下一组控件或聚焦下一个表格(当 Tab 移到下一个单元格时)
Shift-Control-Tab 聚焦上一组控件
Command-esc 打开 Front Row(如果已安装)
Option-推出键 从备选光盘驱动器中推出(如果已安装)
Control-推出键 显示关机对话框
Option-Command-推出键 使电脑进入睡眠模式
Control-Command-推出键 退出所有应用程序(会让您先存储对已打开文稿所作的更改),然后重新启动电脑
Control Option-Command-推出键 退出所有应用程序(会让您先存储对已打开文稿所作的更改),然后关闭电脑
fn-Delete 向前删除(适用于便携式 Mac 的内建键盘)
Control-F1 切换全键盘控制开或关
Control-F2 聚焦菜单栏
Control-F3 聚焦 Dock
Control-F4 聚焦活跃窗口或下一个窗口
Shift-Control-F4 聚焦上一个活跃窗口
Control-F5 聚焦工具栏
Control-F6 聚焦第一个(或下一个)面板
Shift-Control-F6 聚焦上一个面板
Control-F7 临时覆盖窗口和对话框中的当前键盘控制模式
F9 拼贴或取消拼贴所有打开的窗口
F10 拼贴或取消拼贴当前活跃应用程序中所有打开的窗口
F11 隐藏或显示所有打开的窗口
F12 隐藏或显示 Dashboard
Command-` 激活最前面的应用程序中下一个打开的窗口
Shift-Command-` 激活最前面的应用程序中上一个打开的窗口
Option-Command-` 聚焦窗口抽屉
Command- -(减号) 缩小所选项
Command-{ 使所选内容左对齐
Command-} 使所选内容右对齐
Command-| 使所选内容居中对齐
Command-: 显示“拼写”窗口
Command-; 查找文稿中拼写错误的词
Command-, 打开最前面的应用程序的偏好设置窗口(前提是应用程序支持此快捷键)
Option-Control-Command-, 降低屏幕对比度
Option-Control-Command-. 增强屏幕对比度
Command-? 在帮助显示程序中打开应用程序的帮助
Option-Command-/ 打开或关闭字体平滑
Shift-Command-= 放大所选项
Shift-Command-3 将屏幕捕捉到文件
Shift-Control-Command-3 将屏幕捕捉到夹纸板
Shift-Command-4 将所选内容捕捉到文件
Shift-Control-Command-4 将所选内容捕捉到夹纸板
Command-A 高亮显示文稿或窗口中的所有项,或高亮显示文本栏中的所有字符
Command-B 以粗体显示所选文本或切换文本粗体显示开/关
Command-C 将所选数据拷贝到夹纸板
Shift-Command-C 显示“颜色”窗口
Option-Command-C 拷贝所选文本的样式
Control-Command-C 拷贝所选项的格式设置并存储到夹纸板
Option-Command-D 显示或隐藏 Dock
Command-Control D 在字典应用程序中显示所选词的定义
Command-E 使用所选内容进行查找
Command-F 打开“查找”窗口
Option-Command-F 移到搜索栏控件
Command-G 查找所选内容出现的下一个位置
Shift-Command-G 查找所选内容出现的上一个位置
Command-H 隐藏当前正在运行的应用程序窗口
Option-Command-H 隐藏所有其他正在运行的应用程序窗口
Command-I 以斜体显示所选文本或切换文本斜体显示开/关
Option-Command-I 显示检查器窗口
Command-J 滚动到所选部分
Command-M 将活跃窗口最小化至 Dock
Option-Command-M 将活跃应用程序的所有窗口最小化至 Dock
Command-N 在最前面的应用程序中创建新文稿
Command-O 显示对话框,用于选择要在最前面的应用程序中打开的文稿
Command-P 显示“打印”对话框
Shift-Command-P 显示用于指定打印参数(页面设置)的对话框
Command-Q 退出最前面的应用程序
Command-S 存储活跃文稿
Shift-Command-S 显示“存储为”对话框
Command-T 显示“字体”窗口
Option-Command-T 显示或隐藏工具栏
Command-U 对所选文本加下划线或打开/关闭加下划线功能
Command-V 在插入点位置粘贴夹纸板内容
Option-Command-V 将某对象的样式应用于所选对象(粘贴样式)
Option-Shift-Command-V 将周围文本的样式应用于所插入对象(粘贴并匹配样式)
Control-Command-V 将格式设置应用于所选对象(粘贴标尺命令)
Command-W 关闭最前面的窗口
Shift-Command-W 关闭文件及其关联窗口
Option-Command-W 不退出应用程序直接关闭其所有窗口
Command-X 移去所选内容并存储到夹纸板
Command-Z 还原上一命令(有些应用程序允许多次还原)
Shift-Command-Z 重做上一命令(有些应用程序允许多次重做)
Control-右箭头 聚焦视图(如表格)内的另一个值或单元格
Control-左箭头 聚焦视图(如表格)内的另一个值或单元格
Control-下箭头 聚焦视图(如表格)内的另一个值或单元格
Control-上箭头 聚焦视图(如表格)内的另一个值或单元格
Command-右箭头 将文本插入点移至当前行的行尾
Command-左箭头 将文本插入点移至当前行的行首
Command-下箭头 将文本插入点移至文稿的结尾
Command-上箭头 将文本插入点移至文稿的开头
Shift-Command-右箭头
选中插入点与当前行行尾之间的文本 (*)
Shift-Command-左箭头 选中插入点与当前行行首之间的文本 (*)
Shift-右箭头 将文本选择范围向右扩展一个字符 (*)
Shift-左箭头 将文本选择范围向左扩展一个字符 (*)
Shift-Command-上箭头 选中插入点与文稿开头之间的文本 (*)
Shift-Command-下箭头 选中插入点与文稿结尾之间的文本 (*)
Shift-上箭头 将文本选择范围扩展到上一行相同水平位置的最近字符边缘 (*)
Shift-下箭头 将文本选择范围扩展到下一行相同水平位置的最近字符边缘 (*)
Shift-Option-右箭头 将文本选择范围扩展到当前词的词尾,再按一次则扩展到后一词的词尾 (*)
Shift-Option-左箭头 将文本选择范围扩展到当前词的词首,再按一次则扩展到后一词的词首 (*)
Shift-Option-下箭头 将文本选择范围扩展到当前段落的段尾,再按一次则扩展到下一段落的结尾 (*)
Shift-Option-上箭头 将文本选择范围扩展到当前段落的段首,再按一次则扩展到下一段落的段首 (*)
Control-空格键 在当前输入源和上一输入源之间切换
Option-Control-空格键 在所有启用的输入源之间切换
Option-Command-esc 强制退出
(*) 注:如果未选择任何文本,则从插入点位置开始扩展。如果通过拖移选择文本,则从所选内容的边缘开始扩展。反向选择所选内容会取消选择相应部分。
万能辅助 - VoiceOver 键盘命令
有关 Mac OS X v10.6 中 VoiceOver 组合键差异的信息,请参阅此文章。
组合键 功能
Command-F5 或
fn Command-F5 打开或关闭 VoiceOver
Control Option-F8 或
fn Control Option-F8 打开 VoiceOver 实用工具
Control Option-F7 或
fn Control Option-F7 显示 VoiceOver 菜单
Control Option-;
或 fn Control Option-; 启用/停用 VoiceOver 控制选项锁定
Option-Command-8 或
fn Command-F11 开启缩放功能
Option-Command-+ 放大
Option-Command- -(减号) 缩小
Option-Control-Command-8 反转/复原屏幕颜色
Control Option-Command-, 降低对比度
Control Option-Command-. 增强对比度
注:您可能需要在“键盘”偏好设置中启用“将 F1、F2 等键用作标准功能键”,才能使 VoiceOver 菜单和实用工具正常工作。
万能辅助 - 鼠标键
在“万能辅助”偏好设置中打开鼠标键后,您便可以使用键盘或数字小键盘上的键移动鼠标指针。如果电脑没有数字小键盘,请使用 Fn(功能)键。
组合键 功能
8 上移
2 下移
4 左移
6 右移
1 沿对角线向左下角移
3 沿对角线向右下角移
7 沿对角线向左上角移
9 沿对角线向右上角移
5 按鼠标按钮
0 按住鼠标按钮
.(数字小键盘上的句点) 释放按住的鼠标按钮
另请参阅:鼠标快捷键。
其他信息
高级:本文所指为默认的修饰键分配。可在系统偏好设置的“键盘与鼠标”偏好设置中更改修饰键分配。例如,您可以将 Command 键改为用作 Option 键,反之亦然。您也可以恢复默认修饰键设置。
NSClassFromString是一个很有用的东西,尤其在进行iPhone toolchain的开发上。
正常来说,
id myObj = [[NSClassFromString(@"MySpecialClass") alloc] init];
和
id myObj = [[MySpecialClass alloc] init];
是一样的。但是,如果你的程序中并不存在MySpecialClass这个类,下面的写法会出错,而上面的写法只是返回一个空对象而已。
因此,在某些情况下,可以使用NSClassFromString来进行你不确定的类的初始化。
比如在iPhone中,NSTask可能就会出现这种情况,所以在你需要使用NSTask时,最好使用:
[[NSClassFromString(@"NSTask") .....]]
而不要直接使用[NSTask ...]这种写法。
NSClassFromString的好处是:
1 弱化连接,因此并不会把没有的Framework也link到程序中。
2 不需要使用import,因为类是动态加载的,只要存在就可以加载。因此如果你的toolchain中没有某个类的头文件定义,而你确信这个类是可以用的,那么也可以用这种方法。
- (新)360搜索引擎登录入口:http://info.so.360.cn/site_submit.html
- (新)即刻搜索网站提交入口:http://zz.jike.com/submit/genUrlForm
- (新)盘古数据开放平台:http://open.panguso.com/data/resource/url/new
- 百度搜索网站登录口:http://www.baidu.com/search/url_submit.html
- 百度单个网页提交入口:http://zhanzhang.baidu.com/sitesubmit
- Google网站登录口:https://www.google.com/webmasters/tools/submit-url
- Google新闻网站内容:http://www.google.com/support/news_pub/bin/request.py?contact_type=suggest_content&hl=cn
- bing(必应)网页提交登录入口:http://www.bing.com/toolbox/submit-site-url
- (新)简搜搜索引擎登陆口:http://www.jianso.com/add_site.html
- 搜狗网站收录提交入口:http://www.sogou.com/feedback/urlfeedback.php
- SOSO搜搜网站收录提交入口:http://www.soso.com/help/usb/urlsubmit.shtml
- 雅虎中国网站登录口:http://sitemap.cn.yahoo.com/
- 网易有道搜索引擎登录口:http://tellbot.youdao.com/report
- 中搜免费登录服务:http://register.zhongsou.com/NetSearch/frontEnd/free_protocol.htm
- MSN必应网站登录口:http://cn.bing.com/docs/submit.aspx?FORM=WSDD2
- Alexa网站登录入口:http://www.alexa.com/help/webmasters
- TOM搜索网站登录口:http://search.tom.com/tools/weblog/log.php
- 铭万网B2B(必途)网址登陆口:http://search.b2b.cn/pageIncluded/AddPage.php
- 蚁搜搜索网站登录口:http://www.antso.com/apply.asp
- 快搜搜索网站登录口:http://www.kuaisou.com/main/inputweb.asp
- 汕头搜索登录口:http://www.stsou.com/join.asp
- 孙悟空搜索网站登录:http://www.swkong.com/add.php
- 天网网站登陆口:http://home.tianwang.com/denglu.htm
- 速搜全球登陆口:http://www.suso.com.cn/suso/link.asp
- 酷帝网站目录提交入口:http://www.coodir.com/accounts/addsite.asp
- 快搜网站登陆口:http://www.kuaisou.com/main/inputweb.asp
- 搜猫搜索引擎登录入口:http://test.somao123.com/search/url_submit.php
- 泽许搜索网站登录入口:http://www.zxyt.cn/search/zxsc.php
- (新)一淘网开放搜索申请入口:http://open.etao.com/apply_intro.htm?spm=0.0.0.40.9VF4FQ
- 百度博客提交: http://utility.baidu.com/blogsearch/submit.php
- 博客大全提交:http://lusongsong.com/daohang/login.asp
- Google博客提交:http://blogsearch.google.com/ping
- 雅虎中国博客提交:http://search.help.cn.yahoo.com/h4_4.html
- FeedSky提交博客: http://www.feedsky.com
- 搜狗(SoGou)博客提交:http://www.sogou.com/feedback/blogfeedback.php
- 有道(YoDao)博客提交:http://tellbot.yodao.com/
- 必应 Bing博客提交:http://www.bing.com/toolbox/submit-site-url
- 搜搜博客提交:http://www.soso.com/help/usb/urlsubmit.shtml
- Dmoz网站登录入口:http://www.dmoz.org/World/Chinese_Simplified
- NetSearch登陆口:http://intelseek.com/add_url_form.asp
- Freewebsubmission.com 搜索引擎批量提交:http://www.freewebsubmission.com/
- 快速登录20个搜索引擎:http://www.trafficzap.com/searchsubmit.php
- HotBot登录口:http://www.hotbot.com/prefs_filters.asp?prov=Inktomifilter=web
- netscape登录口:http://about.netscape.com/
- AddMe登陆口 :http://www.addme.com/submission/free-submission-start.php
- NetSearch登录口:http://www.netsearch.org/promo/submit.htm
- AddMe登录口:http://www.addme.com/s0new.htm
- Link it All登录口:http://www.that-special-gift.com/ffa/links.html
- Voyager登录口:http://www.voyagersearch.com/cgi-bin/q/search.cgi?NAVG=AddURL
- Gigablast登录口:http://www.gigablast.com/addurl
- Aeiwei登录口:http://www.aeiwi.com/submit.html
- Infotiger登录口:http://www.infotiger.com/addurl.html
- Nationaldirectory登录口:http://www.nationaldirectory.com/addurl/
- WhatUseek登录口:http://www.whatuseek.com/addurl-secondary.shtml
- Exactseek登录口:http://www.exactseek.com/add.html
- Walhello登录口:http://www.walhello.com/addlinkgl.html
- Scrubtheweb登录口:http://www.scrubtheweb.com/addurl.html
- hao123网址收录:http://submit.hao123.com/static/auditSys/wztj.htm
- 360网址导航收录入口:http://hao.360.cn/url.html
- 谷歌265上网导航网站提交:http://www.265.com/submit.html
- 百度网址导航提交入口:http://site.baidu.com/quality/quality_form.php
- 2345网址导航申请收录入口:http://www.2345.com/help/submitweb.htm
- 搜狗网址导航收录入口:http://123.sogou.com/about/shoulu.html
- 博客大全申请收录入口:http://lusongsong.com/daohang/login.asp
- QQ导航网站收录申请规则:http://support.qq.com/cgi-bin/content_...
- 搜狗网址导航收录申请:http://123.sogou.com/shoulu.html
- 114啦网址收录:http://url.114la.com/
- 金山网址导航收录申请:http://123.duba.net/apply/
- 瑞星网址导航收录申请:http://hao.rising.cn/catalog/slsq.html
- 好看123网址导航收录申请:http://www.haokan123.com/urlsubmit/url_submit.html
- 466傲游网址导航申请收录网站:http://bbs.maxthon.cn/viewthread.php?tid=584498&extra=
- 1616网址导航收录:http://www.1616.net/jd/misc/coop.htm
- 淘网址(tao123)收录申请:http://krq.tao123.com/collectsite/
- 0460网站之家收录:http://www.0460.com/member/login.aspx
- 赶驴啊网站收录提交入口:http://www.ganlva.com/url-submit/
- hao123网站收录规则:http://www.hao123.cn/hezuo.htm
- 114网址导航收录申请:http://www.114.com.cn/index.php?view=websubmit
- 726网址收录口:http://www.726.com/url-submit/
- 1166网址收录口:http://www.1166.com/tool/add.html
- 中商网址导航链接提交:http://www.cb114.cn/apps/about.html
- 7999网址收录口:http://7999.com/misc/coop.htm
- 369网址大全新站提交:http://wvw.369.com/us/url.htm
- 568网址导航网址提交:http://www.568.cc/abc/website-add.html
- 找军事网址提交:http://www.zhaojunshi.com/url-submit/
- Google网站管理员工具:http://www.google.com/webmasters/
- 微软Bing管理员工具地址:http://www.bing.com/toolbox/webmaster/
- 百度站长平台:http://zhanzhang.baidu.com/
- 即刻搜索站长中心:http://zz.jike.com/
- 360搜索站长平台:http://zhanzhang.so.com/
一:确认网络环境3G/WIFI 二:使用NSConnection下载数据 三:使用NSXMLParser解析xml文件
一:确认网络环境3G/WIFI
1. 添加源文件和framework
开发Web等网络应用程序的时候,需要确认网络环境,连接情况等信息。如果没有处理它们,是不会通过Apple的审(我们的)查的。
Apple 的 例程 Reachability 中介绍了取得/检测网络状态的方法。要在应用程序程序中使用Reachability,首先要完成如下两部:
1.1. 添加源文件:
在你的程序中使用 Reachability 只须将该例程中的 Reachability.h 和 Reachability.m 拷贝到你的工程中。如下图:
1.2.添加framework:
将SystemConfiguration.framework 添加进工程。如下图:
2. 网络状态
Reachability.h中定义了三种网络状态:
typedef enum {
NotReachable = 0, //无连接
ReachableViaWiFi, //使用3G/GPRS网络
ReachableViaWWAN //使用WiFi网络
} NetworkStatus;
因此可以这样检查网络状态:
Reachability *r = [Reachability reachabilityWithHostName:@“www.apple.com”];
switch ([r currentReachabilityStatus]) {
case NotReachable:
// 没有网络连接
break;
case ReachableViaWWAN:
// 使用3G网络
break;
case ReachableViaWiFi:
// 使用WiFi网络
break;
}
3.检查当前网络环境
程序启动时,如果想检测可用的网络环境,可以像这样
// 是否wifi
+ (BOOL) IsEnableWIFI {
return ([[Reachability reachabilityForLocalWiFi] currentReachabilityStatus] != NotReachable);
}
// 是否3G
+ (BOOL) IsEnable3G {
return ([[Reachability reachabilityForInternetConnection] currentReachabilityStatus] != NotReachable);
}
例子:
- (void)viewWillAppear:(BOOL)animated {
if (([Reachability reachabilityForInternetConnection].currentReachabilityStatus == NotReachable) &&
([Reachability reachabilityForLocalWiFi].currentReachabilityStatus == NotReachable)) {
self.navigationItem.hidesBackButton = YES;
[self.navigationItem setLeftBarButtonItem:nil animated:NO];
}
}
4. 链接状态的实时通知
网络连接状态的实时检查,通知在网络应用中也是十分必要的。接续状态发生变化时,需要及时地通知用户:
Reachability 1.5版本
// My.AppDelegate.h
#import "Reachability.h"
@interface MyAppDelegate : NSObject <UIApplicationDelegate> {
NetworkStatus remoteHostStatus;
}
@property NetworkStatus remoteHostStatus;
@end
// My.AppDelegate.m
#import "MyAppDelegate.h"
@implementation MyAppDelegate
@synthesize remoteHostStatus;
// 更新网络状态
- (void)updateStatus {
self.remoteHostStatus = [[Reachability sharedReachability] remoteHostStatus];
}
// 通知网络状态
- (void)reachabilityChanged:(NSNotification *)note {
[self updateStatus];
if (self.remoteHostStatus == NotReachable) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:NSLocalizedString(@"AppName", nil)
message:NSLocalizedString (@"NotReachable", nil)
delegate:nil cancelButtonTitle:@"OK" otherButtonTitles: nil];
[alert show];
[alert release];
}
}
// 程序启动器,启动网络监视
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// 设置网络检测的站点
[[Reachability sharedReachability] setHostName:@"www.apple.com"];
[[Reachability sharedReachability] setNetworkStatusNotificationsEnabled:YES];
// 设置网络状态变化时的通知函数
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(reachabilityChanged:)
name:@"kNetworkReachabilityChangedNotification" object:nil];
[self updateStatus];
}
- (void)dealloc {
// 删除通知对象
[[NSNotificationCenter defaultCenter] removeObserver:self];
[window release];
[super dealloc];
}
Reachability 2.0版本
// MyAppDelegate.h
@class Reachability;
@interface MyAppDelegate : NSObject <UIApplicationDelegate> {
Reachability *hostReach;
}
@end
// MyAppDelegate.m
- (void)reachabilityChanged:(NSNotification *)note {
Reachability* curReach = [note object];
NSParameterAssert([curReach isKindOfClass: [Reachability class]]);
NetworkStatus status = [curReach currentReachabilityStatus];
if (status == NotReachable) {
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"AppName""
message:@"NotReachable"
delegate:nil
cancelButtonTitle:@"YES" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
- (void)applicationDidFinishLaunching:(UIApplication *)application {
// ...
// 监测网络情况
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reachabilityChanged:)
name: kReachabilityChangedNotification
object: nil];
hostReach = [[Reachability reachabilityWithHostName:@"www.google.com"] retain];
hostReach startNotifer];
// ...
}
二:使用NSConnection下载数据
1.创建NSConnection对象,设置委托对象
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:[self urlString]]];
[NSURLConnection connectionWithRequest:request delegate:self];
2. NSURLConnection delegate委托方法
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response;
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data;
- (void)connectionDidFinishLoading:(NSURLConnection *)connection;
3. 实现委托方法
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response {
[self.receivedData setLength:0]; //通常在这里先清空接受数据的缓存
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data {
[self.receivedData appendData:data]; //可能多次收到数据,把新的数据添加在现有数据最后
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error {
// 错误处理
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection {
// disconnect
[UIApplication sharedApplication].networkActivityIndicatorVisible = NO;
NSString *returnString = [[NSString alloc] initWithData:self.receivedData encoding:NSUTF8StringEncoding];
NSLog(returnString);
[self urlLoaded:[self urlString] data:self.receivedData];
firstTimeDownloaded = YES;
}
三:使用NSXMLParser解析xml文件
1. 设置委托对象,开始解析
NSXMLParser *parser = [[NSXMLParser alloc] initWithData:data]; //或者也可以使用initWithContentsOfURL直接下载文件,但是有一个原因不这么做:
// It's also possible to have NSXMLParser download the data, by passing it a URL, but this is not desirable
// because it gives less control over the network, particularly in responding to connection errors.
[parser setDelegate:self];
[parser parse];
2. 常用的委托方法
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
attributes:(NSDictionary *)attributeDict;
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName
namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName;
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string;
- (void)parser:(NSXMLParser *)parser parseErrorOccurred:(NSError *)parseError;
static NSString *feedURLString = @"http://www.yifeiyang.net/test/test.xml";
3. 应用举例
- (void)parseXMLFileAtURL:(NSURL *)URL parseError:(NSError **)error
{
NSXMLParser *parser = [[NSXMLParser alloc] initWithContentsOfURL:URL];
[parser setDelegate:self];
[parser setShouldProcessNamespaces:NO];
[parser setShouldReportNamespacePrefixes:NO];
[parser setShouldResolveExternalEntities:NO];
[parser parse];
NSError *parseError = [parser parserError];
if (parseError && error) {
*error = parseError;
}
[parser release];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString*)qName attributes:(NSDictionary *)attributeDict{
// 元素开始句柄
if (qName) {
elementName = qName;
}
if ([elementName isEqualToString:@"user"]) {
// 输出属性值
NSLog(@"Name is %@ , Age is %@", [attributeDict objectForKey:@"name"], [attributeDict objectForKey:@"age"]);
}
}
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI
qualifiedName:(NSString *)qName
{
// 元素终了句柄
if (qName) {
elementName = qName;
}
}
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string
{
// 取得元素的text
}
NSError *parseError = nil;
[self parseXMLFileAtURL:[NSURL URLWithString:feedURLString] parseError:&parseError];
使用NSOperation和NSOperationQueue启动多线程
当打开一个应用程序时,iphone会产生一个包含main方法的线程,所用程序中的界面都是运行在这个线程之中的(table views, tab bars, alerts…),有时候我们会用数据填充这些view,现在问 题是如何有效的载入数据,并且用户还能自如的操作程序。方法是启动新的线程,专门用于数据的下载,而主线程不会因为下载数据被阻塞。
不管使用任何编程语言,在实现多线程时都是一件很麻烦的事情。更糟糕的是,一旦出错,这种错误通常相当糟糕。然而,幸运的是apple从os x10.5在这方面做了很多的改进,NSThread的引入,使得开发多线程应用程序容易多了。除此之外,它们还引入了两个全新的类,NSOperation和NSOperationQueue。
接下来我们通过一个实例来剖析如何使用这两个类实现多线程。这里指示展示这两个类的基本用法,当然这不是使用他们的唯一办法。
如果你熟悉java或者它的别的变种语言的话 ,你会发现NSOperation对象很像java.lang.Runnable接口,就像java.lang.Runnable接口那样,NSOperation类也被设计为可扩展的,而且只有一个需要重写的方法。它就是-(void)main。使用NSOperation的最简单的方式就是把一个NSOperation对象加入到NSOperationQueue队列中,一旦这个对象被加入到队列,队列就开始处理这个对象,直到这个对象的所有操作完成。然后它被队列释放。
下面的例子中,使用一个获取网页,并对其解析程NSXMLDocument,最后将解析得到的NSXMLDocument返回给主线程。
PageLoadOperation.h@interface PageLoadOperation : NSOperation {
NSURL *targetURL;}
@property(retain) NSURL *targetURL;
- (id)initWithURL:(NSURL*)url;@end
PageLoadOperation.m
#import "PageLoadOperation.h"
if (![super init]) return nil;
[self setTargetURL:url];
return self;}- (void)dealloc {
[targetURL release], targetURL = nil;
[super dealloc];
}
- (void)main
{
NSString *webpageString = [[[NSString alloc]
initWithContentsOfURL:[self targetURL]] autorelease];
NSError *error = nil;
NSXMLDocument *document = [[NSXMLDocument alloc]
initWithXMLString:webpageString
options:NSXMLDocumentTidyHTML error:&error];
if (!document) {
NSLog(@"%s Error loading document (%@): %@",
_cmd, [[self targetURL] absoluteString], error);
return;
}
[[AppDelegate shared]
performSelectorOnMainThread:@selector(pageLoaded:)
withObject:document waitUntilDone:YES];
[document release];
}
@end
正如我们所看到的那样,这个类相当的简单,在它的init方法中接受一个url并保存起来,当main函数被调用的时候,它使用这个保存的url创建一个字符串,并将这个字符串传递给NSXMLDocumentinit方法。如果加载的xml数据没有出错,数据会被传递给AppDelegate,它处于主线程中。到此,这个线程的任务就完成了。在主线程中注销操作队列的时候,会将这个NSOperation对象释放。
AppDelegate.h
@interface AppDelegate : NSObject {
NSOperationQueue *queue;
}
static AppDelegate *shared;
static NSArray *urlArray;
- (id)init
{
if (shared)
{
[self autorelease];
return shared;
}
if (![super init]) return nil; NSMutableArray *array = [[NSMutableArray alloc] init];[array addObject:@"http://www.google.com"];[array addObject:@"http://www.apple.com"];[array addObject:@"http://www.yahoo.com"];[array addObject:@"http://www.zarrastudios.com"];[array addObject:@"http://www.macosxhints.com"];urlArray = array; queue = [[NSOperationQueue alloc] init];shared = self;return self;
}
(void)applicationDidFinishLaunching:
(NSNotification *)aNotification
{
for (NSString *urlString in urlArray)
{
NSURL *url =
[NSURL URLWithString:urlString]; PageLoadOperation *plo =
[[PageLoadOperation alloc] initWithURL:url];
[queue addOperation:plo];
[plo release];
}
}
- (void)dealloc
{
[queue release], queue = nil;
[super dealloc];
}
+ (id)shared;
{
if (!shared) {
[[AppDelegate alloc] init];
}
return shared;
}
- (void)pageLoaded:(NSXMLDocument*)document;
{
NSLog(@"%s Do something with the XMLDocument: %@",
_cmd, document);
}
@end
NSOperationQueue的并行控制(NSOperationQueue Concurrency)
Reachability 问题
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(reachabilityChanged:)
name: kReachabilityChangedNotification
object: nil];
//只要有hostReach,他就会调用reachabilityChanged
hostReach = [[Reachability reachabilityWithHostName: @"www.google.com"] retain];
[hostReach startNotifier];
//3G网络?
internetReach = [[Reachability reachabilityForInternetConnection] retain];
[internetReach startNotifier];
//wifi网络
wifiReach = [[Reachability reachabilityForLocalWiFi] retain];
[wifiReach startNotifier];
[/appinfo]
请问,红色的3个地方,具体区别是什么啊?
使用hostReach的话,程序启动时就会调用hostReach,而wifiReach,internetReach不会
那这三个函数,到底各自的用途是什么?
在检测 net 的 实时 的连接状态的时候要使用第一个 reachabilityWithHostName method, 它回去连接 host 因为有连接的动作, 而且如果链接过程中网路有 status 的变化,可以通过 notification 反映出来。
eachabilityForInternetConnection eachabilityForLocalWiFi 这两个更象是一个 getter 方法, 用来检测程序启动的时候 当前 device 可以用的网络是哪个,
[[Reachability reachabilityForLocalWiFi] currentReachabilityStatus] != NotReachable 如果是 YES, 那就是Wifi 喽。 这个只是查看你 device 当前可用的网络环境是那个, 更象是一个 device 上 global property 的查询, 不会有实际的连接产生, 所以谈不上 status 的变化。
这是我个人的理解,因为apple 的 doc 中这部分的描述很少, 就只有 Reachability 的head file 的comment 可以看看, 所以是我自己的看法拉。 不过也可以 inspect 一下 三个方法 return 的 Reachability 物件对象的结构,发现一些端倪。 呵呵。
因为我只有wifi可以联网,没有3G什么的,所以,要么是NotReachable,要么是ReachableViaWiFi
应用:dedecms有时由于前台会员中心自制模板原因,使得前后台编辑框宽度不一致,这时就要对不同页面进行不同的宽度设置。这里提供的方法主要是使用不同的调取编辑器函数。
if ( ! function_exists('GetEditorD'))
function SpGetEditorD($fname,$fvalue,$nheight="350",$etype="Basic",$gtype="print",$isfullpage="false",$bbcode=false)
设备及环境:AIR 13"、parallels desktop 7虚拟win7(thin)、中兴A356无线上网卡
设置完毕,试试MAC共享虚拟机网络吧。
注意:虽然本方法可行,但是在opencv2中少了一些library。如果使用缺少的库还需手动添加。使用繁琐。现有更简单的在iOS上运行OpenCV的方法。
链接地址:http://blog.sina.com.cn/s/blog_698415f20100y7ip.html
OpenCV的全称是:Open Source Computer Vision Library。
OpenCV于1999年由Intel建立,现在由Willow Garage提供支持。OpenCV是一个基于BSD许可证授权(开源)发行的跨平台计算机视觉库,可以运行在Linux、Windows和Mac OS操作系统上。它轻量级而且高效——由一系列 C 函数和少量 C++ 类构成,同时提供了Python、Ruby、MATLAB等语言的接口,实现了图像处理和计算机视觉方面的很多通用算法。最新版本是2.4.0。(此段文字摘自百度百科)
OpenCV是Intel公司开发的计算机视觉库,例如,使用这个库,我们可以很容易的检测面部。我纪录了如何在IOS SDK上使用它,包括创建脚本和演示程序。上边是演示程序的截图。
支持最新的OpenCV和IOS SDK
更新项目, 支持OpenCV 2.2.0, iOS SDK 4.3, Xcode 4 (更新于 04/17/2011.)
入门
所有的代码和资料都是开源的,你可以从我的github资源库获得。它包括预编译OpenCV的库和头文件,使您可以轻松地启动测试它。如果你已经有了Git命令,仅仅从我的github克隆资源就可以。如果没有,只好从github下载zip或tar包并释放它。
% git git://github.com/niw/iphone_opencv_test.git
获取到源代码,用Xcode打开OpenCVTest.xcodeproj,然后建立它。你会得到一个演示程序在iPhone虚拟机或iPhone设备上。
从源代码建立OpenCV的资源库
-
使用CMake命令建立OpenCV. 使用 Homebrew 或 MacPorts你可以轻松的安装它。
# 使用Homebrew % brew install cmake # 使用MacPorts % sudo port install cmake
如果你已经安装了最新的java更新,你可能会被要求安装javadeveloper_10.6_10m3261.dmg。这很奇怪,但cmake要求从最新的Java更新中删除jni.h,你可以从这里下载 Mac OS X 10.6,这可能需要你订阅苹果开发者(开发者权限)。是的,苹果现在要贬低在MacOS X 上的Java(更新于 10/30/2010)。
-
从sourceforge获取源代码。我测试了OpenCV-2.2.0.tar.bz2。
-
在演示项目顶级目录提取下载的归档文件。
% tar xjvf OpenCV-2.2.0.tar.bz2
-
应用为iOS SDK的补丁。
% cd OpenCV-2.2.0 % patch -p1 < ../OpenCV-2.2.0.patch
-
接下来的步骤是建立OpenCV的静态库。所有的文件被装到opencv_simulator目录。运行make命令时,你更好的分配j选项和数量根据你CPU的内核数。没有j选项,它需要较长的时间。
% cd .. # 返回到演示程序的project目录 % mkdir build_simulator % cd build_simulator % ../opencv_cmake.sh Simulator ../OpenCV-2.2.0 % make -j 4 % makeinstall
译者测试:
如果你的Mac OS系统版本过高,在运行"opencv_cmake.sh"可能会提示如下信息:
iOS SDK Version 4.3 is not found, please select iOS version you have.
不要紧,这时因为新版本的Mac OS中SDKs的目录结构有所更改,执行以下操作即可解决。
% vim../opencv_cmake.sh
修改:
DEVELOPER_ROOT="/Developer/Platforms/${TARGET_SDK_NAME}.platform/Developer"
为:
DEVELOPER_ROOT="/Applications/Xcode.app/Contents/Developer/Platforms/${TARGET_SDK_NAME}.platform/Developer"
即可。
-
之后的下一个步骤,建立设备的OpenCV静态库的所有文件到build_device目录。
% cd .. # 返回到演示程序的project目录 % mkdir build_device % cd build_device % ../opencv_cmake.sh Device ../OpenCV-2.2.0 % make -j 4 % make install
建立支持脚本
之后的下一个步骤,建立设备的OpenCV静态库的所有文件到build_device目录
图像UIImage和IplImage之间的转换
OpenCV是使用IpImage的结构加工,使用IOS SDK的UIImage对象显示在屏幕上。这意味着我们需要一个介于UIImage和IpImage之间的转换器。值得庆幸的是,我们可以利用iOS SDK APIs做到。
从UIImage创建IpImage是这样的:
// NOTE 戻り値は利用後cvReleaseImage()で解放してください
- (IplImage *)CreateIplImageFromUIImage:(UIImage *)image {
// CGImageをUIImageから取得
CGImageRef imageRef = image.CGImage;
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// 一時的なIplImageを作成
IplImage *iplimage = cvCreateImage(
cvSize(image.size.width,image.size.height), IPL_DEPTH_8U, 4
);
// CGContextを一時的なIplImageから作成
CGContextRef contextRef = CGBitmapContextCreate(
iplimage->imageData, iplimage->width, iplimage->height,
iplimage->depth, iplimage->widthStep,
colorSpace, kCGImageAlphaPremultipliedLast|kCGBitmapByteOrderDefault
);
// CGImageをCGContextに描画
CGContextDrawImage(
contextRef,
CGRectMake(0, 0, image.size.width, image.size.height),
imageRef
);
CGContextRelease(contextRef);
CGColorSpaceRelease(colorSpace);
// 最終的なIplImageを作成
IplImage *ret = cvCreateImage(cvGetSize(iplimage), IPL_DEPTH_8U, 3);
cvCvtColor(iplimage, ret, CV_RGBA2BGR);
cvReleaseImage(&iplimage);
return ret;
}
不要忘记使用cvReleaseImage释放IpImage!
从IpImage创建UIImage是这样的:
// NOTE IplImageは事前にRGBモードにしておいてください。
- (UIImage *)UIImageFromIplImage:(IplImage *)image {
CGColorSpaceRef colorSpace = CGColorSpaceCreateDeviceRGB();
// CGImageのためのバッファを確保
NSData *data =
[NSData dataWithBytes:image->imageData length:image->imageSize];
CGDataProviderRef provider =
CGDataProviderCreateWithCFData((CFDataRef)data);
// IplImageのデータからCGImageを作成
CGImageRef imageRef = CGImageCreate(
image->width, image->height,
image->depth, image->depth * image->nChannels, image->widthStep,
colorSpace, kCGImageAlphaNone|kCGBitmapByteOrderDefault,
provider, NULL, false, kCGRenderingIntentDefault
);
// UIImageをCGImageから取得
UIImage *ret = [UIImage imageWithCGImage:imageRef];
CGImageRelease(imageRef);
CGDataProviderRelease(provider);
CGColorSpaceRelease(colorSpace);
return ret;
}
OK,现在你可以在iPhone上享用OpenCV了。
在自己的项目中使用OpenCV库
-
你可以从我的资源库中下载演示程序,它已经被配置为使用这些库。如果你想在自己的项目中使用OpenCV库,你应该需要增加它的下一个配置。在这个演示程序的Xcode项目中,你可以看到这些设置。
-
从OpenCV lib目录为模拟器或设备添加libopencv_core.a。事实上Xcode并不关心是设备或模拟器中的哪一个,因为它是由选定的库去搜索路径。
-
添加Accelerate.framework被OpenCV库内部使用。
Path:/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS5.1.sdk/System/Library/Frameworks/Accelerate.framework
-
选择你的工程文件(图 1),选中TARGETS下与工程文件同名的target,打开信息面板并选中Build Settings选项卡(图 2)。
(图 1)(图 2) -
- 添加 -lstdc++ 和 -lz 到Other Linker Flags(图 2)。
- 把OpenCV中open_simulator和open_device的路径添加到Header Search Paths(图 3-1,3-2,3-3)。"$(SRCROOT)/opencv_device/include",参照OpenCVTest项目。
- 添加OpenCV的lib目录到Library Search Paths(图 3-1,3-2,3-3)。"$(SRCROOT)/opencv_device/lib",参照OpenCVTest项目。
- 仔细对照你的工程配置是否与演示程序的工程配置相同。如果你的工程配置与演示程序的配置或图3-3相同,那么恭喜你,你的工程环境已经搭建好了。
OpenCV 是一个开源的跨平台计算机视觉库,实现了图像处理和计算机视觉方面的很多通用算法。
最近试着在MacOS和iOS上使用OpenCV,发现网上关于在MacOS和iOS上搭建OpenCV的资料很少。好不容易搜到些资料,却发现由于OpenCV和XCode的版本更新,变得不再有用了。有些问题费了我很多时间,在此总结分享给大家,希望后来人少走些弯路。
可以预见到,随着XCode和OpenCV的版本更新,本文可能不再有效了。所以特此注明,文本介绍的搭建方法仅针对于 XCode4.5.1 和 OpenCV 2.4.2版本。
MacOS系统中使用OpenCV
安装OpenCV
相信大部分Mac用户都安装了brew或port,如果你没有装,那么首先安装一下brew吧。使用如下命令安装brew:
1
|
|
在安装好brew后,只需要一条命令就可以安装OpenCV了:
1
|
|
通常情况下这样做就应该会安装成功,但我在公司和家里面的电脑尝试的时候,brew都会报一些错误,我遇到的都是一些小问题,按照brew的提示信息,解决掉相应的问题即可。
安装成功后,你应该可以在“/usr/local/include”目录下找到名为opencv和opencv2的目录,这里面是OpenCV相关的头文件。你也可以在“/usr/local/lib”目录下找到许多以libopencv_开头的.dylib文件,这些是OpenCV的链接库文件。
在MacOS系统中使用OpenCV
接着我们可以试着在Xcode工程中使用OpenCV。
新建一个Cocoa Application的工程。工程建好后,选中工程的Target,在Build Settings一样,找到“Header Search Paths”这一个选项,将它的值改为“/usr/local/include”。如下所示:
接着切换到Build Phases这个tab,在“Link Binary With Libraries”中,选项+号,然后将弹出的文件选择对话框目录切换到“/usr/local/lib”目录下,选择你需要使用的OpenCV链接库(通常情况下,你至少会需要core、highgui和imgproc库),如下图所示:
这里有一个技巧,因为 /usr 目录在对话框中默认不是可见的,可以按快捷键 command + shift + G,在弹出的“前往文件夹”对话框中输入 /usr/local/lib ,即可跳转到目标文件夹。如下图所示:
下一步是我自己试出来的,你需要在Build Settings中,将“C++ Language Dialect”设置成C++11,将“C++ Standard Library”设置成libstdc++ ,如下图所示。个人感觉是由于XCode默认设置的GNU++11、libc++与OpenCV库有一些兼容性问题,我在更改该设置前老是出现编译错误。如果后续版本解决了这个问题,就不用进行这一步了。
把上面的设置都做好后,就可以在需要的使用OpenCV库的地方,加上opencv的头文件引用即可:
1
|
|
注意,如果你的源文件扩展名是.m的,你还需要改成.mm,这样编译器才知道你将会在该文件混合使用C++语言和Objective-C语言。
OpenCV处理图象需要的格式是cv::Mat类,而MacOS的图象格式默认是NSImage,所以你需要知道如何在cv::Mat与NSImage之前相互转换。如下是一个NSImage的Addition,你肯定会需要它的。该代码来自stackoverflow上的这个贴子。
NSImage+OpenCV.h 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
|
NSImage+OpenCV.mm文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
|
完成以上步骤后,恭喜你,你可以在源代码中自由地调用OpenCV的函数了。
在iOS系统中使用OpenCV
下载或编译opencv2.framework
接下来介绍如何在iOS程序中使用OpenCV。在iOS上使用最新的OpenCV库比较简单,进入opencv的官网,下载build好的名为opencv2.framework即可(下载地址)。
如果你比较喜欢折腾,也可以自行下载opencv的源码,在本地编译opencv2.framework。这里有官方网站的教程,步骤非常简单,不过我照着它的教程尝试了一下失败了。感觉还是XCode编译器与OpenCV代码的兼容性问题,所以就没有继续研究了。
在iOS程序中使用OpenCV
新建一个iOS工程,将opencv2.framework直接拖动到工程中。然后,你需要在Build Settings中,将“C++ Standard Library”设置成libstdc++。
因为opencv中的MIN宏和UIKit的MIN宏有冲突。所以需要在.pch文件中,先定义opencv的头文件,否则会有编译错误。将工程的.pch文件内容修改成如下所示:
1 2 3 4 5 6 7 8 9 10 |
|
把上面的设置都做好后,就可以在需要的使用OpenCV库的地方,加上opencv的头文件引用即可:
1
|
|
还是那句话,如果你的源文件扩展名是.m的,你还需要改成.mm,这样编译器才知道你将会在该文件中混合使用C++语言和Objective-C语言。
同样,iOS程序内部通常用UIImage表示图片,而OpenCV处理图象需要的格式是cv::Mat,你会需要下面这个Addition来在cv::Mat和UIImage格式之间相互转换。该代码来自aptogo的开源代码,他的版权信息在源码头文件中。
UIImage+OpenCV.h 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 |
|
UIImage+OpenCV.mm 文件:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 |
|
总结
上面2个环境搭建好后,你就可以在MacOS上试验各种图象处理算法,然后很方便地移值到iOS上。
一直觉得,图象和声音是移动设备上的特点和优势。因为移动设备没有了可以快速输入的键盘,屏幕也不大,在移动设备上,声音,图象和视频应该是相比文字更方便让人输入的东西。移动端APP应该利用好这些特点,才能设计出更加体贴的功能。
而且,通常情况下做图象处理都比较好玩,记得以前在学校做了一个在QQ游戏大厅自动下中国象棋的程序,其后台使用了网上下载的一个带命令行接口的象棋AI,然后我的代码主要做的事情就是识别象棋棋盘,然后将棋盘数据传给那个象棋AI,接着获得它返回的策略后,模拟鼠标点击来移动棋子。当时不懂什么图象算法,直接把棋子先截取下来保存,然后识别的时候做完全匹配,非常弱的办法,但是效果非常好,做出来也很好玩。嗯,所以文章最后,我想说的是:have fun!