同时开发 Android 和 iOS apps 是一种什么样的体验?

关注者
1,226
被浏览
87,673

36 个回答

申明:本人全职 Android 业余 iOS,只是不能苟同有人说的:"Android 基础设施对开发者更友好",并非刻意粉 iOS 黑 Android。

最近项目中涉及图片/音视频处理,深有体会:至少在多媒体这块,iOS 的轮子明显更多、更好用。

图像处理:

  • iOS 的 CoreImage 库内置的 CIFilter 即可实现图片滤镜;
  • Android 这边基本没有原生支持,只能依赖 OpenCV 等开源项目在 native 层实现,而且可能某些滤镜不支持 Alpha 通道,需要自己在 Java 层再次回炉处理恢复Alpha通道;
  • 另外 iOS 还有个强大的第三方库 GPUImage,基于 GPU 加速,不仅支持图片滤镜,还支持相机视频实时滤镜;Android 虽然也有人弄了个 android-gpuimage,但功能上与前者不可同日而语,实际项目中被运用的应该不多。

流媒体播放:

  • iOS 的 AVFoundation 库内置的 AVQueuePlayer 天然支持播放队列,实乃逆天神器啊;
  • Android 的 VideoView 和 GLSurfaceView 一样继承自 SurfaceView,只支持绑定单个数据源,多个流媒体连续播放不太好无缝衔接(网上有人说可以通过 HttpProxy 实现预加载,这大概就是 @钟颖Cyan 所说的“奇技淫巧”);

流媒体处理:

  • iOS 的 AVFoundation 库内置的 AVMutableComposition / AVAssetExportSession / AVAssetReader / AVAssetWriter 等即可实现音视频合成;
  • Android 这块的原生支持 MediaCodec / MediaMuxer / MediaExtrator / MediaSync 等直到 4.1 / 4.3 / 6.0 才引入,而且文档少;而 jcodec / mp4parser 等 Java 层开源项目也存在性能/格式支持等各种坑,最后只能老老实实滚回去研究 FFmpeg 这个巨无霸了。

最终结果

iOS 分分钟就能撸出原型 demo,而 Android 还在苦逼地各种技术调研。

Android 轮子不给力,经常得自力更生。所以熟悉 C / C++、JNI / NDK 是必须的。

PS

有人说我讲的太片面,14年写过一篇:

iOS / Objective-C 在 API 层面与 Android / Java 的类比

。老文章了,如有纰漏请轻喷。

PPS

同时写 Android 和 iOS 真的没啥。这年头不会几门外语都不好意思出门,我会告诉你14年一年我就学了七种语言么(Objective-C / Swift / Golang / Rust / Haskell / C++11 / Lua)?

但熟悉 API 能写东西毕竟只是初级阶段,若想深入就得了解底层原理机制,而这是需要大量时间、精力、实践的。

有种说法是要成为 T 型人才(注意不是 π 哦),首先你得有那一竖,然后追求那一横。

踏踏实实打好基础(数据结构算法/操作系统/组成与体系结构/网络与密码/数据库,微积分/线性代数/离散数学/概率统计),并且在某一细分领域有所深入,然后再追求广度。

合理构建完善的知识体系很重要,盲目地追求所谓的全栈是不可取的。

之前在一个 Android 交流群看到有人说想学 iOS,理由是接外包更方便... 呵呵,真拿自己当 “码农” 啊。

哎,看不下去了

一:开发环境

iOS的Xcode是垃圾中的垃圾,尤其是现在对Swift的支持,我之前用的时候隔三差五的代码高亮崩溃了,Xcode的崩溃次数绝对是Android IDE的数倍起,而且真心卡,我感觉上下拖动都没60帧。

Android以前的Eclipse也是垃圾,后来出的Intelijia/Android Studio好太多。代码多了也卡,所以我干脆直接指定给他3G内存用(我电脑是16G的13寸rmbp),会好很多。不过自从Android全面切到Gralde后,感觉Gradle编译真心慢,尤其是多module依赖的时候,还有方法数超过6k5需要multidex的时候简直是噩梦,因为开了multidex后是不支持增量编译。这方面iOS好很多,iOS用的多的是cocopod管理依赖,改几行代码编译速度确实比Gradle快。

当然iOS可以用AppCode,但是这玩意老是跟不上Xcode的发版速度,比如iOS9出了,Xcode7出了,但是老得AppCode就没法写了,各种语法错误,得上新的开发版,但是开发版对于iOS新特性的支持肯定又不全

二:开发语言

iOS的OC语法怪异繁琐但是习惯就好,这玩意调用C/C++比Android用的Java好太多。后来的Swift改进太多,但是当前不成熟,主要是Xcode太垃圾,不过现在用Swift写的iOS App也渐渐多起来。Android的Java已死,死在1.7,是不可能上1.8的Lambda,虽然有第三方库搞这个。Jetbrain出的Kotlin对Android的支持也才开始,自己都没1.0,想用Kotlin写Android至少也得等个2,3年把。

三:页面导航和保存现场

iOS是用ViewController,Android用Activity,VC的push==Android的startActivity,VC的present==DialogFragment.show

无论哪个系统都有内存不够的问题,在应用被切到后台,Android原生支持序列化保存现场,以便之后App被回收后再回来能恢复(当然你可以不做,比如某个版本的百度地图就是这么干的,每次切出去进来就重载),Fragment做的那么复杂也有这部分原因,iOS默认不支持,需要开发者自己写很繁琐的代码,所以你可以见到,基本上没有iOS应用在后台被销毁后重进还能恢复现场,一般都是重载页面

复杂点的iOS App都要用到 ViewController互相内嵌,叫 ViewController Container,在Android上面就是Activity内嵌Fragment内嵌Child Fragment。

VC之间传数据因为没有保存现场的需求,所以直接给VC对象的某个属性赋值就OK。Androd就得经过Intent,要求数据必须支持序列化,当然你要是不愿意保存现场,跟iOS差不多也行。其实我也不知道哪个算比较好,因为iOS也有人抱怨iOS的做法让2个VC耦合太强。

四:App内存

iOS App启动后有差不多1/2整个系统内存的可用大小,但是Android的差距就很大,从32mb到195mb+(2G总内存)都有,跟整个手机的总内存有关,没用过3G,4G内存的Android手机,不知道heap size是多少。这就导致Android的内存更容易出问题。反正都有代码没写好因为强引用导致内存泄露的问题

五:UI,兼容性适配

iOS从最早的手动Frame,为了适配ip4 ip5的auto resizing,后来的AutoLayout,后来的Size Class。但是StoryBoard的AutoLayout真的非常非常难用,稍微复杂点的界面,左侧一堆一堆的约束,根本不可能改的了的,对比起,容我现在先吐一下,我眼睛痛。所以很多人用第三方的代码AutoLayout库,比如Masonry,但是我用下来感觉还是啰嗦。iOS9为了搞适配,增加了UIStackView,这其实就是Android的LinearLayout。AutoLayout另外一个问题是卡,所以基本没人会在UITableView的Cell里面用AutoLayout,全是手动Frame布局的。

iOS开发一直以来很多争吵,代码画布局(要么手动Frame,要么各种第三方布局库),还是全部StoryBoard/Xib,这2个都恶心,代码画,VC里面又是布局又是业务,后者又不是人能用的,StobyBoard/Xib的根本没有可读性可言,对于版本管理就是灾难。而且我个人对于Xcode能否打开复杂StoryBoard切保持不崩溃持有怀疑态度。

Android通常是XML画布局,代码做业务,相对来说好太多,XML非常好读写,写个ListView的Cell的速度比UITableView快太多,iOS是需要你自己计算高度的,当然你可以不用,我上面也说了,你不怕卡的话。但是Android兼容麻烦的是Rom兼容,尤其是国内厂商,对于Framework层改动太多,很容易踩到坑。

对于系统Api以及系统版本更新的坑,我印象里面,无论是iOS还是Android都不会少,逃不掉的,老老实实认命找workaround。

六:多线程

iOS的GCD NSOperation对Java的Executor多线程框架。就客户端开发而言,我没感觉出来这2者有什么麻烦或者为难的地方,都能满足需要,当然或许是我太浅薄。

七:存储

虽然iOS有CoreData,但是没人用啊,大家都喜欢SQLite,Androd官方是没ORM方案的,老老实实SQLite,第三方的ORM反正我心虚

iOS分配给App的几个文件夹,如果你在不该写的文件夹写,比如一个会被iCloud备份的文件夹下当缓存用我记得是会被AppStore驳回的。但是Android随便了,整个SD卡可以读写,某个版本的Android是禁止写第二个存储空间的(多数都是SD卡),后来我记得又改回去了。

八:动画

iOS的RunLoop在Android那边就是Handler/Looper/MessageQueue。iOS的RunLoop多个模式,可以在滚动的时候禁止其他的UI消息,很像Android上就是MessageQueue.IdleHandler

因为iOS要跟OS X共享代码,所以是拆分显示和事件处理(手机触摸屏,电脑就是鼠标键盘),也就有了CALayer和UIView,Android因为没历史包袱,都是View自己处理的。

iOS动画可以直接操作CALayer做,Android一般是用Animator操作View,但是因为版本兼容性的问题,很多人还是会用2.x的Aniamtion来做Android动画,那东西渣多了。Animator的一个好处是可以任意属性对于时间的变化,Facebook给iOS出的Pop我记得也是可以这样,不然你就得自己用

CADisplayLink封装了。

动画过程中的快慢iOS上是TimingFunction负责,Android是Interpolator

贝塞尔曲线 UIBezierPath 对应 Path

ViewController过场动画UIViewControllerTransitioning对应Android5的ActivityTransition,但是因为普遍Android手机版本跟不上。。。。很少有人用ActivityTransition。

Androd没有iOS的UIKit Dynamics库,有些特效就得自己写

九:上架

我就以国内情况为例,你如果有个新App,上架AppStore需要一个月你得做好准备,Apple大爷是一周审核一次你的App,有一项通不过你再等一周吧,审核不过会给你截图和解释,你改吧,然后下周又有新问题,所以大约一个月,来来回去4次。

国内没Google Play,所以你要么去小米商店,豌豆荚,应用宝,也得审核3,4天,比Apple要容易不少,但是渠道多,烦,一般还需要改Gradle脚本打包出不同渠道的包来判定对应的应用市场到底真的分发了多少来,都是跟钱有关。

十:感觉

写iOS是被Apple操,写Android是被各手机厂商操