开发适应iphone/ipad及多ios版本程序的技巧

1,让项目/Target支持不同版本的iOS

要让一个程序可以在多个版本的ios上运行相当简单:

  • 在Project Settings中,将BaseSDK设置为最新的版本。
  • 再将【iPhone OS Deployment Target】设置为最老的版本。

将上面这个版本信息设置正确非常简单。但是要在新的iOS上使用新的系统功能,而且还不能让程序在老版本的系统中崩溃,这相对难一些。

2,使用新iOS功能,同时支持老版本

如果你想在iOS4中启动一个后台任务,同时要支持老版本,就要像下面这样写:

Objective-C
1
2
3
4
5
6
7
8
9
10
11
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
if ( [ [ UIApplication sharedApplication ]
         respondsToSelector : @selector ( beginBackgroundTaskWithExpirationHandler : ) ] )
{
         UIBackgroundTaskIdentifier bgTask = [ [ UIApplication sharedApplication ]
         beginBackgroundTaskWithExpirationHandler : ^ { } ] ;
         // Perform work that should be allowed to continue in background
         [ [ UIApplication sharedApplication ] endBackgroundTask : bgTask ] ;
}
#endif

代码分为三个部分:

  1. #if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000 这是编译时期的条件判断。如果我们选择的BaseSDK小于4.0,不会导致编译错误。
  2. UIApplication的beginBackgroundTaskWithExpirationHandler方法在运行时做的check。
  3. check中间的功能代码。

3,让条件判断更好看一些

上面代码有编译期判断和运行时check。要做两个判断,写法麻烦。我们要把两个check合并到一起:

Objective-C
1
2
3
4
5
6
IF_IOS4_OR_GREATER (
UIBackgroundTaskIdentifier bgTask = [ [ UIApplication sharedApplication ]
beginBackgroundTaskWithExpirationHandler : ^ { } ] ;
     // Perform work that should be allowed to continue in background
     [ [ UIApplication sharedApplication ] endBackgroundTask : bgTask ] ;
) ;

可以像下面这样实现宏:

Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
13
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_4_0
#define kCFCoreFoundationVersionNumber_iPhoneOS_4_0 550.32
#endif
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 40000
#define IF_IOS4_OR_GREATER(...) \
if ( kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iPhoneOS_4_0 ) \
{ \
__VA_ARGS__ \
}
#else
#define IF_IOS4_OR_GREATER(...)
#endif

如果想要检查早于某一个sdk版本,可以像下面这样写:

Objective-C
1
2
3
4
5
#define IF_PRE_IOS4(...) \
if ( kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iPhoneOS_4_0 ) \
{ \
__VA_ARGS__ \
}

关于上面写的宏:

  1. 这里使用的是kCFCoreFoundationVersionNumber在运行时判断iOS的版本。有很多例子用的是[[UIDevice currentDevice] systemVersion]。后者需要字符串比较,没有double型的比较直接。
  2. 没有使用do { x } while (0) ;来包装宏。
  3. 宏使用了变量参数列表,加多少个变量都没有关系,用逗号隔开就行。

再有一点,kCFCoreFoundationVersionNumber并不是所有版本SDK都有定义。有时候我们需要自己定义:

Objective-C
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
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_2_0
#define kCFCoreFoundationVersionNumber_iPhoneOS_2_0 478.23
#endif
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_2_1
#define kCFCoreFoundationVersionNumber_iPhoneOS_2_1 478.26
#endif
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_2_2
#define kCFCoreFoundationVersionNumber_iPhoneOS_2_2 478.29
#endif
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_3_0
#define kCFCoreFoundationVersionNumber_iPhoneOS_3_0 478.47
#endif
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_3_1
#define kCFCoreFoundationVersionNumber_iPhoneOS_3_1 478.52
#endif
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_3_2
#define kCFCoreFoundationVersionNumber_iPhoneOS_3_2 478.61
#endif
#ifndef kCFCoreFoundationVersionNumber_iPhoneOS_4_0
#define kCFCoreFoundationVersionNumber_iPhoneOS_4_0 550.32
#endif

4,更好的解决方案

比使用宏更好的方式是使用一个简单的函数。

比如下面的代码:

Objective-C
1
2
3
4
5
6
7
8
9
10
11
#if __IPHONE_OS_VERSION_MAX_ALLOWED >= 30200
if ( [ [ UIDevice currentDevice ] respondsToSelector : @selector ( userInterfaceIdiom ) ] &&
[ [ UIDevice currentDevice ] userInterfaceIdiom ] == UIUserInterfaceIdiomPad )
{
// iPad specific layout changes
}
else
#endif
{
// iPhone layout
}

可以使用IF_IOS4_OR_GREATER来改写,但更好的方法是下面的代码:

Objective-C
1
2
3
4
5
6
7
8
if ( isIPad ( ) )
{
// iPad specific layout changes
}
else
{
// iPhone layout
}

关于isIPad()方法:

Objective-C
1
2
3
4
5
6
7
8
9
10
11
12
BOOL isIPad ( )
{
IF_3_2_OR_GREATER
(
if ( [ [ UIDevice currentDevice ] userInterfaceIdiom ] == UIUserInterfaceIdiomPad )
{
return YES ;
}
) ;
return NO ;
}

5,结论:

Apple没有让支持老版本的sdk非常简单。因为他们想让每个人一直使用新的系统,或者买新的设备。但这对开发人者来说很不现实,我们不能期待软件的用户一直使用新系统或新设备。

写适用多版本的程序关键点是写尽量少的if判断。你肯定不想为了对应多版本的问题,让自己的程序有很多的分支,因为每一个分支都意味着要进行测试。

如果你发现需要写很多的if判断,还可以为每个os版本写一个子类。用不同实现类实现功能。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值