创建一个 HelloWorld 项目, 在这个 IOS 项目中有四个目录 : 如下图;
-- HelloWorldTests 目录 : 单元测试相关的类和资源;
HelloWorld 目录介绍 :
-- 命名规则 : 该目录名称与 IOS 项目名称相同, 是主目录;
-- 存放内容 : IOS 项目的 源码文件, 界面设计文件, 资源文件都存放在该目录下;
-- 源文件 : Objective C 的 .m 和 .h 后缀的文件;
-- 界面设计文件 : Main.storyboard 是界面设计文件, 原来使用的是 nib 界面设计文件, storyboard 是新版本使用的;
-- Supporting Files : 支持库, 一般保存 不是 Objective-C 的源代码 和 资源文件;
Supporting Files 目录简介 :
-- HelloWorld-info.plist 文件 : 文件名格式为 项目名-info.plist, 属性列表文件, 保存 IOS 项目的各种信息;
-- InfoPlist.strings 文件 : 该文件保存字符串, 主要为程序提供国际化支持;
-- main.m 文件 : main() 函数程序入口文件;
-- HelloWorld-Prefix.pch 文件 : 项目中用到的来自外部框架的头文件在这里面注明, Xcode 会预编译这些文件内容;
Frameworks 目录简介 :
-- 包含文件 : 包含项目所依赖的框架 或者 库, 还有 声音 图像 等资源文件也可以放在该文件中;
-- 自动链接 : 框架和库一旦被添加到该目录后, 会自动链接到应用中, IOS 应用可以调用这些资源 和 库中的类 和 函数;
-- 系统默认框架 : Foundation.framework, CoreGraphics.framwork, UIKit.framework, CoreData.framework, XCTest.framework 五个默认框架;
Products 目录 :
-- 包含内容 : 包含该项目所生成的应用程序, 其中 HelloWorld.app 就是安装文件;
-- 红色显示 : 由于还没有编译程序, 该文件显示红色, 这说明该文件目前不存在;
Xcode 与 文件系统 :
-- Xcode 逻辑分组 :
-- 真实文件系统 :
localhost:HelloWorld octopus$ tree
.
|____.DS_Store
|____Base.lproj
| |____.DS_Store
| |____Main.storyboard
|____en.lproj
| |____.DS_Store
| |____InfoPlist.strings
|____HelloWorld-Info.plist
|____HelloWorld-Prefix.pch
|____HelloWorld.xcdatamodeld
| |____.xccurrentversion
| |____HelloWorld.xcdatamodel
| | |____contents
|____Images.xcassets
| |____.DS_Store
| |____AppIcon.appiconset
| | |____Contents.json
| |____LaunchImage.launchimage
| | |____Contents.json
|____main.m
|____OCTAppDelegate.h
|____OCTAppDelegate.m
|____OCTDetailViewController.h
|____OCTDetailViewController.m
|____OCTMasterViewController.h
|____OCTMasterViewController.m
-- 不对应 : Xcode 导航面板中的目录 文件 与 真实文件系统中的目录文件不是对应的;
-- 逻辑分组 : Xcode 将 真实文件进行了逻辑分组, 并不是真实的文件结构;
-- 自定义分组 : 开发者还可以创建自定义的分组;
mac 中的 tree 命令 :
-- tree 命令模拟 :
find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'
-- 模拟 tree 命令 : 之后可以调用 tree 命令了;
alias tree="find . -print | sed -e 's;[^/]*/;|____;g;s;____|; |;g'"
删除 Main.storyboard 文件 :
-- 删除方法 : 选择文件, 按 Delete 键, 弹出以下对话框, 选择 Move to Trash 选项, 直接删除;
-- Remove Reference 选项 : 在文件系统保留该文件, 但是不编译该文件;
-- 修改配置 : 点击项目名称, 选择 General 面板, 然后删除 Main Interface 中的 Main 选项;
创建 xib 文件流程 :
-- 选择文件类型 : 菜单栏选择 File -> New -> File, 弹出下面对话框, 选择 iOS 的 User Interface 选项卡中的 View 选项, 点击 Next 按钮;
-- 创建文件 : 输入名称 Main.xib 自定义的, 选择分组 HelloWorld, 选择所输出的 app 文件;
-- 创建成功 :
xib 界面设计文件 :
-- PlaceHolder 列表区 : 包括 File's Owner 和 First Responder 两个文件;
-- Objects 列表区 : 保存界面布局文件中的 UI 控件实例;
PlaceHolder 列表区 :
-- File's Owner 文件 : 代表加载界面设计文件对象, 即 布局文件对象, 谁负责加载 Main.xib 界面设计文件, 谁就是该 界面设计文件的 File's Owner;
-- First Responder 文件 : 代表正在与用户交互的对象, 即获取到焦点的对象, 其代表的控件会变化, 用户点击按钮时, 按钮就成为了其代表的控件;
Objects 列表区 :
-- 主要作用 : 该列表区 保存 xib 界面 所用到的 UI 控件实例;
-- 工作流程 : 开发者将 UI 控件 拖入 xib 文件, app 运行时会加载 xib 文件, 并为每个控件都创建对象, Objects 列表区可以看到所有的 UI 控件;
xib 和 nib 后缀文件 :
-- 新旧区别 : nib 后缀是传统格式, xib 后缀是新格式;
-- 默认模板 : Xcode 默认使用 xib 作为默认格式;
xib 与 nib 主要区别 :
-- 文件类型 : xib 是文本文件, nib 是二进制文件, Xcode 编译项目时 会将 xib 文件转为 nib 文件;
-- nib 文件 : Interface Builder 把窗口, 菜单栏 以及 各种 UI 组件都冻结在 nib 文件中, 使用 nib 界面设计文件, 这些 UI 控件对象已经被创建好, app 运行时, 只需要苏醒这些 UI 控件 即可;
-- xib 文件优点 : xib 更方便, 便于版本控制;
xib 添加控件 :
-- 对象库面板快捷键 : 使用 control + option + command + 1 快捷键, 即可显示对象库面板;
-- 添加 Label 控件 到界面中 : Label 拖到中间会有 水平 和 垂直两条 蓝色引导线;
-- 边界引导线 : 如果把控件拖到边界, 会出现边界引导线, 说明不能再向外拖了;
上 :
左 :
右 :
下 :
-- 显示 UI 控件轮廓 : Editor -> Canvas -> Show Layout Rectangles, 可以看到布局出现下面的轮廓;
相关面板 :
-- 文件检查器面板 : 快捷键 option + command + 1, 文件相关信息;
-- 快速帮助检查器面板 : 快捷键 option + command + 2, 显示先关的帮助文档;
-- 身份检查器面板 : 快捷键 option + command + 3, 管理界面控件的 实现类, 恢复 ID 等属性;
-- 属性检查器面板 :快捷键 option + command + 4, 管理控件的 拉伸方式, 背景色 等外观属性;
-- 大小检查器面板 : 快捷键 option + command + 5, 管理控件 大小 位置 相关属性;
-- 连接检查器面板 : 快捷键 option + command + 6, 管理控件 与 代码之间关联;
UIView 属性 :
Mode 属性 :
-- 主要作用 : 用于控制 UI 控件内图片的对齐方式, 是否缩放适配控件;
-- Scale To Fit : 缩放图片, 保证图片适配该控件;
-- Aspect Fit : 保持纵横比缩放图片, 保证图片能够适应控件;
-- Aspect Fill : 保持纵横比缩放图片, 保证图片能够填充控件;
-- 注意 : 缩放会带来不必要的开销, 最好为不同屏幕尺寸创建对应的图片;
Tag 属性 : 该属性是 控件的 唯一标识, 可以根据该 标识 获取该 UI 控件的引用;
Interaction 属性 :
-- User Interface Enable : 勾选, 表明该控件支持与用户交互;
-- Multiple Touch : 勾选, 表明该控件支持多点触控, 支持更复杂的手势;
Alpha 属性 :
-- 作用 : 用于控制该控件的透明度, 其属性支持 0.0 ~ 1.0 任意浮点数;
-- 注意 : 如果设置为半透明效果, 会增加额外开销;
background 属性 :
-- 作用 : 设置控件的背景色;
Drawing 属性 :
-- Opaque : 设置控件是否为 不透明, 如果设置为不透明, 不管该控件的透明度是否是半透明, 该控件后的其它控件将不会被绘制;
-- Hidden : 隐藏该控件, 用户看不到本控件;
-- Clears Graphics Context : 清除该控件所覆盖的区域, 勾选该选项后 IOS 会清除该控件覆盖的区域, 然后绘制该控件, 会降低性能;
-- Clip Subviews : 是否裁剪子控件, 当该控件包含多个子控件, 并且这些子控件超出了父类容器, 勾选后, 超出部分就不会被绘制;
-- Autoresize Subviews : 是否自动调整子控件大小, 如果勾选, 该控件大小改变时, 其子控件也会随之调整大小;
Streching 属性 :
-- 主要作用 : 用于控制 UIView 拉伸区域, 只有在需要调整控件大小并重绘控件时才需要定义拉伸区域;
UILabel 属性 :
Text 属性 :
-- 属性值 : 支持 Plain 和 Attribute 属性, 一般设置为 Plain;
-- 文本 : 在 Text 属性下面有一个文本框, 在这个文本框中输入要显示的文本内容;
Color 属性 : 控制 UILabel 中的文本颜色;
Font 属性 :
-- 作用 : 控制文本 字体 文字大小 风格等属性;
-- System : 系统默认字体, 不能修改 Family Style Size 属性;
-- System Bold : 系统默认的粗体字;
-- System Italic : 系统默认的斜体字;
Alignment 属性 :
-- 作用 : 设置对齐方式, 左对齐, 居中对齐, 右对齐;
Lines 属性 :
-- 作用 : 控制 文本行数;
Behavior 属性 :
-- Enabled : 控制 UILabel 是否可用, 如果没有勾选, 该 Label 不可用, 处于淡灰色;
-- Highlighted : 控制 UILabel 是否处于高亮状态, 勾选该控件后处于高亮状态, 控件中的文本以高亮显示;
Line Break 属性 :
-- 作用 : 该属性对 UILabel 内的文本进行截断, UILabel 中的字符串比较多, UILabel 无法容纳这些字符串, 可以将字符串截断, 显示一部分;
-- Truncate Head : 显示后半部分字符串, 前半部分使用 ... 代替;
-- Truncate Middle : 显示 前后 部分, 中间使用 .. 替代;
-- Truncate Tail : 截断后半部分, 后半部分使用 ... 替代;
AutoShrink 属性 :
-- 作用 : UILabel 中字符串较多 以至于 UILabel 无法容纳字符串时, AutoShrink 属性控制文本自动收缩;
-- Fixed Font Size : 不缩放;
-- Minimum Font Scale : 设置最小的缩放倍数, 设置的值是 0.0 ~ 1.0 之间的浮点数;
-- Minimum Font Size : 设置最小的字号大小, 设置的值是字体大小;
-- Tighten Letter Spacing : 勾选该复选框 会自动压缩字符串中的空白, 保证 UILabel 能容纳这些文本中的内容;
Highlighted 属性 :
-- 作用 : 为 UILabel 中的文本设置高亮显示, 前提 Behavior 属性的 Highlighted 属性勾选;
Shadow 属性 :
-- 作用 : 为文本设置阴影颜色;
Shadow Offset 属性 :
-- 作用 : 控制阴影文本与正常文本之间的偏移量,
-- Horizontal : 属性值 >0 向右偏移, < 0 向左偏移;
-- Vertical : 属性值 >0 向下偏移, <0 向上偏移;
程序入口代码示例 :
//
// main.m
// FirstApp
//
// Created by octopus on 15-11-4.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//
#import <UIKit/UIKit.h>
#import "OCAppDelegate.h"
int main(int argc, char * argv[])
{
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([OCAppDelegate class]));
}
}
-- Main 函数执行流程 : 调用 UIApplicationMain () 函数, 创建 UIApplication 对象, 为 UIApplication 对象设置委托, 负责处理应用程序事件循环;
委托对象简介 :
-- UIApplication 本质 : UIApplication 代表了 IOS 应用程序, 每个应用中只有一个 UIApplication;
-- 实际编程对象 : 虽然 UIApplication 代表了整个应用, 但是编程时不直接操作 UIApplication, 开发者一般与 delegate 委托对象交互;
-- 全局变量 : UIApplication 委托对象全局可用, 定义全局变量即 将该变量设置为 UIApplication 的委托对象;
-- 数据交换 : 获取委托对象, 可以向其中存取数据, 可以作为 IOS 应用的通信中心, 程序组件之间通过委托对象进行数据交互;
-- 处理生命周期事件 : 应用程序委托对象还处理 IOS 应用的各种生命周期事件, 处理应用执行过程中的事件循环;
OCAppDelegate.h 详解 :
-- 代码示例 :
//
// OCAppDelegate.h
// FirstApp
//
// Created by octopus on 15-11-4.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface OCAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@end
-- 继承父类 : 该 OCAppDelegate 类, 继承了 UIResponder 类, 表明该类可以作为响应者使用;
-- 实现协议 : 实现了 UIApplicationDelegate 协议, 继承这个协议即表明该对象是应用程序委托类;
-- UIWindow 属性 : 代表 IOS 应用程序的窗口, 一个应用只需创建一次 UIWindow 窗口;
-- FKViewController 属性 : 代表视图控制器, 系统创建控制器时, 通常会加载对应的 xib 文件;
-- 应用初始界面 : 在 OCAppDelegate 中定义了 FKViewController 变量, 该变量类型对应的 xib 文件就是初始界面;
AppDelegate.m 详解 :
-- 代码示例 : 书中的示例代码;
//
// FKAppDelegate.m
// HelloiOS
//
// Created by yeeku on 13-5-16.
// Copyright (c) 2013年 crazyit.org. All rights reserved.
//
#import "FKAppDelegate.h"
#import "FKViewController.h"
@implementation FKAppDelegate
// 当应用程序启动后将会调用该方法
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 创建UIWindow对象,并初始化该窗口的大小与主屏幕大小相同
// 程序将创建的UIWindow对象赋值给该程序委托对象的window属性
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// 创建FKViewController对象、并使用FKViewController界面布局文件来
// 初始化该视图控制器关联的用户界面
self.viewController = [[FKViewController alloc] initWithNibName:@"FKViewController" bundle:nil];
// 让该程序的窗口加载、并显示viewController视图控制器关联的用户界面
self.window.rootViewController = self.viewController;
// 将该UIWindow对象设为主窗口、并显示出来
[self.window makeKeyAndVisible];
return YES;
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// 当应用程序从活动状态转入不活动状态时,系统将会调用该方法。
// 通常来说的,当应用程序突然被中断(比如有电话、短信进来时),系统将会回调该方法
// 另外,当用户离开该程序,程序开始转入后台状态时也会回调该方法。
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// 通常可通过重写该方法来释放共享资源、保存用户数据,取消定时器。
// 开发者还可通过该方法来保存足够的状态数据,
// 这样保证用户重新启动该应用时能正确恢复到当前状态
// 如果该应用程序支持后台执行,当用户退出时,系统调用调用该方法,而不是调用
// applicationWillTerminate:方法
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// 当应用程序将要进入前台时将会调用该方法。
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// 当应用程序进入前台、并转入活动状态时将会调用该方法。
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// 当应用程序被终止时,系统将会调用该方法。
}
@end
-- 重写 application 方法 : 应用程序加载时会回调该方法;
application 方法流程 :
-- 创建 UIWindow 对象 : 创建 UIWindow 对象, 该对象就是 IOS 应用程序的窗口;
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
-- 创建 ViewController 对象 : 该对象用于加载该对象对应的 xib 等界面设计文件;
self.viewController = [[FKViewController alloc] initWithNibName:@"FKViewController" bundle:nil];
-- 显示界面 : 让应用程序窗口显示 ViewController 对象;
self.window.rootViewController = self.viewController;
-- 主窗口 : 将该程序的窗口设置为主窗口, 将主窗口显示出来;
[self.window makeKeyAndVisible];
IOS MVC 模式 :
-- Model 模型 : Model 一般式普通的 Objective - C 类, 这些类用于保存 处理 数据;
-- View 视图 : 使用 Interface Builder 创建的视图组件, 如 xib, storyboard 后缀的界面设计文件;
-- Controller 控制器 : 一般是 Objective - C 类, 一般都会继承 UIViewController 基类;
UIController 方法详解 : 主要用于处理视图加载, 显示等事件;
-- viewDidLoad 方法 : 视图装载完成后, 自动回调该方法, 重写时注意先使用 [super viewDidLoad] 把父类方法调用了, 在其后追加自己处理的内容;
-- didReceiveMemoryWarning 方法 : 系统自动回调的, 内存紧张时会调用此方法, 在方法内释放内存, 注意先调用 [super didReceiveMemoryWarning] 方法;
-- viewWillAppear 方法 : 视图将要显示时系统会自动回调该方法;
-- viewDidAppear 方法 : 视图显示出来后系统自动回调的方法;
-- viewWillDisappear 方法 : 视图将要被隐藏 或者 关闭时, 回调该方法;
-- viewDidDisappear 方法 : 视图被隐藏 或 关闭后, 回调该方法;
-- viewWillLayoutSubviews 方法 : 视图将要排列其子视图时, 需要回调的方法;
-- viewDidLayoutSubviews 方法 : 视图已经排列好其子视图后, 回调的方法;
UIViewController 代码示例 :
-- 头文件 :
//
// OCViewController.h
// FirstApp
//
// Created by octopus on 15-11-4.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface OCViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *label1;
@property (strong, nonatomic) IBOutlet UILabel *label2;
@property (strong, nonatomic) IBOutlet UIButton *button;
- (IBAction)button_click:(id)sender;
@end
-- 实现文件 :
//
// OCViewController.m
// FirstApp
//
// Created by octopus on 15-11-4.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//
#import "OCViewController.h"
@interface OCViewController ()
@end
@implementation OCViewController
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
//使用 IBOutlet 获取 UI 控件
[self.label1 setText:@"Tom"];
//使用 tag 获取 UI 控件
UILabel * label_tag = (UILabel *)[self.view viewWithTag:1];
[label_tag setText:@"Jerry"];
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
- (IBAction)button_click:(id)sender {
//使用 IBOutlet 获取 UI 控件
[self.label1 setText:@"John"];
//使用 tag 获取 UI 控件
UILabel * label_tag = (UILabel *)[self.view viewWithTag:1];
[label_tag setText:@"John"];
}
@end
IBOutlet 属性 :
-- 主要作用 : IBOutlet 属性可以连接 Objective - C 源码 和 界面设计文件 (.xib 文件 或 .storyboard 文件);
-- 连接方法 : 在界面设计文件对应的 UIViewController 类中, 定义一个 IBOutlet 属性, 该属性 与 Interface Builder 中的控件相关联;
-- 调用方法 : 在 UIViewController 中调用 控件的方法, 使用 IBOutlet 属性即可访问 界面设计文件的组件;
IBOutlet 连接方法 :
-- 打开辅助编辑器 :
-- 辅助编辑器界面 : 左边显示 界面设计文件, 右边显示 UIViewController 类;
-- 拖动控件到 UIViewController 中 : 按住 control 键, 将控件拖到 UIViewController.h 中;
-- 设置 IBOutlet 的属性 : 控件拖到 UIViewController 中后, 弹出下面的对话框;
-- 连接控件 : 点击上面的 Connect, 在 UIViewController 中就会出现 @property IBOutlet 属性;
//
// OCViewController.h
// FirstApp
//
// Created by octopus on 15-11-4.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface OCViewController : UIViewController
@property (strong, nonatomic) IBOutlet UILabel *label1;
@property (strong, nonatomic) IBOutlet UILabel *label2;
@property (strong, nonatomic) IBOutlet UIButton *button;
- (IBAction)button_click:(id)sender;
@end
-- IBOutlet 连接标识 : 如下图, 属性前面有 圆圈黑点, 即说明 该 属性是连接 UI控件 的;
IBOutlet 属性解析 :
-- Connection : 设置该控件的 IBOutlet 或 IBOutlet 集合, 默认 IBOutlet 属性;
-- Name : 属性名, 即 @property 的属性名;
-- Type : 界面控件的类型, UILabel 等控件名称;
-- Storage : Weak, Strong 指针的强 弱 存储机制;
IBOutlet 属性 :
-- 不使用 @synthesize : 使用 @property 定义的属性, 在 UIViewController.m 中不需要 使用 @synthesize 设置 setter getter 方法;
-- 查看连接关系 : 使用 Xcode 的连接检查器面板查看 IBOutlet 属性 与 UI控件 间关联, 使用 control + option + command + 6 或者 右上角的
图标 , 注意 要在界面设计文件中先选择 File Owner;
解析连接器面板中的 IBOutlet 元素 :
-- Outlets : 多个 IBOutlet 属性, 每个属性都对应 界面设计文件中的一个 UI 控件;
-- Referencing Outlets : 代表被选择对象本身被关联到其他对象的 IBOutlet 属性;
-- Referencing Outlets Collections : 控件被关联到其它对象的 IBOutlet 集合属性;
通过 Tag 属性获取控件流程 :
-- 设置 UILabel 控件的 Tag 属性 : Command + option + 4 即可显示属性界面;
-- 获取 UILabel 控件 : 通过 viewWithTag : tag标签 获取 UI 控件的引用;
//使用 tag 获取 UI 控件
UILabel * label_tag = (UILabel *)[self.view viewWithTag:1];
[label_tag setText:@"Jerry"];
IBAction 简介 :
-- 主要作用 : IBAction 是 UIViewController 中的特殊方法, 这该方法是 UI 控件事件处理方法;
IBAction 事件绑定流程 :
-- 需求 : 为UIButton 组件添加点击方法;
-- 创建 UI 组件 : Interface Builder 中创建 UIButton 对象;
-- 创建 IBAction 方法 : 在 界面设计文件 对应的 UIViewController 中定义 IBAction 方法;
-- 绑定 IBAction 方法与 UI 组件 : 将 UIViewController 中的 IBAction 方法 与 界面设计文件中的 UIButton 组件绑定;
-- 触发 IBAction 方法 : 界面中的 UIButton 被点击, 就会回调 IBAction 方法;
IBAction 绑定步骤 :
-- 选中界面设计文件, 打开辅助编辑器 :
-- 拖动按钮到 UIViewController.h 文件中 : 按住 control 键不放, 将按钮拖动到 UIViewController 中;
-- 设置 IBAction 属性 : 在接下来弹出的对话框中的 Connection 列表设置 为 Action, 将设置 IBAction 属性, 设置完毕后会自动生成点击事件回调方法, 之后在实现类中实现这个方法即可;
IBAction 属性 :
-- Connection : 选择为 UI 控件创建 IBOutlet 还是 IBAction 属性类型;
-- Name : IBAction 方法名;
-- Type : 触发该事件的 UI 控件类型, 默认为 id, 如果需要更精准可以设置成具体的 UI 组件类, 如 UIButton;
-- Event : 选择为什么样的事件绑定 IBAction 属性, 默认 Touch Up Inside 在 UI 控件区域按下并松开;
-- Arguments : 选择 IBAction 方法形参列表, Sender 触发 IBAction 方法的事件源, Sender And Event, Event 是事件本身;
注册删除事件响应方法 :
-- 注册删除事件方法来源 : IOS 中与用户交互的控件都继承了 UIControl 类, 注册 删除 控件响应方法 是该 UIControl 基类提供的;
-- 添加事件响应方法 : "addTarget : action : forControlEvents :" , 为当前控件的 指定事件 设置 处理方法;
-- 移除事件响应方法 : "removeTarget : action : forControlEvent : " , 删除 UIControl 指定的事件处理方法.
添加移除事件方法参数解析 :
-- addTarget / removeTarget 参数 : 指定 事件响应方法 所在的对象;
-- action 参数 : 接受一个 SEL 参数, 该 参数代表的方法作为事件处理方法;
-- forControlEvents 参数 : UIControlEvent 枚举值参数, 用于指定事件类型.
代码示例 :
-- OCViewController.h 头文件 : 声明 IBOutlet 指定 UI 控件引用;
@property (strong, nonatomic) IBOutlet UIButton *UIControl_button;
-- OCViewController.m 文件 : 为 UI 控件添加事件监听;
//注意 selector 中的方法, 如果后面有参数 则需要带上 冒号 ":"
[self.UIControl_button addTarget: self action:@selector(button_click2:) forControlEvents: UIControlEventTouchUpInside];
-- 添加的方法 :
- (void) button_click2:(id)sender{
[self.label1 setText:@"octopus"];
[self.label2 setText:@"octopus"];
}
StoryBoard 简介 :
-- 使用版本 : IOS 5 之后默认使用 storyboard 作为界面设计文件, 而之前是 xib 作为默认的界面设计文件;
-- 与 xib 界面设计文件的共同点 : 项目中主要包含 应用委托类, 界面设计文件, 界面控制类, 如下图 :
-- 不同点 : UIViewController 与界面设计文件的名称不再相同, 界面设计文件名称是 Main.storyboard, 该界面设计文件包含所有的界面;
-- 界面设计文件 与 界面控制类对应关系 : 一个 storyboard 界面设计文件 对应 多个 界面控制类;
Scene 场景简介 :
-- Scene 组成 : Scene 由 整个视图, 视图控制器, 第一响应者 组成;
-- 场景与界面 : 一个场景 对应 一个窗口界面;
-- 层次关系 : View Controller 在 Scene 中, UI 控件 在 View Controller 中, 如下图 :
灰色箭头作用 :
-- 作用 : 箭头表示 UI 控制器之间的切换关系, 箭头指向需要加载的 视图控制器;
-- 移动箭头 : 视图中只有一个 UI 控制器, 移动箭头始终指向唯一的 一个 UI 控制器;
-- 好处 : 可以直观地看到多个视图之间的协作关系, 可以在 Interface Builder 中配置视图之间的切换关系;
-- 图示 :
界面设计文件的 工具图标 :
-- 缩小 : 多个视图控制器在同一个窗口, 缩小界面可以同时查看所有的 视图控制器;
-- 恢复 : 恢复原样查看;
-- 放大 : 放大界面设计文件;
委托类代码对比 :
-- xib 委托类 : 加载完成方法;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 创建UIWindow对象,并初始化该窗口的大小与主屏幕大小相同
// 程序将创建的UIWindow对象赋值给该程序委托对象的window属性
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// 创建FKViewController对象、并使用FKViewController界面布局文件来
// 初始化该视图控制器关联的用户界面
self.viewController = [[FKViewController alloc] initWithNibName:@"FKViewController" bundle:nil];
// 让该程序的窗口加载、并显示viewController视图控制器关联的用户界面
self.window.rootViewController = self.viewController;
// 将该UIWindow对象设为主窗口、并显示出来
[self.window makeKeyAndVisible];
return YES;
}
-- storyboard 委托类 : 加载完成方法;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
return YES;
}
-- 主要区别 : storyboard 不需要创建 UIViewWindow 和 UIViewController, 不需要将 UIViewController 添加到 UIWindow 中;
-- 设置 storyboard : 点击 项目选项 , 在 General 选项卡中, 选择左侧 TARGETS, 选中对应项目, 在 Main Interface 中选择 storyboard 界面设计文件;
基本无界面 UI 显示代码示例 :
-- 创建 Empty Application :
-- OCAppDelegate.h :
//
// OCAppDelegate.h
// Empty
//
// Created by octopus on 15-11-19.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//
#import <UIKit/UIKit.h>
@interface OCAppDelegate : UIResponder <UIApplicationDelegate>
@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) UILabel * label;
@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;
@end
-- OCAppDelegate.m :
//
// OCAppDelegate.m
// Empty
//
// Created by octopus on 15-11-19.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//
#import "OCAppDelegate.h"
@implementation OCAppDelegate
@synthesize managedObjectContext = _managedObjectContext;
@synthesize managedObjectModel = _managedObjectModel;
@synthesize persistentStoreCoordinator = _persistentStoreCoordinator;
@synthesize label;
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// 创建 UIWindow 对象, 设置其大小与屏幕大小相同
self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// 设置背景颜色
self.window.backgroundColor = [UIColor whiteColor];
// 创建 UIViewController 对象
UIViewController * controller = [[UIViewController alloc] init];
// 窗口加载并显示 视图控制器 并 关联 用户界面
self.window.rootViewController = controller;
// 创建 UIView 对象
UIView * rootView = [[UIView alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
// UIViewController 显示 rootView 控件
controller.view = rootView;
// 创建圆角按钮
UIButton * button = [UIButton buttonWithType : UIButtonTypeRoundedRect];
// 设置按钮大小
button.frame = CGRectMake(60, 200, 200, 40);
// 为按钮设置文本
[button setTitle:@"octopus button" forState: UIControlStateNormal];
// 为按钮添加点击事件
[button addTarget:self action:@selector(button_click) forControlEvents:UIControlEventTouchUpInside];
// 将按钮添加到 View 上
[rootView addSubview : button] ;
// 创建 UILabel 对象
label = [[UILabel alloc] initWithFrame:CGRectMake(60, 30, 200, 130)];
// 设置文本内容
label.text = @"octopus label";
// 设置背景颜色
label.backgroundColor = [UIColor grayColor];
// 将 UILabel 添加到 rootView 中
[rootView addSubview : label];
// 显示 界面
[self.window makeKeyAndVisible];
return YES;
}
- (void) button_click
{
[label setText:@"button click"];
}
- (void)applicationWillResignActive:(UIApplication *)application
{
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
- (void)applicationWillTerminate:(UIApplication *)application
{
// Saves changes in the application's managed object context before the application terminates.
[self saveContext];
}
- (void)saveContext
{
NSError *error = nil;
NSManagedObjectContext *managedObjectContext = self.managedObjectContext;
if (managedObjectContext != nil) {
if ([managedObjectContext hasChanges] && ![managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
}
}
#pragma mark - Core Data stack
// Returns the managed object context for the application.
// If the context doesn't already exist, it is created and bound to the persistent store coordinator for the application.
- (NSManagedObjectContext *)managedObjectContext
{
if (_managedObjectContext != nil) {
return _managedObjectContext;
}
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator != nil) {
_managedObjectContext = [[NSManagedObjectContext alloc] init];
[_managedObjectContext setPersistentStoreCoordinator:coordinator];
}
return _managedObjectContext;
}
// Returns the managed object model for the application.
// If the model doesn't already exist, it is created from the application's model.
- (NSManagedObjectModel *)managedObjectModel
{
if (_managedObjectModel != nil) {
return _managedObjectModel;
}
NSURL *modelURL = [[NSBundle mainBundle] URLForResource:@"Empty" withExtension:@"momd"];
_managedObjectModel = [[NSManagedObjectModel alloc] initWithContentsOfURL:modelURL];
return _managedObjectModel;
}
// Returns the persistent store coordinator for the application.
// If the coordinator doesn't already exist, it is created and the application's store added to it.
- (NSPersistentStoreCoordinator *)persistentStoreCoordinator
{
if (_persistentStoreCoordinator != nil) {
return _persistentStoreCoordinator;
}
NSURL *storeURL = [[self applicationDocumentsDirectory] URLByAppendingPathComponent:@"Empty.sqlite"];
NSError *error = nil;
_persistentStoreCoordinator = [[NSPersistentStoreCoordinator alloc] initWithManagedObjectModel:[self managedObjectModel]];
if (![_persistentStoreCoordinator addPersistentStoreWithType:NSSQLiteStoreType configuration:nil URL:storeURL options:nil error:&error]) {
/*
Replace this implementation with code to handle the error appropriately.
abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
Typical reasons for an error here include:
* The persistent store is not accessible;
* The schema for the persistent store is incompatible with current managed object model.
Check the error message to determine what the actual problem was.
If the persistent store is not accessible, there is typically something wrong with the file path. Often, a file URL is pointing into the application's resources directory instead of a writeable directory.
If you encounter schema incompatibility errors during development, you can reduce their frequency by:
* Simply deleting the existing store:
[[NSFileManager defaultManager] removeItemAtURL:storeURL error:nil]
* Performing automatic lightweight migration by passing the following dictionary as the options parameter:
@{NSMigratePersistentStoresAutomaticallyOption:@YES, NSInferMappingModelAutomaticallyOption:@YES}
Lightweight migration will only work for a limited set of schema changes; consult "Core Data Model Versioning and Data Migration Programming Guide" for details.
*/
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
return _persistentStoreCoordinator;
}
#pragma mark - Application's Documents directory
// Returns the URL to the application's Documents directory.
- (NSURL *)applicationDocumentsDirectory
{
return [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
}
@end
-- 执行效果 : 点击前;
-- 执行后 :
-- 工程内容 : 该工程中只需要修改 OCAppDelegate.h 和 OCAppDelegate.m 两个类;
动态添加删除组件代码示例 :
-- 创建文件 : 创建 Single View Application;
-- 工程文件显示 : 只需要修改 OCViewController.m 文件即可, 其它文件原封不动;
-- OCViewController.m 代码 :
//
// OCViewController.m
// DynamicUI
//
// Created by octopus on 15-11-22.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//
#import "OCViewController.h"
/*
类别与扩展
类别 : 为现有类添加新方法, @interface 已有类 (类别名) ... 方法 ... @end, 实现类实现接口中的方法.
-- 头文件名称 : 已有类+类别名.h;
-- 实现类文件名称 : 已有类+类别名.m, 注意 该实现部分 只是实现 类别中定义的内容;
扩展 : 扩展是匿名的类别, 扩展也要定义的 已有类+任意名.h 中, 在实现类 已有类.m 中需要实现 已有类接口中的内容, 也需要实现扩展中定义的抽象类.
*/
// OCViewController 的扩展, 在
@interface OCViewController ()
@property (nonatomic, strong) NSMutableArray * labels;
@end
@implementation OCViewController
int nextY = 80;
- (void)viewDidLoad
{
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
// 设置 View 的背景颜色
self.view.backgroundColor = [UIColor grayColor];
// 初始化 数组
self.labels = [NSMutableArray array];
// 创建按钮
UIButton * button_add = [UIButton buttonWithType:UIButtonTypeRoundedRect];
// 设置按钮位置大小
button_add.frame = CGRectMake(30, 30, 60, 40);
// 设置按钮 平时状态的 文本, 可以设置平时状态时的文本
[button_add setTitle:@"添加 Label" forState : UIControlStateNormal];
// 设置按钮点击事件
[button_add addTarget:self action:@selector(addButton) forControlEvents:UIControlEventTouchUpInside];
// 将按钮添加到布局中
[self.view addSubview:button_add];
// 生成删除按钮
UIButton * button_delete = [UIButton buttonWithType:UIButtonTypeRoundedRect];
// 设置按钮的位置大小
button_delete.frame = CGRectMake(230, 30, 60, 40);
// 设置按钮文本
[button_delete setTitle:@"删除 Label" forState:UIControlStateNormal];
// 设置按钮点击事件
[button_delete addTarget:self action:@selector(deleteButton) forControlEvents:UIControlEventTouchUpInside];
// 将按钮添加到布局中
[self.view addSubview:button_delete];
}
// 添加控件方法
- (void) addButton
{
// 生成一个 UILabel 控件
UILabel * label = [[UILabel alloc] initWithFrame:CGRectMake(80, nextY, 160, 30)];
// 给控件设置文字
label.text = @"Label 控件";
// 将控件添加到集合中
[self.labels addObject:label];
// 将控件设置到布局中
[self.view addSubview:label];
// y 坐标自增
nextY += 50;
}
// 删除控件方法
- (void) deleteButton
{
// 删除的前提是控件个数大于 0
if([self.labels count] > 0){
// 将集合中的最后一个 UILabel 控件从布局中删除
[[self.labels lastObject] removeFromSuperview];
// 将 UILabel 控件从集合中删除
[self.labels removeLastObject];
// y 坐标自减, 用于添加控件使用
nextY -= 50;
}
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
@end
-- 演示效果 :
自定义组件简介 :
-- UIView 基类 : 所有的 UI 控件都继承了 UIView 基类, UI 组件在 UIView 提供的空白区域上绘制具体的细节;
-- 适用情况 : 在 IOS 系统提供的组件不满足需求时, 就需要自定义组件;
UIView 基类常用方法简介 :
-- "initWithFrame :" 方法 : UI 控件初始化方法, 用于对 UI 控件额外初始化操作时使用;
-- "initWithCoder :" 方法 : 界面设计文件中加载完该控件后, 自动调用的方法;
-- "drawRect : " 方法 : 自行绘制控件内容, 重写该方法, 在该方法中实现;
-- "layoutSubviews : " 方法 : 精确控制子控件布局;
-- "addAddSubviews : " 方法 : 添加完子控件后回调的方法;
-- "willRemoveSubview : " 方法 : 将要删除子控件时, 回调该方法;
-- "didMoveToSuperview : " 方法 : 把控件添加到父控件完成时 回调该方法;
-- "willMoveToSuperview : " 方法 : 在将要添加到父控件之前, 回调该方法;
-- "didMoveToWindow : " 方法 : 将控件添加到窗口完成时, 回调该方法;
-- "willMoveToWindow : " 方法 : 将控件添加到窗口之前, 回调该方法;
-- "touchesBegan : withEvent : " 方法 : 开始触摸控件时触发的方法;
-- "touchesMoved : withEvent : " 方法 : 手指在控件上移动回调方法;
-- "touchesEnd : withEvent : " 方法 : 手指结束触摸回调方法;
-- "touchesCanceled : withEvent : " 方法 : 取消触摸回调方法;
自定义组件 流程 及 代码示例 :
-- 创建 SingleViewApplication :
-- 查看 Main.storyboard 的控件 : 点击 界面设计文件中的 UIView 根控件, 使用 command + option + 3 打开身份检查器, 由身份检查器上可以看到 其 Custom Class 属性为 UIView, 因此该界面的根控件时 UIView;
-- 创建自定义类 : 选择菜单中的 File -> New File -> Cocoa Touch -> Objective-C Class;
-- OCFollowTouchView.h 代码 :
//
// OCFollowTouchView.h
// FollowTouch
//
// Created by octopus on 15-11-25.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//
#import <Foundation/Foundation.h>
@interface OCFollowTouchView : UIView
@end
-- OCFollowTouchView.m 代码示例 :
//
// OCFollowTouchView.m
// FollowTouch
//
// Created by octopus on 15-11-25.
// Copyright (c) 2015年 www.octopus.org.cn. All rights reserved.
//
#import "OCFollowTouchView.h"
@implementation OCFollowTouchView
int currentX;
int currentY;
- (void) touchesMoved : (NSSet * ) touches withEvent:(UIEvent *)event
{
//获取 UITouch 对象
UITouch * touch = [touches anyObject];
//获取触摸的位置
CGPoint lastPoint = [touch locationInView:self];
currentX = lastPoint.x;
currentY = lastPoint.y;
//重绘 UI 控件
[self setNeedsDisplay];
}
- (void) drawRect:(CGRect)rect
{
//获取绘图上下文对象
CGContextRef ref = UIGraphicsGetCurrentContext();
//设置所绘制的图像为红色
CGContextSetFillColorWithColor(ref, [[UIColor redColor] CGColor]);
//绘制图像
CGContextFillEllipseInRect(ref, CGRectMake(currentX - 10, currentY - 10, 20, 20));
}
@end
-- 将自定义组件设置到 Main.storyboard 中 : 在 Custom Class 属性中, 输入自定义类, 然后点击回车, 默认的 View 就会变成我们设置的自定义类;
-- 演示效果 :
参考文章 :
-- IOS 图标图形 : http://www.zhihu.com/question/20248971 ;
-- IOS 7 官方推荐尺寸 : http://www.cnblogs.com/dyllove98/p/3233845.html ;
-- IOS 8 官方推荐尺寸 : 点击打开链接 ;
-- 图标图像大小 : http://www.cnblogs.com/dyllove98/p/3233845.html ;
Retina 屏幕简介 :
-- 像素 : 高清晰度的视网膜屏幕, 这种屏幕的分辨率是普通非 Retina 屏幕的 2 倍;
-- 市场状况 : 目前 IOS 已经下架了所有的 非 Retina 屏幕的设备, 目前在售的所有设备都是 Retina 设备, 但是之前卖出的许多设备有些不是 Retina 屏幕的;
-- 支持 Retina 屏幕的设备 : 现在在售的所有设备, iphone4 ~ 6S, ipod4, ipad 2 之后的新设备;
-- 不支持 Retina 屏幕设备 : 之前出售的低端 IOS 设备大都是非 Retina 屏幕的, ipod 1, ipod2, ipod3, iphone, iphone3G, iphone3GS, ipad1, ipad2.
-- 素材命名规范 : 非 Retina 屏幕名称为 pictire.png, Retina 屏幕的图片名称是 picture@2x.png;
圆角矩形圆角 :
-- 512 px : 90 px;
-- 114 px : 20 px;
-- 72 px : 12 px;
-- 57 px : 10 px;
-- 58 px : 10 px;
-- 29 px : 9 px;
Retina 屏幕应用图标规格 :
-- iPhone 4S ~ 6 (Retina @2x) : 120 x 120 ;
-- iPhone6 Plus (Retina @3x) : 180 x 180;
-- iPad 和 iPad Mini (Retina @2x) : 152 x 152 ;
非 Retina 屏幕应用图标规格 :
-- iPad 和 iPad Mini (@1x) : 76 x 76 ;
-- iPhone 和 iPod : 57 x 57;
Retina 屏幕启动画面 :
-- iPhone 5 ~ 6 : 640 x 1136;
-- iPhone 4 ~ 4S : 640 x 960;
-- iPad : 1536 x 2048 (纵向), 2048 x 1536 (横向);;
非 Retina 屏幕启动图片 :
-- iPad2 或 iPad Mini : 768 x 1024 (纵向), 1024 x 768 (横向);
IOS 图片设置 : 直接从文件目录将图片拖动到 Xcode 相应的设置中.
-- 设置图标 : 在项目文件视图中, 点击 Images.xcassets, 选中左侧的 AppIcon 设置应用图标, 如下图;
-- 设置启动图片 :