标签存档: Xcode

[笔记] Objective-C 中模拟泛型及 Xcode 格式化代码插件

记录一些 iOS & OS X 开发过程中学到或有趣的东西。

Objective-C 中模拟泛型

今天看到的一个辅助代码,可以在 Objective-C 代码中添加泛型的支持:

泛型是程序设计语言的一种特性。允许程序员在强类型程序设计语言中编写代码时定义一些可变部份,那些部份在使用前必須作出指明。各种程序设计语言和其编译器、运行环境对泛型的支持均不一样。(via )

泛型一般出现在 .NET、Java 或 C++ 的代码里面。

在 Objective-C 里面,像数组之类的容器,在取单个元素时,返回类型都是 id,这个时候如果要使用返回对象的一些属性,就需要先转换一下类型,或者使用 getter 方法来获取。

如果用了泛型之后,就很方便了,可以直接以 arr.lastObject.prop 的方式来访问。

使用了上面这个代码使 Objective-C 支持泛型后,就可以像下面这样写代码了:

generics example

这个辅助代码是一个大宏,给 Objective-C 添加泛型支持是以以下几个方面来做到的,例如给 MyClass 添加泛型支持来说明:

  1. 定义一个 MyClass 的 Protocol
  2. 给各个容器类(例如 NSArray、NSMutableArray、NSSet)添加 Category,重新定义各个容器操作方法的返回值和参数类型
    1. 获取单个元素的方法返回值类型修改为 MyClass *
    2. 返回容器的方法返回值类型修改为 NSArray<myclass> *
    3. 参数类型同样处理

这样在使用 NSMutableArray</myclass><myclass> *arr 这样一个变量时,如果添加的元素不是 MyClass * 类型,就会发出警告了。

不过因为 Objective-C 在编译时并不会强制要求变量类型一致,所以如果传递一个非 MyClass *类型的参数,也是可以编译通过的。

当然这个库只能说是在一定程度上方便编写代码而已,至于用不用还是见仁见智了,每次要写 NSArray</myclass><myclass *> 也不见得更方便。

Xcode 代码格式化插件 BBUncrustifyPlugin

插件地址:

这个插件算是对 uncrustify 的一个快捷引用了。

可能会比 Xcode 自带的 Re-indent 功能强大一点点 :)

另外,还有一个图形化的参数配置工具,可以用来配置 uncrustify 那好几百项目的参数:UncrustifyX

参考资料

  1. http://iosdevelopertips.com/objective-c/generics-in-objective-c.html
  2. https://github.com/tomersh/Objective-C-Generics
  3. https://github.com/benoitsan/BBUncrustifyPlugin-Xcode
  4. http://zh.wikipedia.org/wiki/%E6%B3%9B%E5%9E%8B
  5. http://uncrustify.sourceforge.net

—EOF—

给 iOS 项目添加自动更新属性

在 iOS 项目中,有些时候为了方便跟踪发布时的版本,方便调试,或者为了展示程序的编译日期,可以通过在 Info.plist 里面添加自定义属性的方式来实现,但是这个工作是一个纯粹机械的重复劳动,每次手工去更新是比较麻烦的一个事情。

好在 Xcode 项目支持自定义脚本的编译步骤,我们可以通过在编译过程中使用自定义脚本去更新 Info.plist。

在 /usr/libexec 目录下面,有一个工具 PlistBuddy,它可以很方便地修改 plist 文件,而不需要去用 sed 之类的编辑工具来修改。

为了在使用 PlistBuddy 的时候可以直接用 Set 命令设置属性,我们先在 iOS 项目的 Info.plist 里面加一个需要自动更新的属性,例如 BUILD_DATE 和 GIT_REVISION,类型选择为字符串,值填 AUTO_GENERATED。

然后在 iOS 项目的 Target 上添加一个新的编译步骤 Run Script Build Phase:

下页就是要编写脚本了

# 获取编译的日期
DATE=`date +%Y.%m.%d`
 
# 获取编译时 Git 库的短版本号
GIT_REVISION=`git rev-parse --short HEAD`
 
# 设置 Info.plist 中相关的属性
/usr/libexec/PlistBuddy "$TARGET_BUILD_DIR/$INFOPLIST_PATH" -c "Set BUILD_DATE $DATE"
/usr/libexec/PlistBuddy "$TARGET_BUILD_DIR/$INFOPLIST_PATH" -c "Set GIT_REVISION $GIT_REVISION"
 
# 将 Info.plist 转换为二进制格式
plutil -convert binary1 "$TARGET_BUILD_DIR/$INFOPLIST_PATH"

如果需要在程序里获取这些属性,那么就可以用下面的方法:

NSString *buildDate = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"BUILD_DATE"];
NSString *revision = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"GIT_REVISION"];

— EOF —