登入帳戶  | 訂單查詢  | 購物車/收銀台( 0 ) | 在線留言板  | 付款方式  | 運費計算  | 聯絡我們  | 幫助中心 |  加入書簽
會員登入 新用戶登記
HOME新書上架暢銷書架好書推介特價區會員書架精選月讀2023年度TOP分類瀏覽雜誌 臺灣用戶
品種:超過100萬種各類書籍/音像和精品,正品正價,放心網購,悭钱省心 服務:香港台灣澳門海外 送貨:速遞郵局服務站

新書上架簡體書 繁體書
暢銷書架簡體書 繁體書
好書推介簡體書 繁體書

三月出版:大陸書 台灣書
二月出版:大陸書 台灣書
一月出版:大陸書 台灣書
12月出版:大陸書 台灣書
11月出版:大陸書 台灣書
十月出版:大陸書 台灣書
九月出版:大陸書 台灣書
八月出版:大陸書 台灣書
七月出版:大陸書 台灣書
六月出版:大陸書 台灣書
五月出版:大陸書 台灣書
四月出版:大陸書 台灣書
三月出版:大陸書 台灣書
二月出版:大陸書 台灣書
一月出版:大陸書 台灣書

『簡體書』iOS 8应用开发从入门到精通

書城自編碼: 2715196
分類:簡體書→大陸圖書→計算機/網絡程序設計
作者: 李梓萌
國際書號(ISBN): 9787302422884
出版社: 清华大学出版社
出版日期: 2015-12-01
版次: 1 印次: 1
頁數/字數: 296/448000
書度/開本: 16开 釘裝: 平装

售價:HK$ 127.7

我要買

 

** 我創建的書架 **
未登入.


新書推薦:
天象之维:汉画像中的天文与人文
《 天象之维:汉画像中的天文与人文 》

售價:HK$ 105.0
妓女与文人
《 妓女与文人 》

售價:HK$ 38.4
舵手证券图书 短线交易大师:工具和策略 24年新修订版 实战验证的交易技术 经典外版书
《 舵手证券图书 短线交易大师:工具和策略 24年新修订版 实战验证的交易技术 经典外版书 》

售價:HK$ 93.6
中国古兵器集成
《 中国古兵器集成 》

售價:HK$ 816.0
空腹力+轻断食:正在横扫全球的瘦身革命(全2册)
《 空腹力+轻断食:正在横扫全球的瘦身革命(全2册) 》

售價:HK$ 123.6
临床牙周病学和口腔种植学 第7版
《 临床牙周病学和口腔种植学 第7版 》

售價:HK$ 1557.6
粤港澳大湾区文化产业圈论纲
《 粤港澳大湾区文化产业圈论纲 》

售價:HK$ 153.6
粤港澳大湾区蓝皮书:粤港澳大湾区建设报告(2023)
《 粤港澳大湾区蓝皮书:粤港澳大湾区建设报告(2023) 》

售價:HK$ 225.6

 

建議一齊購買:

+

HK$ 183.2
《 iOS 9 开发指南 》
+

HK$ 218.3
《 精通iOS开发(第7版) 》
+

HK$ 164.7
《 iOS 8应用开发入门经典(第6版) 》
+

HK$ 183.2
《 iOS开发指南 从零基础到App Store上架(第3版) 》
編輯推薦:
iOS系统从诞生之日起到现在,在短短几年的时间内,凭借其硬件产品iPhone和iPad的良好用户体验,赢得了广大消费者用户和开发者用户的追捧。

本书从搭建iOS开发环境的入门知识讲起,依次讲解了Objective-C语言基础、Swift语言基础、Cocoa Touch框架、Storyboarding故事板、基本控件的应用、视图处理、界面控制器的处理、实现多场景和弹出框、屏幕旋转处理、声音服务、定位处理、与互联网接轨、与硬件之间的操作、开发通用的项目程序、游戏开发、读写应用程序数据、HealthKit开发详解、HomeKit开发详解、WatchKit开发详解、多功能音乐盒系统。

本书内容全面,几乎涵盖了iOS 8应用开发所需要的全部内容。全书内容言简意赅,讲解细致,特别适合初学者学习和消化,并可从清华大学出版社的网站下载书中的源代码。

本书适合iOS初学者、iOS爱好者、iPhone开发人员、iPad开发人员学习,也可以作为相关培训学校和大专院校相关专业的教学用书。
內容簡介:
iOS系统从诞生之日起到现在,在短短几年的时间内,凭借其硬件产品iPhone和iPad的良好用户体验,赢得了广大消费者用户和开发者用户的追捧。
本书从搭建iOS开发环境的入门知识讲起,依次讲解了Objective-C语言基础、Swift语言基础、Cocoa Touch框架、Storyboarding故事板、基本控件的应用、视图处理、界面控制器的处理、实现多场景和弹出框、屏幕旋转处理、声音服务、定位处理、与互联网接轨、与硬件之间的操作、开发通用的项目程序、游戏开发、读写应用程序数据、HealthKit开发详解、HomeKit开发详解、WatchKit开发详解、多功能音乐盒系统。
本书内容全面,几乎涵盖了iOS 8应用开发所需要的全部内容。全书内容言简意赅,讲解细致,特别适合初学者学习和消化,并可从清华大学出版社的网站下载书中的源代码。
本书适合iOS初学者、iOS爱好者、iPhone开发人员、iPad开发人员学习,也可以作为相关培训学校和大专院校相关专业的教学用书。
目錄
目 录
第1章 iOS开发入门1
1.1 iOS系统介绍2
1.1.1 iOS的发展历程2
1.1.2 iOS 8是一个革命性的版本2
1.2 加入iOS开发团队4
1.3 搭建开发环境6
1.3.1 Xcode介绍7
1.3.2 iOS SDK介绍8
1.3.3 下载并安装Xcode10
1.4 创建第一个iOS 8项目15
1.5 iOS的常用开发框架18
1.5.1 Foundation框架简介18
1.5.2 Cocoa框架简介20
第2章 Objective-C语言基础21
2.1 Objective-C语言基础22
2.1.1 TIOBE编程语言社区排行榜22
2.1.2 Objective-C介绍22
2.1.3 iOS选择Objective-C的原因23
2.1.4 Objective-C的优点和缺点23
2.2 第一段Objective-C程序24
2.2.1 使用Xcode编辑代码24
2.2.2 注释27
2.2.3 #import指令28
2.2.4 主函数29
2.2.5 显示变量的值31
2.3 数据类型和常量32
2.3.1 int类型33
2.3.2 float类型34
2.3.3 double类型35
2.3.4 char类型36
2.3.5 字符常量37
2.3.6 id类型38
2.3.7 限定词40
2.4 字符串41
2.5 表达式42
2.5.1 算数表达式42
2.5.2 常量表达式46
2.5.3 条件运算符46
2.5.4 sizeof运算符47
2.5.5 关系运算符48
2.5.6 强制类型转换运算符48
2.5.7 运算符的优先级49
第3章 Swift语言基础51
3.1 Swift基础52
3.1.1 Swift之父52
3.1.2 Swift的优点53
3.2 数据类型54
3.2.1 int类型54
3.2.2 float类型54
3.2.3 double类型55
3.2.4 char类型55
3.2.5 字符常量55
3.3 常量和变量56
3.3.1 常量56
3.3.2 变量56
3.4 字符串和字符57
3.4.1 字符串字面量58
3.4.2 初始化空字符串58
3.4.3 字符串可变性59
3.4.4 值类型字符串59
3.4.5 计算字符数量60
3.4.6 连接字符串和字符60
3.4.7 字符串插值60
3.4.8 比较字符串61
3.4.9 Unicode字符62
3.5 流程控制64
3.5.1 for循环65
3.5.2 while循环67
3.6 条件语句68
3.6.1 if语句68
3.6.2 switch语句69
3.7 函数70
3.7.1 函数的声明与调用70
3.7.2 函数的参数和返回值71
3.7.3 函数参数名73
第4章 Cocoa Touch框架77
4.1 Cocoa Touch基础78
4.1.1 Cocoa Touch概述78
4.1.2 Cocoa Touch中的框架78
4.2 iPhone的技术层79
4.2.1 Cocoa Touch层79
4.2.2 多媒体层85
4.2.3 核心服务层86
4.2.4 核心OS层87
4.3 Cocoa Touch中的框架87
4.3.1 Core Animation图形处理
框架88
4.3.2 Core Audio音频处理框架88
4.3.3 Core Data数据处理框架89
4.4 Cocoa中的类90
4.4.1 核心类90
4.4.2 数据类型类93
4.4.3 UI界面类97
4.5 国际化100
4.6 使用Xcode学习iOS框架101
4.6.1 使用Xcode文档101
4.6.2 快速帮助103
第5章 Storyboarding故事板105
5.1 故事板的推出背景106
5.2 故事板的文档大纲107
5.3 文档大纲的区域对象108
5.4 创建一个界面109
5.4.1 对象库109
5.4.2 将对象加入到视图中110
5.4.3 使用IB布局工具111
5.5 定制界面外观115
5.5.1 使用属性检查器115
5.5.2 设置辅助功能属性116
5.5.3 测试界面117
5.6 使用模板Single View Application118
5.6.1 创建项目118
5.6.2 规划变量和连接123
5.6.3 设计界面125
5.6.4 创建并连接输出口和操作127
5.6.5 实现应用程序逻辑129
5.6.6 生成应用程序131
第6章 基本控件的应用133
6.1 文本框控件134
6.1.1 文本框基础134
6.1.2 在屏幕中显示一个文本
输入框134
6.1.3 使用Swift实现UITextField
控件135
6.2 文本视图控件141
6.2.1 文本视图基础141
6.2.2 在屏幕中换行显示文本142
6.2.3 基于Swift使用UITextView
控件143
6.3 标签UILabel145
6.3.1 标签UILabel的属性146
6.3.2 使用UILabel显示一段
文本146
6.4 按钮控件150
6.4.1 按钮基础150
6.4.2 按下按钮后触发一个事件151
6.4.3 基于Swift在界面中实现
按钮的交互152
6.5 滑块控件156
6.5.1 使用滑块控件的基本方法157
6.5.2 实现各种各样的滑块158
6.5.3 使用Swift实现UISlider控件
效果166
6.6 图像视图控件UIImageView168
6.6.1 UIImageView的常用操作168
6.6.2 在屏幕中显示图像173
6.6.3 基于Swift使用UIImageView
控件173
6.7 UISwitch控件176
6.7.1 开关控件基础176
6.7.2 改变UISwitch的文本
和颜色176
6.7.3 基于Swift控制是否显示密码
明文179
6.8 分段控件182
6.8.1 分段控件的属性和方法183
6.8.2 使用UISegmentedControl
控件185
6.8.3 基于Swift使用
UISegmentedControl控件187
第7章 视图处理191
7.1 可滚动的视图192
7.1.1 UIScrollView的基本用法192
7.1.2 使用可滚动视图控件194
7.1.3 基于Swift使用UIScrollView
控件198
7.2 翻页视图处理200
7.2.1 PageControl控件基础200
7.2.2 基于Swift使用UIPageControl
控件201
7.3 提醒视图UIAlertView207
7.3.1 UIAlertView基础207
7.3.2 实现一个自定义提醒
对话框211
7.3.3 基于Swift使用UIAlertView
控件214
7.4 选择器视图UIPickerView219
7.4.1 选择器视图基础220
7.4.2 实现两个UIPickerView控件
间的数据依赖222
7.5 表视图基础226
7.5.1 表视图的外观226
7.5.2 表单元格227
7.5.3 添加表视图227
7.5.4 UITableView详解231
7.5.5 拆分表视图234
7.5.6 基于Swift在表视图中使用
其他控件237
7.6 活动指示器
UIActivityIndicatorView240
7.6.1 活动指示器基础240
7.6.2 实现一个播放器的活动
指示器240
7.7 进度条UIProgressView243
7.7.1 进度条基础243
7.7.2 实现一个蓝色进度条效果243
7.7.3 使用Swift实现自定义进度条
效果244
第8章 界面控制器的处理251
8.1 UIView基础252
8.1.1 UIView的结构252
8.1.2 视图架构254
8.1.3 视图层次和子视图的管理255
8.1.4 视图绘制周期256
8.1.5 设置UIView的位置
和尺寸256
8.2 导航控制器UIViewController
简介258
8.2.1 UIViewController基础258
8.2.2 实现不同界面之间的跳转
处理258
8.2.3 基于Swift使用UIViewController
控件260
8.3 使用UINavigationController265
8.3.1 导航栏、导航项和
栏按钮项266
8.3.2 UINavigationController
详解266
8.3.3 在故事板中使用导航
控制器268
8.3.4 实现不同视图的切换270
8.4 选项卡栏控制器274
8.4.1 选项卡栏和选项卡栏项275
8.4.2 在选项卡栏控制器管理的场景
之间共享数据277
8.4.3 UITabBarController使用
详解277
8.4.4 实现不同场景的切换280
8.5 综合使用界面视图控件284
第9章 实现多场景和弹出框293
9.1 多场景故事板基础294
9.2 创建多场景项目295
9.2.1 在故事板中添加场景295
9.2.2 给场景命名297
9.2.3 添加提供支持的视图控制器
子类297
9.2.4 使用#import和@class共享
属性和方法300
9.3 使用第二个视图来编辑第一个视图
中的信息301
第10章 屏幕旋转处理307
10.1 启用界面旋转308
10.2 设计可旋转和可调整大小的界面308
10.2.1 自动旋转和自动调整大小309
10.2.2 调整框架309
10.2.3 切换视图309
10.2.4 使用Interface Builder创建可
旋转和调整大小的界面309
10.2.5 在旋转时调整控件方向313
第11章 声音服务319
11.1 访问声音服务320
11.1.1 声音服务基础320
11.1.2 播放声音文件321
11.2 提醒和震动326
11.2.1 播放提醒音326
11.2.2 使用iOS的提醒功能326
11.3 Media Player框架337
11.3.1 Media Player框架中的类337
11.3.2 使用Media Player播放
视频341
11.4 AV Foundation框架344
11.4.1 准备工作344
11.4.2 使用AV音频播放器344
11.4.3 使用AV录音机345
11.5 图像选择器
UIImagePickerController346
11.5.1 使用图像选择器346
11.5.2 基于Swift语言实现
ImagePicker功能347
11.6 基于Swift实现一个音乐播放器360
第12章 定位处理371
12.1 Core Location框架372
12.1.1 Core Location基础372
12.1.2 使用流程372
12.2 获取位置375
12.2.1 位置管理器委托375
12.2.2 处理定位错误376
12.2.3 位置精度和更新过滤器377
12.2.4 获取航向378
12.3 地图功能379
12.3.1 Map Kit基础379
12.3.2 为地图添加标注380
12.4 在屏幕中实现一个定位系统381
12.4.1 设计界面382
12.4.2 具体编码383
12.5 使用谷歌地图386
12.5.1 添加打开地图功能387
12.5.2 升级视图控制器389
12.5.3 添加自定义地图标注对象391
第13章 与互联网接轨393
13.1 UIWebView控件394
13.1.1 UIWebView基础394
13.1.2 显示指定的网页394
13.1.3 控制屏幕中的网页396
13.1.4 加载显示PDF、Word和
JPEG图片398
13.1.5 在网页中加载HTML
代码400
13.1.6 触摸网页数据401
13.2 实现一个简单的网页浏览器405
13.3 基于Swift使用UIWebView
控件409
第14章 与硬件之间的操作415
14.1 加速计和陀螺仪416
14.1.1 加速计基础416
14.1.2 陀螺仪421
14.1.3 检测倾斜和旋转421
14.2 访问朝向和运动数据427
14.2.1 两种方法427
14.2.2 检测朝向演练429
14.3 基于Swift使用Motion传感器432
第15章 开发通用的项目程序435
15.1 开发通用的应用程序436
15.1.1 在iOS 6中开发通用的应用
程序436
15.1.2 在iOS 7、iOS 8中开发通用
应用程序437
15.1.3 图标文件447
15.1.4 启动图像448
15.2 使用模板创建通用的应用程序448
15.2.1 创建项目448
15.2.2 设计界面449
15.2.3 创建并连接输出口450
15.2.4 实现应用程序逻辑450
15.3 使用视图控制器451
15.3.1 创建项目452
15.3.2 设计界面453
15.3.3 创建并连接输出口453
15.3.4 实现应用程序逻辑454
15.3.5 生成应用程序454
15.4 使用多个目标455
15.4.1 将iPhone目标转换为iPad
目标455
15.4.2 将iPad目标转换为iPhone
目标456
第16章 游戏开发457
16.1 Sprite Kit框架基础458
16.1.1 Sprite Kit的优点和缺点458
16.1.2 Sprite Kit、Cocos2D、Cocos2D-X
和Unity的选择458
16.1.3 开发一个Sprite Kit游戏
程序458
16.2 基于Swift开发一个四子棋游戏470
第17章 读写应用程序的数据481
17.1 iOS应用程序和数据存储482
17.2 用户默认设置482
17.3 设置束484
17.4 iCloud存储485
17.5 使用SQLite 3存储和读取数据486
17.6 核心数据491
17.6.1 Core Data基础491
17.6.2 Core Data的基本架构493
17.6.3 托管对象和托管对象模型496
17.6.4 在iOS中使用Core Data497
17.7 互联网数据501
17.7.1 XML和JSON502
17.7.2 使用JSON获取网站中的照片
信息505
第18章 HealthKit开发详解509
18.1 HealthKit基础510
18.1.1 HealthKit介绍510
18.1.2 市面中的HealthKit应用
现状510
18.1.3 接入HealthKit的好处511
18.2 HealthKit开发基础512
18.2.1 开发要求512
18.2.2 HealthKit开发思路512
18.3 实战演练——检测一天消耗掉的
能量513
第19章 HomeKit开发详解529
19.1 HomeKit基础530
19.1.1 HomeKit对格局的作用530
19.1.2 市场策略和发展机遇531
19.1.3 HomeKit硬件标准531
19.2 HomeKit开发基础532
19.2.1 HomeKit应用程序的层次
模型532
19.2.2 HomeKit程序架构模式533
19.2.3 HomeKit中的类535
19.3 实战演练——实现一个HomeKit
控制程序536
第20章 WatchKit开发详解555
20.1 Apple Watch介绍556
20.2 WatchKit开发基础557
20.2.1 搭建WatchKit开发环境558
20.2.2 WatchKit架构561
20.2.3 WatchKit布局563
20.2.4 Glances和Notifications563
20.2.5 Watch App的生命周期564
20.3 开发Apple Watch应用程序565
20.3.1 创建Watch应用566
20.3.2 创建Glance界面566
20.3.3 自定义通知界面567
20.3.4 配置Xcode项目567
20.4 实战演练——实现AppleWatch界面
布局570
20.5 实战演练——显示地图、网页
和单元格574
第21章 多功能音乐盒系统577
21.1 系统介绍578
21.1.1 功能介绍578
21.1.2 模块划分578
21.2 系统主界面579
21.3 音乐库581
21.3.1 音乐库主界面582
21.3.2 歌曲表视图控制器584
21.3.3 开关控制器589
21.3.4 专辑模块592
21.3.5 歌曲信息模块597
21.3.6 正在播放模块599
21.4 在线搜索604
21.5 MV播放614
21.5.1 主界面614
21.5.2 视图刷新621
21.5.3 MV信息622
21.5.4 MV搜索623
21.5.5 Hot MV624
內容試閱
第2章 Objective-C语言基础
在最近几年中,因为苹果产品iPhone、iPad在销量方面取得了重大成功,使得苹果开发语言Objective-C从众多编程语言中脱颖而出,以非常规的速度在编程语言排行榜中迅速攀升,取得了骄人的战绩。
在本章的内容中,将带领读者初步认识Objective-C这门神奇的编程语言,为步入本书后面知识的学习打下基础。
2.1 Objective-C语言基础
在过去的几年中,Objective-C的占有率连续攀升,截至2014年5月,成为仅次于C、Java之后的一门编程语言。
本节将带领读者一起探寻Objective-C如此火爆的秘密。
2.1.1 TIOBE编程语言社区排行榜
在程序开发领域中,TIOBE编程语言社区排行榜是编程语言流行趋势的一个指标,每月更新。这份排行榜的排名是基于互联网上有经验的程序员、课程和第三方厂商的数量。排名使用著名的搜索引擎如Google、MSN、雅虎以及Wikipedia和YouTube进行计算。注意,这个排行榜只是反映某种编程语言的热门程度,并不能说明一门编程语言好不好,或者一门语言所编写的代码数量多少。
表2-1是截止到2014年5月TIOBE的统计数据。
表2-1 编程语言排行榜截止到2014年5月
2014年排名
2013年排名
语 言
2012年占有率%
与2011年相比%
1
1
C
17.631
-0.23
2
2
Java
17.348
-0.33
3
4
Objective-C
12.875
+3.28
4
3
C++
6.137
-3.58
5
5
C#
4.820
-1.33
从表中可以看出,与以前月份的统计数据相比,前三名的位置有所变动,例如Objective-C取代了C++的第三名位置。作为2011年还在十名开外的Objective-C来说,在短时间内取得如此骄人的战绩是十分可贵的。这主要归功于iPhone和iPad的持续成功,这两种设备上的程序主要都是由Objective-C实现的。
2.1.2 Objective-C介绍
Objective-C是苹果Mac OS X系统上开发的首选语言。Mac OS X技术来源于NextStep的OpenStep操作系统,而OpenStep的软件架构都是用Objective-C语言编写的。这样,Objective-C就理所当然地成为Mac OS X上的最佳语言。
Objective-C诞生于1986年,Brad Cox在第一个纯面向对象语言Smalltalk的基础上写成了Objective-C语言。后来,Brad Cox创立了StepStone公司,专门负责Objective-C语言的推广。
1988年,Steve Jobs的NextStep采用Objective-C作为开发语言。
1992年,在GNU GCC编译器中包含了对Objective-C的支持。在这以后相当长的时间内,Objective-C语言得到了很多程序员的认可,并且他们很多人是编程界的鼻祖和大碗,例如Richard Stallman、Dennis Glating等人。
Objective-C通常被写为ObjC、Objective C或Obj-C,是一门扩充了C语言的面向对象编程语言。
Objective-C语言推出后,主要被用在如下两个使用OpenStep标准的平台上面:
* Mac OS X。
* GNUstep。
除此而外,在NextStep和OpenStep中,Objective-C语言也是被作为基本语言来使用的。在GCC运作的系统中,可以实现Objective-C的编写和编译操作,因为GCC包含Objective-C的编译器。
2.1.3 iOS选择Objective-C的原因
iOS选择Objective-C作为开发语言,有许多方面的原因,具体来说,有如下4点。
1面向对象
Objective-C语言是一门面向对象的语言,功能十分强大。在Cocoa框架中的很多功能,只能通过面向对象的技术来呈现,所以,Objective-C一开始就是为了满足面向对象的需求而设计的。
2融合性好
从严格意义上讲,Objective-C语言是标准C语言的一个超集。当前使用的C程序无须重新开发,就可以使用Cocoa软件框架,开发者可以在Objective-C中使用C的所有特性。
3简单易用
Objective-C是一种简洁的语言,它语法简单,易于学习。但是另一方面,因为易于混淆的术语以及抽象设计的重要性,对于初学者来说,可能学习面向对象编程的过程比较漫长。要想学好Objective-C这种结构良好的语言,需要付出很多汗水和精力。
4动态机制支持
Objective-C与其他的基于标准C语言的面向对象语言相比,对动态的机制支持更为彻底。专业的编译器为运行环境保留了很多对象本身的数据信息,所以在编译某些程序时,可以将选择推迟到运行时来决定。正是基于此特性,使得基于Objective-C的程序非常灵活和强大。例如,Objective-C的动态机制提供了如下两个比普通面向对象语言更好的优点。
* Objective-C语言支持开放式的动态绑定:这有助于交互式用户接口架构的简单化。例如,在Objective-C程序中发送消息时,不但无须考虑消息接收者的类,而且也无须考虑方法的名字。这样,可以允许用户在运行时再做出决定,也给开发人员带来了极大的设计自由。
* Objective-C语言的动态机制成就了各种复杂的开发工具:运行环境提供了访问运行中程序数据的接口,所以使得开发工具监控Objective-C程序成为可能。
2.1.4 Objective-C的优点和缺点
Objective-C是一门非常“实际”的编程语言,它使用一个用C写成的很小的运行库,只会令应用程序的大小增加很小,这与大部分OO面向对象系统那样使用极大的VM虚拟机执行时间来取代整个系统的运作相反。Objective-C写成的程序通常很小。
Objective-C的最初版本并不支持垃圾回收。在当时,这是人们争论的焦点之一,很多人考虑到Smalltalk回收会产生漫长的“死亡时间”,从而令整个系统失去功能。Objective-C为避免这个问题,所以不再拥有这个功能。虽然在某些第三方版本中已加入这个功能尤是GNUstep,但是,Apple在其Mac OS X中仍未引入这个功能。不过令人欣慰的是,在Apple发布的Xcode 4中,开始支持自动释放,虽然不敢鲁莽地说那是垃圾回收,因为毕竟两者机制不同。在Xcode 4中的自动释放,也就是ARCAutomatic Reference Counting机制,是不需要用户手动去Release释放一个对象,而是在编译期间,编译器会自动帮我们添加那些以前经常写的[NSObject release]。
还有另外一个问题,Objective-C不包含命名空间机制,取而代之的是程序设计师必须为其类别名称加上前缀,这样经常会导致冲突。在2004年,在Cocoa编程环境中,所有Mac OS X类和函数均有NS作为前缀,例如NSObject或NSButton,来清楚地分辨它们属于Mac OS X核心;使用NS是由于这些类别的名称是在NextStep开发时定下的。
虽然Objective-C是C语言的母集,但它也不视C语言的基本类型为第一级的对象。与C++不同,Objective-C不支持运算符重载。虽然与C++不同,但是与Java相同,Objective-C只容许对象继承一个类别不设多重继承。Categories和Protocols不但可以提供很多多重继承的好处,而且没有很多缺点,例如,额外执行时间过重和二进制不兼容。
由于Objective-C使用动态运行时类型,而且所有的方法都是函数调用,有时甚至连系统调用syscalls也是如此,所以,很多常见的编译时性能优化方法都不能应用于Objective-C,例如内联函数、常数传播、交互式优化、纯量取代与聚集等。这使得Objective-C性能劣于类似的对象抽象语言,例如C++。不过Objective-C的拥护者认为,既然Objective-C运行时消耗较大,Objective-C本来就不应该应用于C++或Java常见的底层抽象。
2.2 第一段Objective-C程序
在本节的内容中,将首先通过Xcode 6.1编写一段Objective-C程序,然后讲解这段程序的各个构成元素的基本知识,为读者步入本书后面知识的学习打下基础。
2.2.1 使用Xcode编辑代码
Xcode是一款功能全面的应用程序开发工具,通过此工具,可以输入、编译、调试并执行Objective-C程序。如果想在Mac上快速开发Objective-C应用程序,则必须学会使用这个强大的工具的方法。在本章前面的章节中,已经介绍了安装并搭建Xcode工具环境的流程,接下来,将简单介绍使用Xcode编辑Objective-C代码的基本方法。
1Xcode位于Developer文件夹的Applications子文件夹中,快捷图标如图2-1所示。
图2-1 Xcode图标
2启动Xcode,在File菜单下选择New Project命令,如图2-2所示。
图2-2 新建一个项目
3此时,会出现一个窗口,如图2-3所示。
图2-3 选择应用程序类型
4在Choose a template for your new project窗口的左侧,显示了可供选择的模板类别,因为我们的重点是类别iOS Application,所以在此需要确保选择了它。而在右侧,显示了当前类别中的模板以及当前选定模板的描述。就这里而言,应单击Empty Application空应用程序模板,再单击Next下一步按钮,如图2-4所示。
5单击Choose按钮打开一个新窗口,如图2-5所示。
6在此,将前面的程序命名为“prog1”,保存在本地机器中后,在Xcode中的编辑界面如图2-6所示。
图2-4 单击Empty Application空应用程序模板
图2-5 打开一个新窗口
图2-6 Xcode prog1项目窗口
7此时,在Xcode 6.1创建的工程中编写Objective-C代码,这段代码的功能是在屏幕上显示“first Programming!”短语。将这段程序保存为“prog1.m”,具体代码如下所示:
显示短语
#import FoundationFoundation.h
int mainint argc, const char *argv[l
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSLog@"first Programming!";
[pool drain];
return 0;
}
对于上述程序,我们可以使用Xcode编译并运行程序,或者使用GNU Objective-C编译器在Terminal窗口中编译并运行程序。Objective-C程序最常用的扩展名是“.m”,然后可以使用Xcode打开。
当在Xcode中打开上面创建的第一段Obiective-C代码first.m时,不必关注屏幕上为文本显示的各种颜色。Xcode使用不同的颜色指示值、保留字等内容。
8接下来开始编译并运行第一个程序,但是,首先需要保存上述程序,方法是从File菜单中选择Save命令。如果在未保存文件的情况下尝试编译并运行程序,Xcode会询问是否需要保存。在Build菜单下,可以选择Build或Build and Run命令。在此选择后者,因为如果构建时不会出现任何错误,则会自动运行此程序。也可点击工具栏中出现的Build and Go图标工具按钮。
Build and Go意味着“构建,然后执行上次最后完成的操作”,可能是Run、Debug、Run with Shark或Instruments等。首次为项目使用此图标工具按钮时,Build and Go意味着构建并运行程序,所以,此时使用这个操作没有问题。但是一定要知道Build and Go与Build and Run之间的区别。
如果程序中有错误,在此步骤期间,会看到列出的错误消息。如果情况如此,可回到程序中解决错误问题,然后再次重复此过程。解决程序中的所有错误后,会出现一个新窗口,其中显示prog1 - Debugger Console。如果该窗口没有自动出现,可进入主菜单栏,并从Run菜单中选择Console命令,这样就能显示了。
注意:在Objective-C中,小写字母和大写字母是有区别的。Objective-C并不关心程序行在何处开始输入,程序行的任何位置都能输入语句。基于此,我们可以开发容易阅读的程序。
在接下来的内容中,将详细讲解上述Objective-C程序各个构成元素的基本知识。
2.2.2 注释
接下来开始分析文件first.m,程序的第一行是:
显示短语
上述代码表示一段注释,在程序中使用的注释语句用于说明程序并增强程序的可读性。注释负责告诉该程序的读者,不管是程序员还是其他负责维护该程序的人,这只是程序员在编写特定程序和特定语句序列时的想法。一般首行注释用来描述整个程序的功能。
在Objective-C程序中,有如下两种插入注释的方式。
* 第一种:使用两个连续的斜杠“”,在双斜杠后直到这行结尾的任何字符都将被编译器忽略。
* 第二种:使用“*…*”注释的形式,在斜杆和星号中间不能插入任何空格。“*”表示开始,“*”表示结束,在两者之间的所有字符都被视为注释语句的一部分,从而被Objective-C编译器忽略。
当注释需要跨越很多程序行时,通常使用这种注释格式,例如下面的代码:
*
这是注释,因为很长很长很长很长很长很长的,
所以得换行,
功能是显示一行文本。
如果不明白可以联系作者:
xxxx@yahoo.com
*
在编写程序或者将其键入到计算机中时,应该养成在程序中插入注释的习惯。使用注释有如下两个好处。
1当特殊的程序逻辑在我们的大脑中出现时就说明程序,要比程序完成后再回来重新思考这个逻辑简单得多。
2通过在工作的早期阶段把注释插入程序中,在调试阶段隔离和调试程序逻辑错误时将会受益匪浅。注释不仅可以帮助人们理解程序,而且还有助于指出逻辑错误的根源。
2.2.3 #import指令
我们继续分析程序,看接下来的代码:
#import FoundationFoundation.h
该#import指令的功能,是告诉编译器找到并处理名为Foundation.h的文件,这是一个系统文件,表示这个文件不是我们创建的。
#import表示将该文件的信息导入或包含到程序中,这个功能像把此文件的内容键入到程序中。例如上述代码可以导入文件Foundation.h。
在Objective-C语言中,编译器指令以@符号开始,这个符号经常用于使用类和对象的情况。在表2-2中,对Objective-C语言中的指令进行了总结。
表2-2 编译器指令
指 令
含 义
例 子
@“chars”
实现常量NSSTRING字符串对象相邻的字符串已连接
NSString *url = @“http:
www.kochan-wood.com”;
@class c1, c2, ...
将c1、c2…声明为类
@class Point, Rectangle;
@defs class
该指令为class返回一个结构变量的列表
struct Fract
{ @defsFraction; }
*fractPtr;
fractPtr = struct Fract *
[[Fraction alloc] init];
续表
指 令
含 义
例 子
@dynamic names
用于names的存取器方法,可动态提供
@dynamic drawRect;
@encodetype
将字符串编码为type类型
@encodeint*
@end
结束接口部分、实现部分或协议部分
@end
@implementation
开始一个实现部分
@implementation Fraction;
@interface
开始一个接口部分
@interface Fraction:
Object Copying
@private
定义一个或多个实例变量的作用域
例如定义实例变量
@protected
定义一个或多个实例变量的作用域
@public
定义一个或多个实例变量的作用域
@propertylist names
为names声明list中的属性
propertyretain, nonatomic
NSSTRING *name;
@protocolprotocol
为指定protocol创建一个Protocol对象
@protocolCopying]{...}
if [myObj conformsTo: protocol
@protocol name
开始name的协议定义
@protocol Copying
@selectormethod
指定method的SEL选择对象
if [myObj respondsTo: @selectorallocF] {...}
@synchronized object
通过单线程开始一个块的执行。Object已知是一个互斥mutex的旗语
@synthesize names
为names生成存取器方法,如果未提供的话
@synthesize name, email;参见“实例变量”
@try
开始执行一个块,以捕捉异常
例如“异常处理”应用
@catchexception
开始执行一个块,以处理exception
@finally
开始执行一个块,不管上面的@try块是否抛出异常,都会执行
@throw
抛出一个异常
2.2.4 主函数
接下来看如下剩余的代码:
int mainint argc, const char *argv[]
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSLog@"first Programming!";
[pool drain];
return 0;
}
上述代码都被包含在函数main中,此函数与C语言中的同名函数类似,是整个程序的入口函数。上述代码功能是指定程序的名称为main,这是一个特殊的名称,功能是准确地表示程序将要在何处开始执行。在main前面的保留关键字int用于指定main返回值的类型,此处用int表示该值为整型在本书后面的章节中,将更加详细地讨论类型问题。
在上述main代码块中包含了多条语句。我们可以把程序的所有语句放入一对花括号中,最简单的情形是:一条语句是一个以分号结束的表达式。系统将把位于花括号中的所有程序语句看作main例程的组成部分。首先看如下第一条语句:
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
上述语句为自动释放池在内存中保留了空间。作为模板的一部分,Xcode会将这行内容自动放入程序中。
接下来的一条语句用于指定要调用名为NSLog的例程,传递或传送给NSLog例程的参数或实参是如下字符串:
@"first Programming!"
此处的符号@位于一对双引号的字符串前面,这被称为常量NSString对象。NSString例程是Objective-C库中的一个函数,它只能显示或记录其参数。但是之前它会显示该例程的执行日期和时间、程序名以及其他在此不会介绍的数值。在本书的后面的内容中,不会列出NSLog在输出前面插入的这些文本。
在Objective-C中,所有的程序语句必须使用分号“;”结束,这也是为什么分号在NSLog调用的结束圆括号之后立即出现的原因。在退出Objective-C程序之前,应该立即释放已分配的内存池和与程序相关联的对象,例如,使用类似于下面的语句可以实现:
[pool drain];
注意:Xcode会在程序中自动插入此行内容。
在函数main中的最后一条语句是:
return 0;
上述语句的功能,是终止main的运行,并且返回状态值0。在Objective-C程序中规定,0表示程序正常结束。任何非零值通常表示程序出现了一些问题,例如无法找到程序所需要的文件。
如果使用Xcode进行调试,会在Debug Console窗口中发现,在NSLog输出的行后显示下面的提示:
The Debugger has exited with status 0.
假如修改上面的程序,修改后能够同时显示文本“Objective-C OK”。要想实现这个功能,可以简单地通过添加另一个对NSLog例程调用的方法来实现,例如使用下面的代码:
#import FoundationFoundation.h
int mainint argc, const char *argv[]
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSLog@"first Programming!";
NSLog@"Objective-C OK!";
[pool drain];
return 0;
}
在编写上述代码时,必须使用分号结束每个Objective-C程序语句。执行后会输出:
first Programming!
Objective-C OK!
而在下面的代码中可以看到,无须为每行输出单独调用NSLog例程:
#import FoundationFoundation.h
int mainint argc, const char *argv[]
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];

NSLog@"look...\n..1\n...2\n....3";
[pool drain];
return 0;
}
在上述代码中,首先看看特殊的两字符序列。“\n”中的反斜杠和字母是一个整体,合起来表示换行符。换行符的功能,是通知系统要准确完成其名称所暗示的转到一个新行的工作。任何要在换行符之后输出的字符,随后将出现在显示器的下一行。其实,换行符非常类于HTML标记中的换行标记br。执行上述代码后,会输出:
look...
..1
...2
....3
2.2.5 显示变量的值
在Objective-C程序中,通过NSLog不仅可以显示简单的短语,而且还能显示定义的变量值并计算结果。例如,在下面的代码中,使用NSLog显示了10+20的结果:
#import FoundationFoundation.h
int mainint argc, const char *argv[]
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
int sum;

sum = 10 + 20;

NSLog@"The sum of 10 and 20 is %i", sum;
[pool drain];
return 0;
}
对于上述代码的具体说明如下。
1函数main中,第一条语句为自动释放池在内存中保留了空间。然后将变量sum定义为整型。在Objective-C程序中,使用所有程序变量前,必须先定义它们。定义变量的目的,是告诉Objective-C编译器程序将如何使用这些变量。编译器需要确保这些信息生成正确的指令,便于将值存储到变量中,或者从变量中检索值。被定义成int类型的变量只能够存储整型值,例如3、4、-10和0都是整型值,也就是说,没有小数位的值是整型值。而带有小数位的数,例如2.34、2.456和27.0等,被称为浮点数,它们都是实数。
2整型变量sum的功能是存储整数10+20的和。在编写上述代码时,故意在定义这个变量的下方预留了一个空行,这样做的目的,是在视觉上区分例程的变量定义和程序语句这种做法是一个良好的风格,在很多时候,在程序中添加单个空白行,能够使程序的可读性更强。
3代码“sum = 10 + 20;”表示10和20相加,并把结果存储使用赋值运算符或等号到变量sum中。
4NSLog语句调用了圆括号中的两个参数,这两个参数用逗号隔开。NSLog语句的第一个参数总是要显示的字符串。然而,在显示字符串的同时,通常还希望显示某些程序变量的值。在上述代码中,希望在显示字符之后还要显示变量sum的值:
The sum of 50 and 25 is %i
第一个参数中的百分号是一个特殊字符,它可以被函数NSLog识别。紧跟在百分号后的字符指定在这种情况下将要显示的值类型。在该程序中,字母i被NSLog例程识别,表示将要显示的是一个整数。只要NSLog例程在字符串中发现字符“%i”,都将自动显示例程第二个参数的值。因为sum是NSLog的下一个参数,所以它的值将在显示字符“The sum of 10 and 20 is ”之后自动显示。
该程序代码执行后,会输出如下内容:
The sum of 10 and 20 is 30
2.3 数据类型和常量
其实,在本章前面的第一段代码中,我们已经接触过Objective-C的基本数据类型int,例如,声明为int类型的变量只能用于保存整型值,也就是说,没有小数位的值。其实,除了int类型外,在Objective-C中还有另外3种基本数据类型,分别是float、double和char,具体说明如下所示。
* float:用于存储浮点数即包含小数位的值。
* double:与float类型一样,但是前者的精度约是后者精度的两倍。
* char:可以存储单个字符,例如字母a,数字字符100,或者一个分号“;”。
在Objective-C程序中,任何数字、单个字符或者字符串通常称为常量。例如,数字88表示一个常量整数值。字符串@“Programming in Objective-C”表示一个常量字符串对象。在Objective-C程序中,完全由常量值组成的表达式被称为常量表达式。例如,下面的表达式就是一个常量表达式,因为此表达式的每一项都是常量值:
128 + 1 – 2
如果将i声明为整型变量,那么,下面的表达式就不是一个常量表达式:
128 + 1 – i
在Objective-C中,定义了多个简单或基本的数据类型,例如,int表示整数类型,这就是一种简单的数据类型,而不是复杂的对象。
注意:虽然Objective-C是一门面向对象的语言,但是,简单数据类型并不是面向对象的。它们类似于其他大多数非面向对象语言比如C语言的简单数据类型。在Objective-C中,提供简单数据类型的原因,是出于效率方面的考虑,另外,与Java语言不同,Objective-C的整数大小是根据执行环境的规定而变化的。
2.3.1 int类型
在Objective-C程序中,整数常量由一个或多个数字的序列组成。序列前的负号表示该值是一个负数,例如值88、-10和100都是合法的整数常量。Objective-C规定,在数字中间不能插入空格,并且不能用逗号来表示大于999的值。所以数值12,000就是一个非法的整数常量,写成12000才是正确的。
在Objective-C中有两种特殊的格式,它们用一种非十进数基数10的基数来表示整数常量。如果整型值的第一位是0,那么,这个整数将用八进制计数法来表示,就是说,用基数8来表示。在这种情况下,该值的其余位必须是合法的8进制数字,必须是0~7之间的数字。因此,在Objective-C中,以8进制表示的值50等价于10进制的值40,表示方式为050。与此类似,八进制的常量0177表示十进制的值1271×64+7×8+7。通过在NSLog调用的格式字符串中使用格式符号%o,可以在终端上用八进制显示整型值。在这种情况下,使用八进制显示的值不带有前导0。而格式符号%#o将在八进制值的前面显示前导0。
如果整型常量以0和字母x无论是小写字母还是大写字母开头,那么,这个值都将用十六进制以16为基数计数法来表示。紧跟在字母x后的是十六进制值的数字,可以由0~9之间的数字和a~f或A~F之间的字母组成。字母表示的数字分别为10~15。假如要给名为RGBColor的整型常量指派十六进制的值FFEF0D,则可以使用如下代码来实现:
RGBColor = 0xFFEF0D;
在程序代码中,符号%x将用十六进制格式显示一个值,该值不带前导的0x并用a~f之间的小写字符表示十六进制数字。要使用前导0x显示这个值,需要使用格式字符%#x,例如下面的代码:
NSlog"Color is %#X\n", RGBColor;
该代码中,通过“%#X”中的大写字母X可以显示前导的0x,然后用大写字母表示十六进制数。
无论是字符、整数还是浮点数,每个值都有与其对应的值域。此值域与为存储特定类型的值而分配的内存变量有关。大多数情况下,在Objective-C中都没有规定值域的具体范围,因为它通常依赖于所运行的计算机,所以叫作设备或机器相关量。例如,一个整数在计算机上既可以占用32位空间,也可以使用64位空间来存储。
另外,在任何编程语言中,都预留了一定数量的标识符,这些标识符是不能被定义变量和常量的。
表2-3中,列出了Objective-C程序中具有特殊含义的标识符。
表2-3 特殊的预定义标识符
标 识 符
含 义
_cmd
在方法内自动定义的本地变量,它包含该方法的选择程序
__func__
在函数内或包含函数名或方法名的方法内自动定义的本地字符串变量
BOOL
Boolean值,通常以YES和NO的方式使用
Class
类对象类型
id
通用对象类型
IMP
指向返回id类型值的方法的指针
nil
空对象
Nil
空类对象
NO
定义为BOOL 0
NSObject
定义在FoundationNSObject.h中的根Foundation对象
Protocol
存储协议相关信息的类的名称
SEL
已编译的选择程序
self
在用于访问消息接收者的方法内自动定义的本地变量
super
消息接收者的父类
YES
定义为BOOL 1
2.3.2 float类型
在Objective-C程序中,float类型的变量可以存储有小数位的值。由此可见,通过查看是否包含小数点,就可以区分出一个数是否为浮点常量。
在Objective-C程序中,不但可以省略小数点之前的数字,而且也可以省略小数点之后的数字,但是,不能将它们全部省略。例如3.、125.8及-.0001等,都是合法的浮点常量。要想显示浮点值,可用NSLog转换字符%f。
另外,在Objective-C程序中,也能使用科学计数法来表示浮点常量。例如1.5e-4就是使用这种计数法来表示的浮点值,它表示1.5×10-4。位于字母e前的值称为尾数,而位于字母e后的值称为指数。指数前面可以放置正号或负号,指数表示将与尾数相乘的10的幂。因此,在常量2.85e-3中,2.85是尾数值,而-3是指数值。该常量表示值2.85×10-3,或0.00285。
另外,在Objective-C程序中,不但可用小写字母书写用于分隔尾数和指数的字母e,而且也可以用大写字母来书写。
在Objective-C程序中,建议在NSLog格式字符串中指定格式字符%e。使用NSLog格式字符串%g时,允许NSLog确定使用常用的浮点计数法还是使用科学计数法来显示浮点值。当值小于-4或大于5时,采用%e科学计数法表示,否则采用%f浮点计数法。
十六进制的浮点常量包含前导的0x或0X,在后面紧跟一个或多个十进制或十六进制数字,然后紧接着是p或P,最后是可以带符号的二进制指数。例如,0x0.3p10表示的值为316×210=192。
2.3.3 double类型
在Objective-C程序中,类型double与类型float类似。Objective-C规定,当在float变量中所提供的值域不能满足要求时,需要使用double变量来实现需求。声明为double类型的变量可以存储的位数,大概是float变量所能存储的两倍多。在现实应用中,大多数计算机使用64位来表示double值。除非另有特殊说明,否则,Objective-C编译器会将全部浮点常量当作double值来对待。要想清楚地表示float常量,需要在数字的尾部添加字符f或F,例如:
12.4f
要想显示double的值,可以使用格式符号%f、%e或%g来辅助实现,它们与显示float值所用的格式符号是相同的。其实,double类型和float类型可以被称为实型。在Objective-C语言中,实型数据分为实型常量和实型变量。
1.实型常量
实型常量也称为实数或者浮点数。在Objective-C语言中,它有两种形式,即小数形式和指数形式。
* 小数形式:由数字0~9和小数点组成。例如0.0、25.0、5.789、0.13、5.0、300.、-267.8230等,均为合法的实数。注意,必须有小数点。在NSLog上,使用%f格式来输出小数形式的实数。
* 指数形式:由十进制数,加阶码标志e或E以及阶码只能为整数,可以带符号组成。其一般形式为aEna为十进制数,n为十进制整数。其值为a×10n。在NSLog上,使用%e格式来输出指数形式的实数。
例如,下面是一些合法的实数:
2.1E5等于2.1×105
3.7E-2等于3.7×10-2
而下面是不合法的实数:
345无小数点
E7阶码标志E之前无数字
-5无阶码标志,无小数点
53.-E3负号位置不对
2.7E无阶码
Objective-C允许浮点数使用后缀,后缀为f或F即表示该数为浮点数。例如,356.4f和356.4F是等价的。
2.实型变量
1实型数据在内存中的存放形式
实型数据一般占4个字节32位内存空间,按指数形式存储。小数部分占的位bit数越多,数的有效数字就越多,精度就越高。指数部分占的位数越多,则能表示的数值范围就越大。
2实型变量的分类
实型变量分为单精度float型、双精度double型和长双精度long double型三类。在大多数计算机中,单精度型占4个字节32位内存空间,其数值范围为3.4E-38 ~ 3.4E+38,只能提供7位有效数字。双精度型占8个字节64位内存空间,其数值范围为1.7E-308~ 1.7E+308,可提供16位有效数字。
2.3.4 char类型
在Objective-C程序中,char类型变量的功能是存储单个字符,只要将字符放到一对单引号中,就能得到字符常量。例如‘a’、‘;’和‘0’都是合法的字符常量。其中,‘a’表示字母a,‘;’表示分号,‘0’表示字符0并不等同于数字0。
在Objective-C程序中,不能把字符常量与C风格的字符串混为一谈,字符常量是放在单引号中的单个字符;而字符串则是放在双引号中的任意个数的字符,不但要求在前面有@字符,而且要求放在双引号中的字符串才是NSString字符串对象。
另外,字符常量‘\n’即换行符是一个合法的字符常量,虽然这看似与前面提到的规则相矛盾。出现这种情况的原因是,反斜杠符号是Objective-C中的一个特殊符号,其实并不把它看成一个字符。也就是说,Objective-C编译器仅仅将‘\n’看作是单个字符,尽管它实际上由两个字符组成。这些特殊字符都是由反斜杠字符开头的。
在NSLog调用中,可以使用格式字符%c来显示char变量的值。例如,在下面的程序中,使用了基本的Objective-C数据类型:
#import FoundationFoundation.h
int mainint argc, char *argv[]
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
int integerVar = 50;
float floatingVar = 331.79;
double doubleVar = 8.44e+11;
char charVar = ''W'';
NSLog @"integerVar = %i", integerVar;
NSLog @"floatingVar = %f", floatingVar;
NSLog @"doubleVar = %e", doubleVar;
NSLog @"doubleVar = %g", doubleVar;
NSLog @"charVar = %c", charVar;
[pool drain];
return 0;
}
在上述代码中,函数内第3行floatingVar的值是331.79,但实际显示为331.790009。这是因为,实际显示的值是由使用的特定计算机系统决定的。出现这种不准确值的原因,是计算机内部使用特殊的方式表示数字。
例如,当使用计算器处理数字时,很可能遇到这类不准确性。如果用计算器计算1除以3,将得到结果.33333333,很可能结尾带有一些附加的3。这串3是计算器计算13的近似值。理论上,应该存在无限个3。然而,该计算器只能保存这些位的数字,这就是计算机的不确定性。
此处应用了相同类型的不确定性:在计算机的内存中,不能精确地表示一些浮点值。
执行上述代码后,会输出:
integerVar = 50
floatingVar = 331.790009
doubleVar = 8.440000e+11
doubleVar = 8.44e+11
charVar = ''W''
另外,使用char也可以表示字符变量。字符变量类型定义的格式和书写规则都与整型变量相同,例如下面的代码:
char a, b;
每个字符变量被分配一个字节的内存空间,因此,只能存放一个字符。字符值是以ASCII码的形式存放在变量的内存单元中的。如x的十进制ASCII码是120,y的十进制ASCII码是121。下面的例子是为字符变量a、b分别赋予‘x’和‘y’:
a = ''x'';
b = ''y'';
这实际上是在a、b两个内存单元中存放120和121的二进制代码。我们可以把字符值看成是整型值。Objective-C语言允许为整型变量赋字符值,也允许为字符变量赋整型值。在输出时,允许把字符变量按整型量输出,也允许把整型量按字符量输出。整型量为多字节量,字符量为单字节量,当整型量按字符型量处理时,只有低8位字节参与处理。
2.3.5 字符常量
在Objective-C程序中,字符常量是用单引号括起来的一个字符,例如,下面列出的都是合法的字符常量:‘a’、‘b’、‘=’、‘+’、‘?’。
Objective-C中的字符常量有如下4个特点。
1字符常量只能用单引号括起来,不能用双引号或其他括号。
2字符常量只能是单个字符,不能是字符串。转义字符除外。
3字符可以是字符集中的任意字符。但数字被定义为字符型后,就不能参与数值运算了。如‘5’和5是不同的。‘5’是字符常量,不能参与整数运算。
4Objective-C中的字符串形式不是“abc”,而是@“abc”。
转义字符是一种特殊的字符常量。转义字符以反斜线“\”开头,后面紧跟一个或几个字符。转义字符具有特定的含义,不同于字符原有的意义,故称“转义”字符。例如,“\n”就是一个转义字符,表示“换行”。转义字符主要用来表示那些用一般字符不便于表示的控制代码。常用的转义字符及其含义如表2-4所示。
表2-4 常用的转义字符及其含义
转义字符
转义字符的意义
ASCII码
\n
回车换行
10
\t
横向跳到下一制表位置
9
\b
退格
8
续表
转义字符
转义字符的意义
ASCII码
\r
回车
13
\f
走纸换页
12
\反斜线符“\”
92
\''
单引号符
39
\"
双引号符
34
\a
鸣铃
7
\ddd
1~3位八进制数所代表的字符
\xhh
1~2位十六进制数所代表的字符
在大多数情况下,Objective-C字符集中的任何一个字符都可以使用转义字符来表示。在上述表2-4中,ddd和hh分别为八进制和十六进制的ASCII码,表中的\ddd和\xhh正是为此而提出的。例如,\101表示字母A,\102表示字母B,\134表示反斜线,\XOA表示换行等。我们来看下面的例子:
#import FoundationFoundation.h
int mainint argc, const char *argv[]
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
char a = 120;
char b = 121;
NSLog@"%c, %c", a, b;
NSLog@"%i, %i", a, b;
[pool drain];
return 0;
}
在上述代码中,定义a、b为字符型,但在赋值语句中赋以整型值。从结果看,输出a和b值的形式取决于NSLog函数格式串中的格式符。当格式符为“%c”时,对应输出的变量值为字符,当格式符为“%i”时,对应输出的变量值为整数。执行上述代码后输出:
x,y
120,121
2.3.6 id类型
在Objective-C程序中,id是一般对象类型,id数据类型可以存储任何类型的对象。例如,在下面的代码中,将number声明为id类型的变量:
id number;
我们可以声明一个方法,使其具有id类型的返回值。例如,在下面的代码中,声明了一个名为newOb的实例方法,它不但具有名为type的单个整型参数,而且还具有id类型的返回值:
- id newOb: int type;
在此需要注意,对返回值和参数类型声明来说,id是默认的类型。
再如,在下面的代码中,声明了一个返回id类型值的类方法:
+ allocInit;
id数据类型是本书经常使用的一种重要数据类型,是Objective-C中的一个十分重要的特性。在表2-5中,列出了基本数据类型和限定词。
表2-5 Objective-C的基本数据类型
类 型
常量实例
NSlog格式字符
char
‘a’,‘\n’
%c
short int
-4
%hi、%hx、%ho
unsigned short int
5
%hu、%hx、%ho
int
12、-97、0xFFE0、0177
%i、%x、%o
unsigned int
12u、100u、0XFFu
%u、%x、%o
long int
12L、-2001、0xffffL
%li、%lx、%lo
unsigned long int
12UL、100ul、0xffeeUL
%lu、%lx、%lo
long long int
0xe5e5e5e5LL、500ll
%lli、%llx、%llo
unsigned long long int
12ull、0xffeeULL
%llu、%llx、%llo
float
12.34f、3.1e-5f、0x1.5p10、0x1p-1
%f、%e、%g、%a
double
12.34、3.1e-5、0x.1p3
%f、%e、%g、%a
long double
12.431、3.1e-51
%Lf、%Le、%Lg
id
nil
%p
在Objective-C程序中,id类型是一个独特的数据类型,在概念上与Java语言中的Object类相似,可以被转换为任何数据类型。也就是说,在id类型变量中,可以存放任何数据类型的对象。在内部处理上,这种类型被定义为指向对象的指针,实际上,是一个指向这种对象的实例变量的指针。
例如,下面定义了一个id类型的变量和返回一个id类型的方法:
id anObject;
- id new: int type;
id和void*并非完全一样,下面是id在objc.h中的定义:
typedef struct objc_object {
class isa;
} *id;
由此可以看出,id是指向struct objc_object的一个指针。也就是说,id是一个指向任何一个继承了Object或NSObject类的对象。因为id是一个指针,所以在使用id的时候,不需要加星号,例如下面的代码:
id foo = renhe;
上述代码定义了一个foo变量,这个变量是指向NSObject的任意一个子类的指针。而“id *foo= renhe;”所定义的foo变量则是指向另一个指针的指针,被指向的指针指向NSObject的一个子类。
2.3.7 限定词
在Objective-C程序中的限定词有long、long long、short、unsigned及signed。
1. long
如果直接把限定词long放在声明int前,那么,所声明的整型变量在某些计算机上具有扩展的值域。例如,下面是一个上述情况的例子:
long int factorial;
通过上述代码,将变量factorial声明为long的整型变量。这就像float和double变量一样,long变量的具体精度也是由具体的计算机系统决定的。在许多系统上,int与long int具有相同的值域,而且任何一个都能存储32位宽231-1或2147483647的整型值。
在Objective-C程序中,long int类型的常量值可以通过在整型常量末尾添加字母L大小写均可来形成,此时,在数字和L之间不允许有空格出现。根据此要求,我们可以声明为如下格式:
long int numberOfPoints = 138881100L;
通过上述代码,将变量numberOfPoints声明为long int类型,而且初值为138881100。
要想使用NSLog显示long int的值,需要使用字母l作为修饰符,并且将其放在整型格式符号i、o和x之前。这意味着格式符号%li用十进制格式显示long int的值,符号%lo用八进制格式显示值,而符号%lx则用十六进制格式显示值。
2. long long
例如,在下面的代码中,使用了long long的整型数据类型:
long long int maxnum;
通过上述代码,将指定的变量声明为具有特定扩展精度的变量,通过该扩展精度,保证了变量至少具有64位的宽度。NSLog字符串不使用单个字母l,而使用两个l来显示long long的整数,例如“%lli”的形式。我们同样可以将long标识符放在double声明之前,例如下面的代码:
long double CN_NB_2012;
可以把long double常量写成其尾部带有字母l或L的浮点常量的形式,例如:
1.234e+5L
要想显示long double的值,需要使用修饰符L来帮助实现。例如,通过%Lf,用浮点计数法显示long double的值,通过%Le用科学计数法显示同样的值,使用%Lg告诉NSLog在%Lf和%Le之间任选一个使用。
3. short
如果把限定词short放在int声明之前,意思是告诉Objective-C编译器要声明的特定变量用来存储相当小的整数。使用short变量的主要好处,是节约内存空间,当程序员需要大量内存,而可用的内存量又十分有限时,可以使用short变量来解决内存不足的问题。
在很多计算机设备上,short int所占用的内存空间是常规int变量的一半。在任何情况下,需要确保分配给short int的空间数量不少于16位。
在Objective-C程序中,没有其他方法可显式编写short int型常量。要想显示short int变量,可以将字母h放在任何普通的整型转换符号之前,例如%hi、%ho或%hx。也就是说,可以用任何整型转换符号来显示short int,原因是,当它作为参数传递给NSLog例程时,可以转换成整数。
4. unsigned
在Objective-C程序中,unsigned是一种最终限定符,当整数变量只用来存储正数时,可以使用最终限定符。
例如,通过下面的代码向编译器声明,变量counter只用于保存正值:
unsigned int counter;
使用限制符的整型变量可以专门存储正整数,也可以扩展整型变量的精度。
将字母u或U放在常量之后,可以产生unsigned int常量,例如下面的代码:
0x00ffU
在编写整型常量时,可以组合使用字母u或U和l或L,例如,下面的代码可以告诉编译器将常量10000看作unsigned long:
10000UL
如果整型常量之后不带有字母u、U、l或L中的任何一个,而且因为太大,所以不适合用普通大小的int表示,那么编译器将把它看作是unsigned int值。如果太小,则不适合用unsigned int来表示,那么,此时,编译器将把它看作long int。如果仍然不适合用long int表示,编译器会把它作为unsigned long int来处理。
在Objective-C程序中,当将变量声明为long int、short int或unsigned int类型时,可以省略关键字int,为此,变量unsigned counter与如下声明格式等价:
unsigned counter;
同样,也可以将变量char声明为unsigned。
5. signed
在Objective-C程序中,限定词signed能够明确地告诉编译器特定变量是有符号的。signed主要用在char声明之前。
2.4 字 符 串
在Objective-C程序中,字符串常量是由@和一对双引号括起的字符序列。比如,@“CHINA”、@“program”、@“$12.5”等都是合法的字符串常量。与C语言的区别是有无@。字符串常量和字符常量是不同的量,主要有如下两点区别。
1字符常量由单引号括起来,字符串常量由双引号括起来。
2字符常量只能是单个字符,字符串常量则可以含一个或多个字符。
在Objective-C语言中,字符串不是作为字符的数组被实现。在Objective-C中的字符串类型是NSString,它不是一个简单数据类型,而是一个对象类型,这是与C++语言不同的。我们会在后面的章节中详细介绍NSString。下面是一个简单的NSString例子:
#import FoundationFoundation.h
int mainint argc, const char *argv[] {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
NSLog@"Programming is fun!";
[pool drain];
return 0;
}
上述代码与本章的第一段Objective-C程序类似,运行后会输出:
Programming is fun!
2.5 表 达 式
在Objective-C程序中,联合使用表达式和运算符可以构成功能强大的程序语句。本节将详细讲解表达式的基本知识,为读者步入本书后面知识的学习打下坚实的基础。
2.5.1 算数表达式
在Objective-C语言中,两个数相加时使用加号+,两个数相减时使用减号-,两个数相乘时使用乘号*,两个数相除时使用除号。因为它们运算两个值或项,所以这些运算符称为二元算术运算符。
1. 整数运算和一元负号运算符
例如,下面的代码演示了运算符的优先级,并且引入了整数运算的概念:
#import FoundationFoundation.h
int main int argc, char *argv[]
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
int a = 25;
int b = 2;
int result;
float c = 25.0;
float d = 2.0;

NSLog @"6 + a 5 * b = %i", 6+a5*b;
NSLog @"a b * b = %i", ab*b;
NSLog @"c d * d = %f", cd*d;
NSLog @"-a = %i", -a;

[pool drain];
return 0;
}
对上述代码的具体说明如下。
1第一个NSLog调用中的表达式巩固了运算符优先级的概念。该表达式的计算按以下顺序执行:
* 因为除法的优先级比加法高,所以,先将a的值25除以5。该运算将给出中间结果5。
* 因为乘法的优先级也大于加法,所以随后,中间结果5将乘以2即b的值,并获得新的中间结果10。
* 最后计算6加10,并得出最终结果16。
2第二条NSLog语句会产生一个新误区,我们希望a除以b再乘以b的操作返回a已经设置为25。但是,此操作并不会产生这一结果,在显示器上输出显示的是24。其实,该问题的实际情况是:这个表达式是采用整数运算来求值的。再看变量a和b的声明,它们都是用int类型声明的。当包含两个整数的表达式求值时,Objective-C系统都将使用整数运算来执行这个操作。在这种情况下,数字的所有小数部分将丢失。因此,计算a除以b,即25除以2时,得到的中间结果是12,而不是期望的12.5。这个中间结果乘以2,就得到最终结果24,这样,就解释了出现“丢失”数字精度的情况。
3在倒数第2个NSLog语句中,如果用浮点值代替整数来执行同样的运算,就会获得期望的结果。决定到底使用float变量还是int变量的,是基于变量的使用目的。如果无须使用任何小数位,可使用整型变量。这将使程序更加高效,也就是说,它可以在大多数计算机上更加快速地执行。另一方面,如果需要精确到小数位,很清楚应该选择什么。此时,唯一必须回答的问题是使用float还是double。对此问题的回答取决于使用数据所需的精度以及它们的量级。
4在最后一条NSLog语句中,使用一元负号运算符对变量a的值进行了求反处理。这个一元运算符是用于单个值的运算符,而二元运算符作用于两个值。负号实际上扮演了一个双重角色:作为二元运算符,它执行两个数相减的操作;作为一元运算符,它对一个值求反。
经过以上分析,最终运行上述代码后,会输出:
6 + a 5 * b = 16
a b * b = 24
c d * d = 25.000000
-a = -25
由此可见,与其他算术运算符相比,一元负号运算符具有更高的优先级,但一元正号运算符+除外,它与算术运算符的优先级相同,所以表达式“c = -a * b;”将执行-a乘以b。
在上述代码的前三条语句中,在int和a、b及result的声明中插入了额外的空格,这样做的目的,是对齐每个变量的声明,这种书写语句的方法使程序更加容易阅读。另外,我们还需要养成这样一个习惯——每个运算符前后都有空格;这种做法不是必需的,仅仅是出于美观上的考虑。一般来说,在允许单个空格的任何位置都可以插入额外的空格。
2. 模运算符
在Objective-C程序中,使用百分号%表示模运算符。为了了解模运算符的工作方式,请读者看下面的代码:
#import FoundationFoundation.h
int mainint argc, char *argv[]
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
int a=25, b=5, c=10, d=7;

NSLog@"a %% b = %i", a%b;
NSLog@"a %% c = %i", a%c;
NSLog@"a %% d = %i", a%d;
NSLog@"a d * d + a %% d = %i", ad*d + a%d;
[pool drain];
return 0;
}
对于上述代码的具体说明如下所示。
1在main语句中定义并初始化了4个变量:a、b、c和d,这些工作都是在一条语句内完成的。NSLog使用百分号之后的字符来确定如何输出下一个参数。如果它后面紧跟另一个百分号,那么,NSLog例程认为我们其实想显示百分号,并在程序输出的适当位置插入一个百分号。
2模运算符%的功能是计算第一个值除以第二个值所得的余数,在上述第一个例子中,25除以5所得的余数显示为0。如果用25除以10,会得到余数5,输出中的第二行可以证实。执行25除以7将得到余数4,它显示在输出的第三行。
3最后一条是求值表达式语句。Objective-C使用整数运算来执行两个整数间的任何运算,所以两个整数相除所产生的任何余数将被完全丢弃。如果使用表达式ad表示25除以7,将会得到中间结果3。如果将这个结果乘以d的值即7,将会产生中间结果21。最后,加上a除以d的余数,该余数由表达式a%d来表示,会产生最终结果25。这个值与变量a的值相同,并非巧合。一般来说,表达式“ad*d + a%d”的值将始终与a的值相等,当然,这是在假定a和d都是整型值的条件下做出的。事实上,定义的模运算符%只用于处理整数。
在Objective-C程序中,模运算符的优先级与乘法和除法的优先级相同。由此可以得出,表达式“table + value % TABLE_SIZE”等价于表达式“table + value % TABLE_SIZE”。
经过上述分析,运行上述代码后会输出:
a % b = 0
a % c = 5
a % d = 4
a d * d + a % d = 25
3. 整型值和浮点值的相互转换
要想使用Objective-C程序实现更复杂的功能,必须掌握浮点值和整型值之间进行隐式转换的规则。例如,下面的代码演示了数值数据类型间的一些简单转换:
#import FoundationFoundation.h
int mainint argc, char *argv[]
{
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
float f1=123.125, f2;
int i1, i2=-150;
i1 = f1; floating 转换为integer
NSLog@"%f assigned to an int produces %i", f1, i1;
f1 = i2; integer 转换为floating
NSLog@"%i assigned to a float produces %f", i2, f1;
f1 = i2 100; 整除integer类型
NSLog@"%i divided by 100 produces %f", i2, f1;
f2 = i2 100.0; 整除float类型
NSLog@"%i divided by 100.0 produces %f", i2, f2;
f2 = floati2100; 类型转换操作符
NSLog@"float %i divided by 100 produces %f", i2, f2;
[pool drain];
return 0;
}
对于上述代码的具体说明如下所示。
1因为在Objective-C中,只要将浮点值赋值给整型变量,数值的小数部分都会被删节,所以在第一个程序中,当把f1的值赋予i1时,会删除数字123.125的小数部分,这意味着只有整数部分即123存储到了i1中。
2当产生把整型变量指派给浮点变量的操作时,不会引起数值的任何改变,该值仅由系统转换并存储到浮点变量中。例如上述代码的第二行验证了这一情况——i2的值-150进行了正确转换,并储到float变量f1中。
执行上述代码后输出:
123.125000 assigned to an int produces 123
-150 assigned to a float produces -150.000000
-150 divided by 100 produces -1.000000
-150 divided by 100.0 produces -1.500000
float -150 divided by 100 produces -1.500000
4. 类型转换运算符
在声明和定义方法时,将类型放入圆括号中,可以声明返回值和参数的类型。在表达式中使用类型时,括号表示一个特殊的用途。例如,上面程序中的最后一个除法运算:
f2 = float i2 100;
在上述代码中,引入了类型转换运算符。为了求表达式值,类型转换运算符将变量i2的值转换成float类型。该运算符永远不会影响变量i2的值;它是一元运算符,行为与其他一元运算符一样。
类型转换运算符的优先级要高于所有的算术运算符,但是,一元减号和一元加号运算符除外。如果需要,可以经常使用圆括号进行限制,以任何想要的顺序来执行一些项。例如,表达式“int 29.55 + int 21.99”在Objective-C中等价于“29 + 21”,因为将浮点值转换成整数的后果就是舍弃其中的浮点值。
而表达式“float 6 float 4”得到的结果为1.5,与表达式“float6 4”的执行效果是相同的。
类型转换运算符通常用于将一般id类型的对象转换成特定类的对象,例如,在下面的代码中,将id变量myNumber的值转换成一个Fraction对象,转换结果将指派给Fraction变量myFraction:
id myNumber;
Fraction *myFraction;
...
myFraction = Fraction*myNumber;
2.5.2 常量表达式
在Objective-C程序中,常量表达式是指每一项都是常量值的表达式。其中,在下列情况下,必须使用常量表达式:
* 作为switch语句中case之后的值。
* 指定数组的大小。
* 为枚举标识符指派值。
* 在结构定义中,指定位域的大小。
* 为外部或静态变量指派初始值。
* 为全局变量指派初始值。
* 在#if预处理程序语句中,作为#if之后的表达式。
其中,在上述前4种情况下,常量表达式必须由整数常量、字符常量、枚举常量和sizeof表达式组成。在此,只能使用以下运算符:算术运算符、按位运算符、关系运算符、条件表达式运算符和类型强制转换运算符。
在上述第5和第6种情况中,除了上面提到的规则外,还可以显式地或隐式地使用取地址运算符。然而,它只能应用于外部或静态变量或函数。因此,假设x是一个外部或静态变量,表达式“x + 10”将是合法的常量表达式。此外,表达式“a[10] - 5”在a是外部或静态数组时将是合法的常量表达式。最后,因为a[0]等价于表达式a,所以“a + sizeof char * 100”也是一个合法的常量表达式。
在上述最后一种需要常量表达式在#if之后的情况下,除了不能使用sizeof运算符、枚举常量和类型强制转换运算符以外,其余规则与前4种情况的规则相同。然而,它允许使用特殊的defined运算符。
2.5.3 条件运算符
Obj

 

 

書城介紹  | 合作申請 | 索要書目  | 新手入門 | 聯絡方式  | 幫助中心 | 找書說明  | 送貨方式 | 付款方式 香港用户  | 台灣用户 | 大陸用户 | 海外用户
megBook.com.hk
Copyright © 2013 - 2024 (香港)大書城有限公司  All Rights Reserved.