我们都知道 Vim 和 Emacs 都是文本编辑器中的上古神器,你也许用 ctags,cscopes 配合 Vim 完成过大型 C 或者 C++ 的开发,你也许配合过其他插件,完成过 JavaScript,python 代码的开发,但是很少有人试过 iOS app 的开发吧,毕竟 iOS 的框架包含了很多东西,以及 Objective-C 天生很长的 API 名字,让我们没办法把此神器用起来,今天我就来给大家讲下我是怎么使用 Vim 开发 iOS App 的,当然 Emacs 也可以

begin

使用 Vim 开发 iOS App 并不是特殊的爱好,而是被 Xcode 8 活生生的逼的,刚开始更新了 Xcode 8 以后,Xcode 8 把第三方插件给屏蔽了,导致没有 XVim 给我用了,没有 XVim 以后,发现异常不顺手,于是尝试用了一段时间的 AppCode,不得不说 AppCode 是一个非常好的 IDE,但是他有个很大的缺点,那就是 Java,JetBrain 家的东西都很不错,唯一缺点就是基于 Java,整个平台都略慢,然后我在不断的 google 过程中,发现了有人竟不知何谓恐惧,竟然使用 Vim 开发 iOS App,最后我也学会了这个新姿势 XDDDD

不过目前,只支持 Objective-C 代码的开发,swift 的话,没有解决工程文件自动补全的问题,因为目前大家使用的流行的 swift 自动补全工具 SourceKitten 并没有支持 workspace 所以暂时还没用起来

以及,目前不支持调试,因为发现 Vim 对调试的支持确实好糟糕...

准备活动

工欲善其事,必先利其器,主角是 Vim 或者 Emacs,少了其他配角和龙套们,也没办法正负恐惧,我们来看看用到了些什么东西,让我们的 Vim 成为利器的,这里只是点下他们的名,文章后面会把链接奉上

  • 首先我们来看主角队的同学们,他们是征服恐惧的主力

    • macOS,没有神话,开发 iOS 还是只能在 Mac 上
    • 支持 python 的 Vim,可以用 Vim8 或是 neoVim 食用更佳,我就用的 neoVim
    • YCMD,其实他是 YouCompleteMe + YouCompelteMeDeamon 的合体,自动补全、定义跳转等功能,就依赖他了
  • 接下来我们来看看其他龙套们

    • Vbundle,装插件用的,没他,龙套和主角都不用上场了
    • unite + unite-outline + unite-outline-objc,提供了方法导航
    • auto-pairs,自动补全右括号
    • ctrlp,文件搜索跳转
    • Ag,字符串搜索工具
    • syntastic,语法检查工具
    • vim-clang-format,代码格式工具

恩,需要的东西大概就是这些了,Vim 的配置文件,我是基于好久以前 square 开源的 maximum-awesome 的,所以,配合这个食用风味更佳,我的 dot file 也放到了 github 上,欢迎大家 star

进入正题

龙套们,基本都可以通过配置 vbundle 来完成安装,之后只用配置对应的快捷键就好了,这里的正题,要搞定难搞的主 YCMD

难搞的主 YCMD

安装 YCMD

YCMD 的安装很简单,主要是需要一定的配置

首先在 vim 的配置文件中加入下面的内容,更新配置文件并执行 BundleInstall 命令,让 Vbundle 把 YouCompleteMe 插件装上

  1. Plugin 'Valloric/YouCompleteMe'

然后到这个路径 ~/.vim/bundle/YouCompleteMe 这里是 YouCompleteMe 安装的位置,在这里需要编译 YCM,一条命令就可以搞定

  1. ./install.py --clang-completer --system-libclang

--clang-completer 告诉脚本我们需要 clang 的支持,--system-libclang 告诉编译脚本使用系统的 clang,因为之前 clang 升级 4.0 的时候,并没有已经编译好的包给我下载,所以这里不用系统 clang 的话,编译脚本会下载一个 clang 3.0,这样就无法支持 iOS 10.0 以后的 sdk 了,因为 iOS 10.0 以后的 sdk 为了支持 swift 引入了一些 clang 3.0 不支持的新语法,所以这里要加上 --system-libclang

然后等他编译完成,这样 YCMD 就配置好了,似乎这里看并不是很难搞,其实难搞的是如何在 iOS 项目中配置好自动提示

为 Xcode 项目配置 YCMD

这里进入到了真正征服恐惧的地方了

YouCompleteMe 的原理

曾经有人说过,编辑器再怎么神器是没办法超过 IDE 的,因为 IDE 是通过编译、解析整个项目的所有文件,来达到语法错误提示,自动补全,定义跳转等高级功能的,而 YCMD 就是来弥补这一个差距的,YCMD 通过传入完整的编译参数,编译需要提示的文件,来实现自动补全,这样没办法超过 IDE 的部分就被抹平了

配置一个项目

这里我们配置一个复杂的项目来练练手,首先 YCMD 是不可能通过 Xcode 的项目文件或是 workspace 文件获取到编译参数的,所以这一步需要手来,当然,将来可以做成自动的,因为目前手动的做其实很方便,所以现在还没有做成自动的

首先,YCMD 是通过每个项目路径下的 .ycm_extra_conf.py 脚本文件来获取编译参数的,这个脚本文件中有一个叫做 FlagsForFile 的函数,我们通过这个函数返回某一个特定文件需要的编译参数,一般情况下大部分文件的编译参数是一样的,我们来看一个配置的列子

  1. import os
  2. import ycm_core
  3. flags = [
  4. '-resource-dir',
  5. '/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.0.0',
  6. '-x objective-c',
  7. '-arch armv7',
  8. '-fmessage-length=0',
  9. # '-fmodules',
  10. # '-gmodules',
  11. '-fdiagnostics-show-note-include-stack',
  12. '-fmacro-backtrace-limit=0',
  13. '-D__arm__=1',
  14. '-D__IPHONE_OS_VERSION_MIN_REQUIRED=80000',
  15. '-std=gnu99',
  16. '-fobjc-arc',
  17. '-Wnon-modular-include-in-framework-module',
  18. '-Werror=non-modular-include-in-framework-module',
  19. '-Wno-trigraphs',
  20. '-fpascal-strings',
  21. '-Os',
  22. '-fno-common',
  23. '-Wno-missing-field-initializers',
  24. '-Wno-missing-prototypes',
  25. '-Werror=return-type',
  26. '-Wunreachable-code',
  27. '-Wno-implicit-atomic-properties',
  28. '-Werror=deprecated-objc-isa-usage',
  29. '-Werror=objc-root-class',
  30. '-Wno-arc-repeated-use-of-weak',
  31. '-Wduplicate-method-match',
  32. '-Wno-missing-braces',
  33. '-Wparentheses',
  34. '-Wswitch',
  35. '-Wunused-function',
  36. '-Wno-unused-label',
  37. '-Wno-unused-parameter',
  38. '-Wunused-variable',
  39. '-Wunused-value',
  40. '-Wempty-body',
  41. '-Wconditional-uninitialized',
  42. '-Wno-unknown-pragmas',
  43. '-Wno-shadow',
  44. '-Wno-four-char-constants',
  45. '-Wno-conversion',
  46. '-Wconstant-conversion',
  47. '-Wint-conversion',
  48. '-Wbool-conversion',
  49. '-Wenum-conversion',
  50. '-Wshorten-64-to-32',
  51. '-Wpointer-sign',
  52. '-Wno-newline-eof',
  53. '-Wno-selector',
  54. '-Wno-strict-selector-match',
  55. '-Wundeclared-selector',
  56. '-Wno-deprecated-implementations',
  57. '-DOBJC_OLD_DISPATCH_PROTOTYPES=0',
  58. '-isysroot',
  59. '/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk',
  60. '-fstrict-aliasing',
  61. '-Wprotocol',
  62. '-Wdeprecated-declarations',
  63. '-miphoneos-version-min=8.0',
  64. '-g',
  65. '-Wno-sign-conversion',
  66. '-Wno-infinite-recursion',
  67. '-fembed-bitcode-marker',
  68. '-I/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform',
  69. '-I/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/usr/include',
  70. '-I/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator.sdk/System/Library/Frameworks',
  71. '-I/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/../lib/clang/8.0.0/include',
  72. '-F/Users/apple/Documents/Developer/CloudLifeWorkspace/iOS/Develop/Project_iOS/project',
  73. '-MMD',
  74. '-MT',
  75. '-MF',
  76. ]
  77. SOURCE_EXTENSIONS = [ '.cpp', '.cxx', '.cc', '.c', '.m', '.mm' ]
  78. HEADER_EXTENSIONS = [ '.hpp', '.hxx', '.hh', '.h' ]
  79. def FlagsForFile( filename, **kwargs ):
  80. staticFlags = flags
  81. return {
  82. 'flags': staticFlags,
  83. 'do_cache': True
  84. }

这里上面的代码可以当作 .ycmd_extra_conf 文件的一个最小模板,也就是如果我们的项目里面没有子目录,没有第三方库,那么使用这个已经可以为 iOS 项目提供自动提示了

颤抖吧凡人,如此这般的编译条件,需要你能够把 Xcode 项目配置中的编译参数完完全全翻译出来才行,但是我也是凡人,所以这个不是我写的,而是有方法生成的,方法如下

把需要增加自动提示的项目用 Xcode 打开,然后编译,然后如下图所示,找到编译信息然后随便找项目中的一个文件,注意不要是 Pod 中的文件,最右边,有个三条横线的按钮,点开他,没错,你看到了完整的编译参数,下图中 EXPORT PATH =.... 下面的所有内容就是完整的编译参数

  • Report View

  • 戳这个按钮

  • 我们要的编译信息

右键,copy,找到你熟悉的记事本,参数都是空格分隔的,所以,这里我们把它转换成上面代码中的形式,并把不需要的去掉,比如这里我注释了 -fmodules-gmodules 因为这样编译没办法使用 module

把这些加入到配置文件中后,再打开 Vim 你就会发现自动提示变得非常好用了,不过这里还会有一个问题,如果编译的时候,有无法找到 UIKit,这是因为 YCMD 默认引入了 macOS SDK 的路径,导致了编译时 clang 认为我们编译目标是 macOS,所以如下图需要修改 ~/.vim/bundle/YouCompleteMe/third_party/ycmd/ycmd/completers/cpp/flags.py 文件,去掉默认引入 macOS sdk 的编译参数,这样就好了

效果图们

至此,最主要的问题已经被我们解决了,接下来看下效果如何

  • 首先是自动提示

  • 查找文件

  • 方法名称大纲

  • 搜索字符串

  • 语法检查

好处

这么做自然不是为了花样炫技,更多的是为了探索 Vim 的使用,以及更多了解 Xcode 项目

  • 完整的 Vim 环境,写代码再也不用碰鼠标了
  • Vim 插件 + 不满的地方自己动手丰衣足食
  • 快速,跟 Vim 比速度,笑话
  • 方便快接的字符串搜索,替换操作
  • 学了点 Python
  • 支持 cocoapod,毕竟 pod 也只是编译参数而已
  • 附赠一个 C/C++ 的开发环境

已知问题

虽然目前已经可以达到写代码的程度了,但是还是有很多问题,如下:

  • 没办法 debug
  • 不支持 Xcode 中的 group 展示
  • 头文件的提示有问题
  • 不能使用 @import 的导入,会报语法错误
  • xib,storyboard 自然是不行的,我的做法是 Xcode 里面拖 UI + 关联 Outlet + Debug,Vim 中做大量的代码编辑操作
  • [] 方括号的匹配没有 Xcode 那么智能
  • delegate 或是全局的自动提示,需要使用 ctrl + 空格打开,并且有时候会有点慢
  • delegate 的自动提示有时候需要输入前面半部分的方法名才会有,比如上面截图的 tableView,需要先输入 - (void)tableView:(UITableView *)tableView 再使用 ctrl + 空格才会有非常好的自动提示,当然输入前面这部分也会有一定的提示,整体上看能接受

上面的问题都是一直以来我没有解决的问题,大家要是发现有破解的方法,欢迎联系

end

折腾这么多,相信大家已经可以用 Vim 敲 iOS 的代码了,虽然虽然当初开始折腾的时候,踩了很多坑,比如 clang 3 升级 clang 4 后,原来的配置都不能用了,但是收获挺多的也并不是这么一篇文章能够说完的,除了 Vim 大家也可以试试 Emacs 下的配置,我用的 Spacemacs,添加了 ycmd 的 layer,配置后也有了相同的效果

也欢迎大家丢砖

参考资料

  • YouCompleteMe: 自动补全插件
  • Vbundle: 插件管理插件
  • Unite: 一个通用的显示插件,可以用来显示各种东西,比如文件列表,buffer 列表,outline
  • Unite-outline: Unite 插件的 outline 插件
  • Unite-outline-objc: Unite-outline 插件的 Objective-C 插件
  • auto-pairs: 自动补全括号的插件
  • ctrlp: 文件查找插件
  • Ag: 字符串查找插件
  • syntastic: 语法检查插件
  • vim-clang-format: clang format 格式化插件
  • VimAwesome: 方便的 Vim 插件导航网站
  • maximum-awesome: 一个比较有名的 Vim 配置,包括了上面的 Vbundle,Ag,ctrlp,syntastic 等插件,以及一些很方便的配置,我的配置文件是基于这个配置的,使用前先安装这个
  • 我的配置文件: 我的配置文件,除了上文写的内容,还加了些 php,python,js 等开发配置,以及一些自己觉得用起来方便的配置

征服恐惧!用 Vim 写 iOS App的更多相关文章

  1. Vim 写 iOS App

    Vim 写 iOS App 我们都知道 Vim 和 Emacs 都是文本编辑器中的上古神器,你也许用 ctags,cscopes 配合 Vim 完成过大型 C 或者 C++ 的开发,你也许配合过其他插 ...

  2. 整理一下前段时间在写iOS app时所涉及的东西

    在刚学习和做完一个android app后,看了两周的Objective-C就开始做这个项目,所以整个app代码有很多现学现用的东西,今天来总结一下. 这个名为VID的app是用于公司产品的研发与de ...

  3. ios app开发步骤

    虽然开发一个app的任务看上去可能很艰巨,但是整个过程可以抽象成几个相对简单的步骤,下面这些步骤会在你开发第一个app时帮你步入正途. 定义Concept 每个好app都是从一个concept开始. ...

  4. 写一个类似淘宝的ios app需要用到哪些技术?

    写一个类似淘宝的ios app需要用到哪些技术? 让我想起了有人私信我,说不缺钱,做个类似知乎的东西,包括加运营,需要多少钱. 扯淡结束,正好最近看了一点这方面的东西,也许对题主来说有点帮助. 手机淘 ...

  5. [编译] 7、在Linux下搭建安卓APP的开发烧写环境(makefile版-gradle版)—— 在Linux上用命令行+VIM开发安卓APP

    April 18, 2020 6:54 AM - BEAUTIFULZZZZ 目录 0 前言 1 gradle 安装配置 1.1 卸载系统默认装的gradle 1.2 下载对应版本的二进制文件 1.3 ...

  6. 如何用PHP/MySQL为 iOS App 写一个简单的web服务器(译) PART1

    原文:http://www.raywenderlich.com/2941/how-to-write-a-simple-phpmysql-web-service-for-an-ios-app 作为一个i ...

  7. iOS APP安全杂谈

      iOS APP安全杂谈 高小厨 · 2015/06/30 10:16 0x00 序 以前总是在这里看到各位大牛分享其安全渗透经验,而今我也很荣幸的收到了乌云的约稿,兴奋之情难以言表.由于IOS是一 ...

  8. iOS App引导页功能实现

    一.写作原因 以前都没有想着来写点东西,今天遇到件事情让我决定每次还是要做记录.因为以前自己可以轻松的完成pod spec的配置,但是今天在做的时候还是忘了遇到了很多坑.pod spec配置遇到的坑不 ...

  9. 用Model-View-ViewModel构建iOS App(转)

    转载自 Model-View-ViewModel for iOS [译] 如果你已经开发一段时间的iOS应用,你一定听说过Model-View-Controller, 即MVC.MVC是构建iOS a ...

随机推荐

  1. NSCalendar 日历类

    NSCalendar 日历类 Cocoa中对日期和时间的处理 NSCalendar (一) (2008-11-12 21:54:10) NSCalendar用于处理时间相关问题.比如比较时间前后.计算 ...

  2. Chapter5 – 碰撞检测

    主人公能够放子弹了,虽然子弹看起来很美,但是怎么样来打到妖怪? 在这一章我们介绍一下最简单的碰撞检测方法去实现它. 首先第一个,我们有必要保存每个妖怪和子弹的指针,来够追踪他们的位置. 在这个游戏中我 ...

  3. 数据库 Mysql事务详解

    Mysql事务 mysql的事务默认是自动提交的,也就是你提交一个query,他就直接执行!我们可以通过 禁止自动提交 开启自动提交 //mysql事务 #include <stdio.h> ...

  4. 详解Grunt插件之LiveReload实现页面自动刷新(两种方案)

    http://www.jb51.net/article/70415.htm    含Grunt系列教程 这篇文章主要通过两种方案详解Grunt插件之LiveReload实现页面自动刷新,需要的朋友可以 ...

  5. ReactiveCocoa学习笔记--用法

    1.监测UI变量的变化 return 后把值传递下去. 1.1.输出 [self.usernameTextField.rac_textSignal subscribeNext:^(id x){ NSL ...

  6. IOS 利用图片设置背景

    UIImageView* imageView = [[UIImageView alloc] initWithFrame:self.view.bounds]; imageView.image = [UI ...

  7. php 正则只保留 汉字 字母 数字

    $str = "?><?>”\"<喂喂喂555?><|“:L}{P+_)In thsdff0?><M<>\"s ...

  8. 新手如何学习java(java学习建议路线图)

    怎么学习Java,这是很多新手经常会问我的问题,现在我简单描述下一个Java初学者到就业要学到的一些东西:     首先要明白Java体系设计到得三个方面:J2SE,J2EE,J2ME(KJAVA). ...

  9. iPhone 屏幕分辨率

    5S     640 x 1136 5       640 x 1136 4s     640 x 960 4       640 x 960 3gs   320 x 480

  10. C标准I/O建立一个文件仓库

    实现了 增删改查 创建了一个结构体 保存 num name cout price 代码 #include<stdio.h>#include<string.h>#include& ...