[iOS]如何避免图像解压缩的时间开销

这是一篇译文,(原文"Avoiding Image Decompression Sickness"在此),原文是我看过的非常不错的一篇关于iOS图片显示的一些文章,解决了我的一些疑惑和问题,因此翻译过来分享,为保证一定的通顺性其中一部分内容与原文有些许出入,但我尽量保证了意思的一致性,欢迎指正批评,横线之间为译文,略挫,见谅:


当开始iCatalog.framework的工作时,我发现使用大尺寸图片会引起一些恼人的问题,“大”意味着这个图片有足够大的分辨率(1024×768)来覆盖iPad的整个屏幕,或者覆盖未来Retina Display iPad(如果有的话)的双倍分辨率(2048×1536)屏幕。

想像一个杂志类型的App,一个分页的UIScrollView,每页显示一个UIImageView,一旦某一页进入屏幕区域你就要为这个页创建或者重用一个UIImageView并把它放到scrollView的当前显示区域,即使这个页只有一个像素进入到屏幕区域,你还是要做这些工作。这在模拟器上运行得非常好,但在真机上进行测试,你会发现每次进入下一页时都会有一个明显的延迟。这个延迟来自于将图片从文件解压缩并渲染到屏幕上这一系列的工作。不幸的是UIImage仅在图片将要显示的时候做这个解压工作。

因为添加一个view到当前的view层次结构中必须在主线程上进行,所以图片的解压缩和之后渲染到屏幕上的工作也在主线程进行,这就是这个延迟产生的原因,这个问题也可以在store里的其他有类似这种效果的app中发现。

一般我们使用的图片有两种主要格式,jpeg和png。Apple通常推荐你使用png作为用户界面的图片格式,这些图片会被一个叫pngcrush开源的工具优化(译者注:这个工具就在/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/pngcrush ),这样对于iOS设备就可以在显示时更快地进行解压和渲染。iPad平台上首批出现的杂志应用,比如Wired,就曾用过png作为杂志内容图片的格式,这导致了这个应用的某一版本大小超过了500MB(link)[http://www.cocoanetics.com/2010/05/saturday-morning-breakfast-wired-emag/]

虽然png格式的图片会被事先优化好,但是这并不意味着在所有情况下png都是最佳的图片格式,png对于那些app中自带的图片来说非常好,但是对于要从internet上down下来的图片来说又会怎样呢。png和jpeg这两种格式都有各自的优缺点:

png格式的图片有alpha通道,jpeg则没有。png无损压缩,jpeg允许你选择0-100%的压缩质量。如果需要alpha通道(透明),就只能用png格式。但是如果你不需要一个完美的图片,就可以使用jpeg格式,jpeg格式会忽略那些你看不到的信息,对于大部分的图片可以使用60-70%的压缩质量而不对图片造成明显的影响,对于比如文字那样有"sharp pixels"的图片就可能需要较高的压缩质量,对于照片可以使用较低的压缩质量。

来看一下一个图片的空间消耗:

  1. 磁盘空间或者通过internet传输所消耗的空间
  2. 解压缩空间,通常是长X宽X高X4字节(RGBA)
  3. 当显示在一个view中时,view本身也需要空间来存储layer

对于这里的第一个问题,有一个可能的优化方法:将压缩的文件拷贝到内存中不如映射到内存中,NSData有能力来假设一块磁盘空间是在内存中的,这样当访问这个图片时实际上就是从磁盘访问而不是从内存。据说CGImage知道哪种访问方式是最高效的,UIImage只是将CGImage封装了一下。

对于“将这些像素显示到屏幕上最快要多久?”这个问题,显示一个图片所消耗的时间由以下三个因素决定:

  1. 从磁盘上alloc/init UIImage的时间
  2. 解压缩的时间
  3. 将解压缩后的比特转换成CGContext的时间,通常需要改变尺寸,混合,抗锯齿工作。

要逐一解答各个问题,我们需要一个benchmark来测量。

测试环境和测试内容

继续阅读[iOS]如何避免图像解压缩的时间开销

解决因删除xib(nib)文件所导致的错误

用XCode编写程序,如果你由于各种原因需要删除一个xib文件,在删除文件后就可能遇到一些稀奇古怪的问题,首先说下解决方法

尝试做以下工作:

  • 粗暴地删除真机/模拟器上对应的App (这个一般就能解决问题了)(注意看后文,有更温和的解决方法)
  • 对整个工程Clean一下,至于Clean在哪,建议到Help下面搜索一下
  • XCode 3可能还有个Empty Caches… -> Empty

原因我想大家已经猜到了,编译一个新版本的应用只是把要修改的部分替换成新的,似乎并不会对删除多余的东西,比如你之前建立的xib(nib),这也就导致了虽然你的代码已经不在依靠那个nib运行了,但是原来的nib还是残留在那里,并且会在运行时加载,这就可能造成一些问题.

同样,如果你错误地删除了一个nib而没有"刷新"一下你的应用,这个错误就会被掩盖起来,等你的应用编译或安装到其他机器上时就可能产生各种错误.

了解了原理也就知道了替换第一步的放法:

  • 找到xxx.app,显示包内容,删除你不想要的nib文件

–以上–

在iPhone/iPad/iPod上查看iOS文档

7.26更新:iPad基本不用看了,拿模拟器试了下发现官方文档对iPad支持甚好,而离线版缺少对iPad的支持,无法通过Safari打开

苹果的官方文档甚是强大,对开发的各个方面都进行了及其详尽的介绍,作为开发者当然要时常翻看,本地的文档只能在电脑上看,要想用我们的iDevices查看文档只好连网看在线版的,但由于网速限制不够有效率,官方文档虽然支持转换成PDF,但是转换速度很慢,转换后一堆超链接也失效了.另外我找了好久也没有一个叫"Procket Documentation"或者类似的App,实在有些遗憾.

这里有一个不太完美的解决方案:官方文档虽然都是docset格式的,但其实右键显示包内容一看就是一堆html,css啥的,和在线版的文档一样完全可以用浏览器解决,所以只要把docset里面的Documents文件夹拖到你的iDevices里面就行了,如果你没有越狱就用GoodReader啥的看吧,不过我用iPhone 4测试效果不太理想,文档首页加载奇慢,而且显示不全,那个搜索不知道好不好使,太卡没法测试,iPad 2不知道效果能怎么样,有iPad 2的同学试验下最好在评论中说下效果,别的页面也可以直接浏览,不过效果没有桌面版的Safai那样好,排版似乎有些问题(不是大问题,试下就知道了),但是不影响看.

如果越狱了,可以在Cydia里搜索下lighttpd,安装,最好也安装一下Lighttpd SBSetting Toggle,安装后重启,然后就可以用Safari访问127.0.0.1了.(这里只介绍下安装那个Toogle后的使用方法,Lighttpd SBSetting Toggle的说明中提到webroot地址是/var/www,配置文件是/etc/lighttpd2.cong,用默认的配置文件访问127.0.0.1就可以直接看到/var/www下的目录.只要把之前提到的Document文件夹放这里就行了,接下来怎么做就不用说了吧.) 用自带Safari打开文档,文档首页依旧很卡,但是比GoodReader强多了,而且搜索也勉强可以用(iPhone 4测试,其他不知效果如何),其他页面和GoodReader浏览效果一样,都是排版有点问题,不影响效果.

目前为止也没做太多测试,现在正考虑用其他浏览器看看效果是否能好些(Operamini试了下根本不行),如果有发现就会更新这篇文章,没有就这样了.

其实这个方法也可以用来查看Android文档什么的.

–以上–

PS:搜狗输入法Mac版真TM2(Ver 1.1),中文标点那个选项没有记忆,切个输入法就又回到默认值了,写这篇文章净折腾全角半角的问题了.另外所谓的词库也就那回事,跟Win版没法比.

iCloud 部分功能开始生效

iCloud虽说要到秋季才发布,但其部分功能已经开始生效了.

如果你同意了iTunes的最新条款并通过电脑或者其他设备在iTunes Store下载了新的音乐,App或书籍你的iDevices就将受到如下推送通知:You downloaded an app from your computer. Turn on Automatic Downloads to receive apps on this device without having to sync.

在偏好设置>>Store,就可以看到新的选项,如图所示:

可以让你的iDevices不需要与电脑连接而自动同步(不如说是下载)你通过电脑或者另一台iDevice在iTunes Store购买的音乐,App和书籍.详情可以参考官方的说明

–以上–

在iphone/ipod上安装ipad应用

先把地址贴上http://www.ifans.com/forums/showthread.php?t=298141

首先把.ipa改成.zip,拖出其中的info.plist和iTunesMetadata.plist,修改后再托回压缩包中,覆盖原来的,最后把zip改回ipa,修改后可以用iTunes同步到iphone上,但是具体能不能用,有没有什么毛病就不一定了,要解决这些还需要更深一部的修改,毕竟ipad程序本来就不是给iphone设计的。

简单说下修改过程吧,其实修改两处即可

  1. info.plist  中UIDeviceFamily,2改成1
  2. iTunesMetadata.plist 中softwareSupportedDeviceIds,9改成1

实测garageband可以安装上,但是只能显示左上角的部分,基本不能用,别的应用也没来得及下载,大家自行实验吧。

[教程]共享本机代理给其他设备

由于某些众所周知的原因,本文风格可能有些委婉,还请各位谅解。

     有些代理程序只能给本机使用,比如那些默认地址是localhost:port这样的,要把这种只针对本地的代理共享给其他设备尤其是iphone,touch,ipad,android等移动设备就有些麻烦了。笔者认为其中一个可行的方法就是搭建一个服务器,比如apache之类的,再设法把网络请求通过本机的代理发送(大概就是这个意思吧,我也描述不太好)。但是我只实现了搭建服务器这一块,不知道怎么实现后面那部分,要是高手看到这还请多多指教。

    好了言归正传,既然有难度的弄不明白,总有简单的方法,只需要Charles Web Debugging Proxy这个软件即可实现。这个软件夸Mac Linux Windows三大平台,有30天试用期,希望广大同学多多支持正版。

    软件针对本文的使用方法:菜单:Proxy  >>  External Proxy Settings…,勾选 Use External Proxy Serves,在下面即可设置代理,注意到这里还可以设置socks代理,因此可以通过Charles把代理共享给不支持socks代理的设备。

    在Proxy >> Proxy Settiongs下面可以设置对外的端口,默认是8888,设置好之后就可以把代理共享给其他设备了。

Have Fun

-以上-

iOS 上搭建C/C++开发环境 Beta

11.02.24更新:这有一个别人写的简单版,更方便。

    先说一下效果吧,STL啥的试了几个可用,成功编译了我之前写的一个垃圾程序,过多的测试还没有做,应该能满足基础需求。

    标题之所以加了Beta,是因为笔者也是参考各路教程,东拼西凑才把GCC搭建好的,过程相当混乱,有些步骤也可能有遗漏,因此本文仅供参考,尽量不要完全遵照这个教程。

搭建过程如下:

  1. 当然是越狱,装Cydia,这个不多说了,有锁的注意,小心变砖。
  2. Cydia里安装OpenSSH,APT 0.6 Transitional,Aptitude,wget,unzip,zip
  3. SSH到你的iphone上,这里强烈建议把iphone的root和mobile用户的密码改了,保证机器的安全。
  4. 找一个你喜欢的文件夹:
    wget http://apt.saurik.com/debs/libgcc_4.2-20080410-1-6_iphoneos-arm.deb
    dpkg -i libgcc_4.2-20080410-1-6_iphoneos-arm.deb
    apt-get install iphone-gcc ldid make
    wget下载的那个deb包之后可以删除,随你。另外libgcc那个不用费心去看是否有新版,就用这个就行。
  5. 下载这个附件,把里面的libSystem.dylib放到iphone的 /usr/lib/ 目录下
  6. 这一步仅供测试用,终端上输入:
    echo 'main() { printf("Hello, world!\n"); }' > hello.c
    gcc -o hello hello.c
    ldid -S hello
    ./hello
    ldid是给编译好的程序签名,要不然iphone不会让你运行
  7. 之后就有些混乱了,在Cydia里先后安装了GNU Debugger, C++ Standard Library, iPhone 2.0 Toolchain, 这里面也许有不需要的,但是不想再刷机测试一下。
  8. 现在如果我没有遗漏什么步骤的话,测试stdio.h等c的头文件应该是OK的,C++的iostream等好像还不行,编译时提示应该是找不到usr/include/c++/4.0.0/bits/c++config.h这个文件。此时把第5步中下载的那个附件中的include.tar.gz中的usr/include/c++/4.0.0/ 中的arm-apple-darwin8,拷贝到iphone /usr/include/c++/4.0.0/ 下,然后在bits/ 中建立arm-apple-darwin8/ 中所有文件的链接,因为这里有我们需要的c++config.h,直接拷贝这些文件到bits下也应该可以。
  9. 之后用g++编译一个测试文件出现的错误提示应该是找不到 -lstdc++,原因其实是缺少libstdc++.dylib这个文件,这个文件我是在XCode里面找的,尝试了几个找到了个好用的,但是不知道具体是哪一个了,第5步那个附件里也提供了,是从iphone中拷出来的,应该好用。

到此就应该能实现预期的目标了,我能回忆起的过程也就是这些了,大家有问题留言吧。

附参考文献:

  1. 【ipod4g出品】用 iPhone gcc 编译 iPhone SDK 游戏(真机开发、运行及调试) 
  2. iphone-gcc

Apple岁末广告攻势

Apple这样一家大公司之所以如此成功,当然少不了广告的作用,下面是笔者在2010年年末收到的apple广告邮件截图,与大家分享一下,共同体验Apple的强大。

这一段的广告与往日不同,采用了红色的文字和按钮,完美展现出节日的气氛。

11月16日,应该是这一波广告攻势的第一封mail吧,涵盖了Apple2010年的主要产品:iPad、Air、Touch、iPhone、Apple TV

继续阅读Apple岁末广告攻势