0
点赞
收藏
分享

微信扫一扫

【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )

雪域迷影 2022-03-12 阅读 32



文章目录


  • ​​一. 代码生成控件​​

  • ​​1. 创建设置项目​​

  • ​​( 1 ) 创建项目 ( ① 选择 Create a new Xcode project | ② 创建 Single View Application 项目 | ③ 设置项目信息 | ④ 设置代码路径并创建 )​​
  • ​​( 2 ) 界面设置 ( ① 选中 ViewController | ② 属性查看器 -> Simulated Metrics -> Size | ③ 设置 iPhone 4.7-inch )​​

  • ​​2. 设置按钮及添加事件​​

  • ​​( 1 ) 添加按钮事件 ( Control + 左键 拖动到 代码中 生成按钮方法 )​​
  • ​​( 2 ) 修改按钮文字 ( ① 双击控件 | ② 修改 Tittle 属性 )​​

  • ​​3. 生成 UIView 控件 并 查看 View 层级​​

  • ​​( 1 ) 代码 生成 UIView 控件 ( ① 创建控件 | ② 设置 frame | ③ 设置颜色 | ④ 添加控件 )​​
  • ​​( 2 ) 运行并查看效果 ( 查看 View 层次 )​​

  • ​​4. 代码生成按钮 并 绑定事件​​
  • ​​( 1 ) 代码生成 按钮 ( ① 创建按钮控件 | ② 设置 frame | ③ 设置文字( 颜色 ) | ④ 设置背景( 前景 )图片 | ⑤ 绑定事件 | ⑥ 添加控件 )​​

  • ​​二. UIView 属性 和 子控件操作​​

  • ​​( 1 ) 创建 设置 应用 ( ① 创建应用 | ② 设置界面尺寸 )​​
  • ​​( 2 ) 设置 Main.storyboard UI 界面 ( ① 背景 )​​
  • ​​( 3 ) 在 ViewController.m 关联 控件变量 ( ① 按住 Control 拖拽 控件 到 @interface 代码块中 | ② Connect 对话框 设置 名称 类型 )​​
  • ​​( 4 ) 生成 子组件 代码 ( ① 生成子组件 | ② 设置子组件属性 | ③ 设置子组件 frame 属性 [ 随机位置生成 ] | ④ 添加子组件到父容器中 )​​
  • ​​( 5 ) 删除 子组件 代码 ( ① 获取子组件数组 | ② 使用 for in 循环删除子组件 | ③ isKindOfClass 判定组件类型 )​​
  • ​​( 6 ) 删除 指定 Tag 的控件 的 代码 ( ① 调用父控件的 viewWithTag 方法 | ② )​​
  • ​​( 7 ) UIView 常用方法属性 ( ① tag 属性 | ② removeFromSuperView 方法 | ③ addSubView 方法 | ④ viewWithTag 方法 | ⑤ frame 属性 | ⑥ transform 属性 )​​
  • ​​( 8 ) 效果展示​​

  • ​​三. 图片浏览器​​

  • ​​1. 应用创建 设置​​
  • ​​( 1 ) 创建 设置 应用 ( ① 创建应用 | ② 设置界面尺寸 )​​
  • ​​2. UI 控件 设置​​

  • ​​( 1 ) 设置 Main.storyboard ( 拖入相关控件 )​​
  • ​​( 2 ) 关联 Main.storyboard 与 ViewController.m ( ① 关联控件变量 | ② 关联方法 | ③ 设置相关的成员变量 )​​

  • ​​3. 相关知识点​​

  • ​​( 1 ) UILabel 设置 ( ① 换行设置 | ② 设置行高 | ③ 宽高控制 )​​
  • ​​( 2 ) UIButton 启用 禁用 ( ① enabled 属性 YES NO )​​
  • ​​( 3 ) NSArray 和 NSMutableDictionary 存储数据 ( ① NSArray 数组 | ② 字典 )​​

  • ​​4. 代码逻辑 与 完整代码​​

  • ​​( 1 ) 代码逻辑 ( ① 边界处理 | ② 按钮处理 | ③ UILabel 文字切换 | ④ UIImageView 图片切换 )​​
  • ​​( 2 ) 完整代码​​
  • ​​( 3 ) 效果展示​​


  • ​​四. Storyboard 添加 配置 及 相关知识点​​

  • ​​1. 添加 新界面 ( ① 新建 Storyboard | ② 配置 Storyboard | ③ 新建ViewController 代码 )​​

  • ​​( 1 ) 添加 Storyboard ( ① File -> New -> File | ② iOS -> User Interface -> Storyboard | ③ General -> Deployment -> Main Interface 配置 Storyboard )​​
  • ​​( 2 ) Storyboard 设置 ( ① 拖动箭头设置启动界面 | ② View Controller 的 Is Initial View Controller 勾选框 设置启动界面 | ③ 关联 ViewController 代码 )​​
  • ​​( 3 ) 新建 ViewController.m 文件 ( ① File -> New -> File | ② iOS -> Source -> Cocoa Touch Class | ③ Storyboard 中 身份查看器 配置 Class )​​

  • ​​2. Storyboard 相关知识点 ( ① 删除 Storyboard | ② Storyboard 本质 )​​

  • ​​( 1 ) 删除 Storyboard ( ① 删除文件及引用 | ② 删除引用 文件保留 )​​
  • ​​( 2 ) Storyboard 本质 ( XML 文本文件 )​​

  • ​​3. iOS 应用启动步骤简介​​
  • ​​( 1 ) iOS 应用启动步骤​​

  • ​​五. Bundle 简介​​

  • ​​( 1 ) Bundle 简介​​
  • ​​( 2 ) 图片放置 位置 ( ① 放在 Assets.xcassets [推荐] | ② 放在根目录[不推荐] )​​
  • ​​( 3 ) NSBundle 使用 ( ① 获取 NSBundle 对象 | ② 获取 Bundle 目录下 某文件的 全路径 )​​

  • ​​六. Property List 简介​​

  • ​​( 1 ) Property List 创建 ( ① New File | ② iOS -> Resource -> Property List | ③ 数据设置 | ④ 类型设置 )​​
  • ​​( 2 ) 获取 Property List 数据 ( ① 获取 Bundle PList 路径 | ② dictionaryWithContentsOfFile 初始化字典 | ③ 查看数据 )​​
  • ​​( 3 ) Property List 多种类型 数据 设置 获取 ( ① 设置 Root 类型为 NSArray | ② 设置 多类型 数据 | ③ 获取 PList 的 Bundle 路径 | ④ 初始化 数组 | ⑤ 打断点查看数据 )​​

  • ​​七. 优化 图片 浏览器 ( ① 使用 PList | ② 懒加载 )​​

  • ​​( 1 ) 使用 PList 存储 数据 ( ① 创建 PList 文件 | ② 数据准备 | ③ 获取 Bundle 路径 | ④ 获取 PList 的 Bundle 路径 | ⑤ PList -> 数组 )​​
  • ​​( 2 ) 懒加载 优化 ( ① 在 get 方法中加载数据 | ② 如果为 空 才 加载 )​​

  • ​​八. UIImageView 播放动画 及 内存优化​​

  • ​​1. 动画 播放​​

  • ​​( 1 ) UIImageView 动画 相关属性 ( ① 图片数组 | ② 动画时长 | ③ 重复次数 )​​
  • ​​( 2 ) UIImageView 动画 相关方法 ( ① 开始播放 | ② 停止播放 | ③ 是否正在播放 )​​
  • ​​( 3 ) UIImageView 动画 执行流程 ( ① 准备 UIImage 数组 | ② 设置动画参数 UIImage数组 时长 重复次数 | ③ 启动动画 )​​

  • ​​2. 图片内存 优化​​

  • ​​( 1 ) UIImageView 动画 内存 查看 ( ① Debug Navigator 查看内存 | ② 查看 动画播放前后的内存变化 | ③ 分析内存不释放的原因 )​​
  • ​​( 2 ) UIImage 内存分析 ( ① 使用 UIImage imageNamed:图片名称 加载图片 | ② 使用 UIImage imageWithContentsOfFile:Bundle路径名 加载图片 )​​
  • ​​( 3 ) 内存优化 的 动画 执行 完整流程 ( ① 准备 UIImage 数组 | ② 设置动画参数 UIImage数组 时长 重复次数 | ③ 启动动画 | ④ 异步设置图片数组为 nil )​​
  • ​​( 4 ) NSBundle pathForResource 为 nil 解决方案 ( ① 拖入目录 选择 Create gropus | ② 查看 Xcode 项目 配置 -> Build phases 的 Bundle 配置 )​​
  • ​​( 5 ) 效果展示​​







博客相关资源




一. 代码生成控件




1. 创建设置项目



( 1 ) 创建项目 ( ① 选择 Create a new Xcode project | ② 创建 Single View Application 项目 | ③ 设置项目信息 | ④ 设置代码路径并创建 )



项目创建流程 :​ ① 选择 Create a new Xcode project , ② 创建 Single View Application 项目 , ③ 设置项目信息 , ④ 设置代码路径并创建 ;


  • 1.选择项目创建 :​ 在 Xcode 欢迎界面中 , 点击 ​​Create a new Xcode project​​ 选项 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle
  • 2.选择项目类型 :​ 在 ​​Choose a template for your new project​​ 对话框中 , 选择项目类型 iOS -> Application -> ​Single View Application​ 项目 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_控件_02
  • 3.设置项目名称 :​ 输入 项目 相关的 信息 , 主要是 项目名称 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_03
  • 4.选择代码存放路径 :​ ​选择代码存放路径​ , 点击 ​​Create​​ 按钮, 创建项目 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_04


( 2 ) 界面设置 ( ① 选中 ViewController | ② 属性查看器 -> Simulated Metrics -> Size | ③ 设置 iPhone 4.7-inch )

界面设置 :​ 需要自己手动设定一个 屏幕尺寸 ;


  • 1.创建后的默认 UI 设计界面 :​ 创建项目完成后, Main.storyboard 中显示的是一个正方形的 界面 , 需要将其设置为 一个 手机形状的 UI 界面 ;
  • 2.设置成 4.7 寸屏幕大小 :​ ​① 选中 ViewController 图标​ , ​② 设置 右侧 的 属性查看器 -> Simulated Metrics -> Size​ , ​③ 选择 iPhone 4.7-inch 屏幕大小​ ;

【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_05

  • 3.iPhone 尺寸 :​ ① iPhone 5 , 5S , SE : 4-inch ( 对角线长度 ) , ② iPhone 6 , 6S , 7 : 4.7-inch ( 对角线长度 ) , ③ iPhone 6 Plus , 6s Plus , 7Plus : 5.5-inch ( 对角线长度 ) ;



2. 设置按钮及添加事件



( 1 ) 添加按钮事件 ( Control + 左键 拖动到 代码中 生成按钮方法 )

添加按钮事件 :


  • 1.添加按钮 :​ 向 Main.storyboard 中拖入按钮控件 ;
  • 2.生成按钮方法 :


    • ① 打开辅助编辑器 :​ 同时显示 Main.storyboard 和 ViewController.m 代码 ;
    • ② 拖动生成方法 :​ 按住 Control 键 , 左键点击 Button 控件不放 , 然后拖动到 ViewController.m 代码空白处 ;
      【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_06
    • ③ 设置方法属性 :


      • a . 在 Name 栏 设置 方法名称 ;
      • b . 在 Event 栏 设置 方法触发动作 ;
      • c . Touch Up Inside 即 点击方法 ;
      • d . 在 Arguments 栏 设置需要传入的参数 :


        • 1> 如果在方法中需要使用按钮参数 , 则选择 Sender ,
        • 2> 如果需要 按钮 和 事件 参数 , 选择 Sender and Event ,
        • 3> 如果不需要参数 , 设置 None 即可 ;
          【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle_07




    • ④ 生成方法 :​ 点击 上述 对话框中的 Connect 按钮 , 即可生成对应方法 ;
      【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_PList_08


  • 5.生成的代码 :

- (IBAction)generateView {
}


( 2 ) 修改按钮文字 ( ① 双击控件 | ② 修改 Tittle 属性 )



修改按钮文字 :


  • 1.方法1 :​ 点击选中 UIButton 控件, 然后再右侧的属性查看器中的 Tittle 属性中修改按钮文字 ;
  • 2.方法2 :​ 在 Main.storyboard 中双击 UIButton 控件 , 修改 按钮文字 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_09
  • 3.修改后 :【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_PList_10



3. 生成 UIView 控件 并 查看 View 层级



( 1 ) 代码 生成 UIView 控件 ( ① 创建控件 | ② 设置 frame | ③ 设置颜色 | ④ 添加控件 )



代码生成 UIView 控件 :

  • 1.创建 UIView 控件 :​ 使用 UIView 的 alloc init 方法 , 创建 UIView 控件 ;
//1. 创建 View 控件 , 使用 alloc init 方法
UIView * newView = [[UIView alloc] init];
  • 2.修改 Frame 属性 :​ 使用 CGRectMake 方法创建 CGRect 结构体变量 , 并设置给 UIView 控件的 frame 属性 ;
//2. 修改 控件 的 Frame 属性
newView.frame = CGRectMake(100, 100, 100, 100);
  • 3.设置颜色 :​ 设置 UIView 的 backgroundColor 属性 , 传递一个 UIColor 对象 ;
//3. 为 控件 设置一个颜色值
newView.backgroundColor = [UIColor redColor];
  • 4.添加 UIView 控件 :​ 获取当前 ViewController 的 根 View 组件 , 然后将 生成的 UIView 控件添加到 该 根 View 控件中 ;
//4. 将 控件 添加到 View 中
[self.view addSubview:newView];
  • 5.总体代码 :
//
// ViewController.m
// 1.GenerateUIViewByCode
//
// Created by octopus on 19/2/3.
// Copyright © 2019年 han. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (IBAction)generateView {

//1. 创建 View 控件 , 使用 alloc init 方法
UIView * newView = [[UIView alloc] init];

//2. 修改 控件 的 Frame 属性
newView.frame = CGRectMake(100, 100, 100, 100);

//3. 为 控件 设置一个颜色值
newView.backgroundColor = [UIColor redColor];

//4. 将 控件 添加到 View 中
[self.view addSubview:newView];

}


@end


( 2 ) 运行并查看效果 ( 查看 View 层次 )



运行并查看效果 :



1.运行程序 :​ 点击 ​​Build and then run the current scheme​​ 按钮 , 运行虚拟机 ; 然后点击 10 次 生成 10 个 UIView 控件 ;
【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_11



2.查看 创建的 View 层次 :​ 注意 该 步骤 必须在虚拟机运行之后才能操作 , 点击下方的 ​​Debug View Hierarchy​​ 按钮 , 即可查看 View 层次 ;
【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_12
【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_13



3.查看 层次 :​ 鼠标 按住 界面 , 左右拖动 , 即可看到生成的 10 个 UIView 的层次 ;
【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_14





4. 代码生成按钮 并 绑定事件



( 1 ) 代码生成 按钮 ( ① 创建按钮控件 | ② 设置 frame | ③ 设置文字( 颜色 ) | ④ 设置背景( 前景 )图片 | ⑤ 绑定事件 | ⑥ 添加控件 )



代码生成 按钮 :

  • 1.创建按钮控件 :​ 创建 UIButton 控件时 , 需要制定按钮类型 , 这里创建 Custom 类型的控件 ;
//1. 创建 某种 Type 的 按钮 , 这里创建 UIButtonTypeCustom 类型的 按钮
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];
  • 2.设置 frame 属性 :​ 使用 ​​CGRectMake​​​ 方法创建 CGRect 结构体变量 , 并赋值给 按钮的 ​​frame​​ 属性 ;
//2. 设置 Frame 属性
button.frame = CGRectMake(100, 100, 100, 100);
  • 3.设置按钮文字 :​ 调用 ​​setTittle​​ 方法 , 设置生成的按钮的文字 ;
//3. 设置 文字 , 这里需要根据不同的状态设置显示的文字 , 这里只设置 UIControlStateNormal 状态的文字
[button setTitle:@"生成按钮" forState:UIControlStateNormal];
  • 4.设置文字颜色 :​ 调用 ​​setTittleColor​​ 方法 , 设置按钮文字的颜色 ;
//4. 设置 文字颜色 , 这里设置普通状态时的 文字 颜色
[button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];
  • 5.设置背景图片 :


    • ① 添加图片资源 :​ 选中 Assets.xcassets , 从 Finder 中拖动图片资源 到 其中 ;
      【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_控件_15
    • ② 设置背景图片 :​ 调用 ​​setBackgroundImage​​ 方法 , 设置背景图片 ;


//5. 设置 背景图片
[button setBackgroundImage:[UIImage imageNamed:@"button_bg"] forState:UIControlStateNormal];
  • 6.绑定事件 :​ 创建一个方法 , 然后调用 UIButton 的 ​​addTarget​​ 绑定该方法 ;
//添加按钮事件 
//5. 设置 背景图片
[button setBackgroundImage:[UIImage imageNamed:@"button_bg"] forState:UIControlStateNormal];

// 创建的按钮事件
//为 生成的 按钮 绑定 点击事件
- (void) bindMethod{
NSLog(@"绑定事件触发");
}
  • 7.添加控件 :​ 获取父控件 ​​self.view​​​ , 调用父控件的 ​​addView​​ 方法 添加控件 ;
//7. 将 UIButton 添加到 根 View 中
[self.view addSubview:button];
  • 8.完整代码示例 :
//
// ViewController.m
// 1.GenerateUIViewByCode
//
// Created by octopus on 19/2/3.
// Copyright © 2019年 han. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

//该方法在 UIViewController 创建完成 , 并开始加载到内存中时 , 在这个时刻执行该 viewDidLoad 方法
//一般情况下 是 在该方法中 执行 初始化数据 , 创建控件 等操作 ;
- (void)viewDidLoad {
[super viewDidLoad];

//1. 创建 某种 Type 的 按钮 , 这里创建 UIButtonTypeCustom 类型的 按钮
UIButton * button = [UIButton buttonWithType:UIButtonTypeCustom];

//2. 设置 Frame 属性
button.frame = CGRectMake(100, 100, 100, 100);

//3. 设置 文字 , 这里需要根据不同的状态设置显示的文字 , 这里只设置 UIControlStateNormal 状态的文字
[button setTitle:@"生成按钮" forState:UIControlStateNormal];

//4. 设置 文字颜色 , 这里设置普通状态时的 文字 颜色
[button setTitleColor:[UIColor redColor] forState:UIControlStateNormal];

//5. 设置 背景图片
[button setBackgroundImage:[UIImage imageNamed:@"button_bg"] forState:UIControlStateNormal];

//6. 绑定 事件
[button addTarget:self action:@selector(bindMethod) forControlEvents:UIControlEventTouchUpInside];

//7. 将 UIButton 添加到 根 View 中
[self.view addSubview:button];
}

//为 生成的 按钮 绑定 点击事件
- (void) bindMethod{
NSLog(@"绑定事件触发");
}


- (IBAction)generateView {

//1. 创建 View 控件 , 使用 alloc init 方法
UIView * newView = [[UIView alloc] init];

//2. 修改 控件 的 Frame 属性
newView.frame = CGRectMake(100, 100, 100, 100);

//3. 为 控件 设置一个颜色值
newView.backgroundColor = [UIColor redColor];

//4. 将 控件 添加到 View 中
[self.view addSubview:newView];

}


@end




二. UIView 属性 和 子控件操作




( 1 ) 创建 设置 应用 ( ① 创建应用 | ② 设置界面尺寸 )



创建 设置 应用 :


  • 1.创建应用 :​ ​① 点击 Create a new Xcode project 应用​ ; ​② 创建 Single View Application 项目​ ; ​③ 设置 项目名称 , 组织标识 等信息​ ; ​④ 设置代码路径​ ; 参考 一 . 1 . ( 1 ) 章节内容 ;
  • 2.设置界面尺寸 :​ ​① Main.storyboard 界面中 选中 ViewController​ ; ​② 在 属性查看器中设置 Size 属性为 iPhone 4.7-inch​ ; ​③ 在 文件查看器 中取消 Use Auto Layout 选项​ ;


( 2 ) 设置 Main.storyboard UI 界面 ( ① 背景 )



设置 Main.storyboard 界面 :


  • 1.设置背景颜色 :​ 选中 ViewController 下的 根 View 控件 , 在 属性查看其中 设置 Background 属性 , 设置一个颜色 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_16
  • 2.向界面中添加一个 View 控件 :​ 添加 View 控件 当做容器 , 设置尺寸 300 x 300 , 居中显示 , 之后将生成的 UIView 控件放在该 容器 中 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_控件_17
  • 3.添加按钮 :​ 添加两个按钮 , 两个按钮的功能分别是 生成 UIView 控件 和 清空 UIView 控件 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_18


( 3 ) 在 ViewController.m 关联 控件变量 ( ① 按住 Control 拖拽 控件 到 @interface 代码块中 | ② Connect 对话框 设置 名称 类型 )



关联 ViewController.m 变量 :



1.拖线关联 :​ 按住 Control 键 不放 , 然后拖线到 ViewController.m 中的 @interface 代码块中 , 之后会弹出 Connect 对话框 ;
【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_PList_19



2.设置变量信息 :​ 在 Connect 对话框中 设置 名称 和 类型 , 然后点击 Connect 按钮 , 然后生成代码 ;
【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_20



3.查看生成的代码 :​ 点击 Connect 按钮后 , 会自动根据 类型 和 变量名 生成 对应的 代码 ;
【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_21




( 4 ) 生成 子组件 代码 ( ① 生成子组件 | ② 设置子组件属性 | ③ 设置子组件 frame 属性 [ 随机位置生成 ] | ④ 添加子组件到父容器中 )



生成子组件代码 :

  • 1.创建子组件 :​ 调用 UILabel 的 alloc init 方法 , 生成子组件 ;
//1. 创建 UILabel 类型子组件
UILabel * label = [[UILabel alloc] init];
  • 2.设置子组件 :​ 设置子组件信息 , 为 UILabel 设置文字 ;
//2. 设置 子组件 信息
label.text = @"生成的子组件";
  • 3.设置 frame 属性 :​ 设置随机的位置 , ​使用 arc4random_uniform 函数生成随机数​ , x 坐标 和 y 坐标要使用不同的 随机值 , 之后设置一个 宽高 即可 ;
//3. 设置 frame 属性 , 主要是设置 位置 和 大小 , 这里针对位置 设置一个随机位置
// 随机数使用 arc4random_uniform 是用于生成随机数的函数
label.frame = CGRectMake(arc4random_uniform(200), arc4random_uniform(280), 150, 20);
  • 4.添加到父容器 :​ 将代码添加到 父容器 中 ;
//4. 添加到 Container 中
[self.Container addSubview:label];
  • 5.整体代码 :
// 添加 子组件
// ① 添加组件 : 调用 父容器组件 的 addSubview 方法添加子组件
- (IBAction)generateView:(UIButton *)sender {
//1. 创建 UILabel 类型子组件
UILabel * label = [[UILabel alloc] init];

//2. 设置 子组件 信息
label.text = @"生成的子组件";

//3. 设置 frame 属性 , 主要是设置 位置 和 大小 , 这里针对位置 设置一个随机位置
// 随机数使用 arc4random_uniform 是用于生成随机数的函数
label.frame = CGRectMake(arc4random_uniform(200), arc4random_uniform(280), 150, 20);

//4. 添加到 Container 中
[self.Container addSubview:label];
}


( 5 ) 删除 子组件 代码 ( ① 获取子组件数组 | ② 使用 for in 循环删除子组件 | ③ isKindOfClass 判定组件类型 )



删除子组件代码 :

  • 1.获取子组件数组 :​ 访问 父容器的 subViews 属性 即可获取 父容器所有的子组件, 该属性在 UIView 中定义 ;
self.Container.subviews
  • 2.删除子组件 :​ 使用 removeFromSuperView 方法 来 删除控件 ;
[view removeFromSuperview];

  • 3.控件类型准备 :​ 父容器中添加 UIButton 组件 , 用于区分 UILabel 和 UIButton , 这里只删除 UILabel 控件 ;
  • 4.判定组件类型 :​ 使用 isKindOfClass 判断 对象 类型 ;

[view isKindOfClass:[UIButton class]]
  • 5.删除所有 UILabel 控件 :​ 使用 for in 循环 删除所有的 UILabel 控件 ;
//1. 获取所有的子组件数组 , 直接遍历删除每个子组件即可 , 注意不删除 UIButton 类型的组件
for(UIView * view in self.Container.subviews){
[view removeFromSuperview];
}
  • 6.完整代码 :
// 删除 子组件
// ① 删除方法 : 使用 removeFromSuperView 方法 来 删除控件
// ② 获取子组件 : 访问 父容器的 subViews 属性 即可获取 父容器所有的子组件, 该属性在 UIView 中定义
// ③ 判定组件类型 : 通过调用 [uiView isKindOfClass:[UIButton class]] 方法可以判断 uiView 是否是 UIButton 类型的组件
- (IBAction)clearView:(UIButton *)sender {
//1. 获取所有的子组件数组 , 直接遍历删除每个子组件即可 , 注意不删除 UIButton 类型的组件
for(UIView * view in self.Container.subviews){
[view removeFromSuperview];
}

}


( 6 ) 删除 指定 Tag 的控件 的 代码 ( ① 调用父控件的 viewWithTag 方法 | ② )



删除指定 Tag 的控件 :


  • 1.生成方法 :​ 按住 Control 拖线关联 , 在 Connect 对话框 设置方法参数 , 生成方法 ;
  • 2.控件准备 :​ 拖入 3 个 Label 控件 , 分别设置 Tag 属性 1 , 2, 3 ;
  • 3.获取子控件方法 :​ 调用父控件的 viewWithTag 方法 获取指定 Tag 属性的子组件 , ​如果 父控件 的 Tag 与 子控件的 Tag 相同 , 也能获取到 , 并且优先获取父控件​ ; ​如果删除父控件 , 那么其子控件也会被全部删除 ;
  • 4.删除控件 :​ 调用获取的子控件的 ​​removeFromSuperview​​ 方法 , 删除控件 ;
  • 5.代码示例 :

- (IBAction)clearTag:(UIButton *)sender {

//1. 获取指定 Tag 的控件
UILabel * label1 = [self.Container viewWithTag:1];
UILabel * label2 = [self.Container viewWithTag:2];
UILabel * label3 = [self.Container viewWithTag:3];

//2. 删除 子控件
[label1 removeFromSuperview];
[label2 removeFromSuperview];
[label3 removeFromSuperview];

}


( 7 ) UIView 常用方法属性 ( ① tag 属性 | ② removeFromSuperView 方法 | ③ addSubView 方法 | ④ viewWithTag 方法 | ⑤ frame 属性 | ⑥ transform 属性 )



UIView 常用方法属性 :


  • 1.tag 属性 :​ 用于标示控件 , 不能改变控件外观 ;
  • 2.removeFromSuperView 方法 :​ 将 子控件 从 父控件 删除 ;
  • 3.addSubView 方法 :​ 向 父控件 中 添加子控件 , 还需要设置 Frame属性 才能显示 ;
  • 4.viewWithTag 方法 :​ 获取 指定 Tag 属性的 子控件 , 如果 父控件 也是这个 Tag , 那么优先获取自己 ;
  • 5.frame 属性 :​ 定义控件的位置 和 尺寸 ;
  • 6.transform 属性 :​ 改变 位置 , 大小 , 旋转角度 属性 ; 有两种使用方式 , 一种是 直接创建指定所有参数 ; 第二种 可以在之前的基础上进行增量修改 ;


( 8 ) 效果展示



效果展示 :




三. 图片浏览器




1. 应用创建 设置



( 1 ) 创建 设置 应用 ( ① 创建应用 | ② 设置界面尺寸 )



创建 设置 应用 :


  • 1.创建应用 :​ ​① 点击 Create a new Xcode project 应用​ ; ​② 创建 Single View Application 项目​ ; ​③ 设置 项目名称 , 组织标识 等信息​ ; ​④ 设置代码路径​ ; 参考 一 . 1 . ( 1 ) 章节内容 ;
  • 2.设置界面尺寸 :​ ​① Main.storyboard 界面中 选中 ViewController​ ; ​② 在 属性查看器中设置 Size 属性为 iPhone 4.7-inch​ ; ​③ 在 文件查看器 中取消 Use Auto Layout 选项​ ;



2. UI 控件 设置



( 1 ) 设置 Main.storyboard ( 拖入相关控件 )



设置 Main.storyboard 界面 :


  • 1.准备对应控件 :​ 根据需求 拖入 对应的控件 , 并设置相关属性 ; 这里就不再详细介绍 , 贴一张 设置好的控件 和 默认文字 图片 展示图 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_23
  • 2.准备素材 :​ 拖入 显示的图片 和 箭头 等 图片资源 ;


( 2 ) 关联 Main.storyboard 与 ViewController.m ( ① 关联控件变量 | ② 关联方法 | ③ 设置相关的成员变量 )



关联 Main.storyboard 与 ViewController.m :

  • 1.关联控件变量 :​ 按住 Control 键 , 将控件拖动到 ​​@interface​​ 代码区域 , 在弹出的对话框中输入控件命令 和 选择控件类型 , 即可生成控件关联的变量 ;
// 显示图片的索引
@property (weak, nonatomic) IBOutlet UILabel *indexLabel;

// 显示图片
@property (weak, nonatomic) IBOutlet UIImageView *Image;

// 左箭头按钮
@property (weak, nonatomic) IBOutlet UIButton *lastButton;

// 右箭头按钮
@property (weak, nonatomic) IBOutlet UIButton *nextButton;

// 图片介绍
@property (weak, nonatomic) IBOutlet UILabel *imageDescription;
  • 2.关联 UIButton 点击方法 :​ 按住 Control 键 , 将控件拖动到 ​​@implementation​​ 代码区域 , 在弹出的对话框中 输入方法名称 , 选择控件类型 , 选择触发操作 , 选择传入的参数 即可生成点击方法 ;
// 上一张 图片
- (IBAction)lastImage:(UIButton *)sender {
}

// 下一张 图片
- (IBAction)nextImage:(UIButton *)sender {
}



3. 相关知识点



( 1 ) UILabel 设置 ( ① 换行设置 | ② 设置行高 | ③ 宽高控制 )



UILabel 设置 :


  • 1.设置自动换行 :​ 在 UILabel 中有 ​​Lines​​ 属性 , 可以设置显示 几行 文字 , ​Lines 属性 设置 0 就会自动进行换行​ ;
  • 2.UILabel 行高设置 :​ 自动换行的前提是 , UILabel 有对应的多行的行高 , 如果 UILabel 高度很小只能显示 1 行 , 那么 UILabel 自动换行 也只是显示 1 行 , 因此 ​如果需要自动换行的话 , 需要给 UILabel 设置足够的行高​ ;

【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_24

  • 3.宽高控制 :​ UILabel 的 宽度 和 高度 都需要把握好 , 宽度如果不够 , 后面会出现 … 的 省略情况 , 同理 高度不足 也会出现这种情况 ;


( 2 ) UIButton 启用 禁用 ( ① enabled 属性 YES NO )



UIButton 的启用 禁用 :


  • 1.enabled 属性 ( 可视化修改 ) :​ 在 UIButton 的 属性查看器中 Control 模块下 , Enabled 属性用来设置 按钮是否可用 , 如果 勾选 按钮可用 , 反之 按钮 会变灰 不可用 ;
  • 2.源码中查看 enabled 属性 :​ 默认是 YES 可用 , 如果设置为 NO 不可用 ;

@property(nonatomic,getter=isEnabled) BOOL enabled;                                  // default is YES. if NO, ignores touch events and subclasses may draw differently
  • 3.代码修改 enabled 属性 :​ 方法中 直接修改 sender.enabled 属性值 为 YES 或 NO , 即可修改 UIButton 是否可用 ;


( 3 ) NSArray 和 NSMutableDictionary 存储数据 ( ① NSArray 数组 | ② 字典 )



NSArray 和 NSMutableDictionary 存储数据 :


  • 1.使用方法 :​ 定义一个 NSArray 成员变量 , 其每个元素都是一个 NSMutableDictionary 字典 , 字典中存放 两个 键值对 , 分别是 图片名称 和 图片描述 ;
  • 2.定义 NSArray 成员变量 :​ 使用 @property 定义 , 注意

// 用于保存所有图片数据的数组 , 每个数组元素存放字典数据
@property (strong, nonatomic) NSArray * pics;
  • 3.初始化 NSArray 成员变量 :​ 先逐个创建对应的 ​​NSMutableDictionary​​​ 字典 , 然后将字典 当做元素 放入 ​​NSArray​​ 数组中 , 数组中的每个元素都是一个 字典 ;
// 1. 初始化图片名称数组
NSMutableDictionary * d1 = [NSMutableDictionary dictionary];
d1[@"pic"]=@"1_Mustang";
d1[@"des"]=@"Mustang(福特野马)是美国福特汽车公司推出的2005款野马汽车,最高时速232.2公里,设计源自2003 年汽车巡回展上的概念车,野马的诞生标志着美国仅存的大马力轿车获得了重生。";
NSMutableDictionary * d2 = [NSMutableDictionary dictionary];
d2[@"pic"]=@"2_Prado";
d2[@"des"]=@"普拉多是一款进口ORV,源于丰田享誉全球的LAND CRUISER车系,1996年丰田正式将LAND CRUISER FJ90命名为PRADO普拉多,即真正意义上的第一代普拉多。";
NSMutableDictionary * d3 = [NSMutableDictionary dictionary];
d3[@"pic"]=@"3_Camaro";
d3[@"des"]=@"雪佛兰 科迈罗(英文名:Chevrolet Camaro)设计于1960年,目前共发展了六代。1966年9月26日发布的1967款Camaro是以雪佛兰Nova为原型而设计的。";
NSMutableDictionary * d4 = [NSMutableDictionary dictionary];
d4[@"pic"]=@"4_LandCru";
d4[@"des"]=@"兰德酷路泽【陆地巡洋舰】是丰田汽车出品的LAND CRUISER 200,是丰田公司生产的一款进口ORV越野车(Off Road Vehicle) [1] ,它的外观在继承原有设计DNA的同时向具备新时代的“新鲜感·先进性”风格进化。是四轮驱动,轴距2850毫米,四轮碟刹的硬派越野车。";
NSMutableDictionary * d5 = [NSMutableDictionary dictionary];
d5[@"pic"]=@"5_Mondeo";
d5[@"des"]=@"福特蒙迪欧(Mondeo)是一款长安福特旗舰车型,不仅搭载多项创新科技,并在至臻品质、动力系统以及安全性能等方面实现全面提升。";

// 将字典放入数组中
self.pics = @[d1, d2, d3, d4, d5];
  • 4.获取 NSArray 中的元素 :​ 根据数组下标 [int] 获取数组中的元素 ;
// ① 获取对应的数据 字典
NSMutableDictionary * d = self.pics[self.index - 1];
  • 5.从 NSMutableDictionary 字典 中获取对应元素 :​ 获取 ​​NSMutableDictionary * d​​​ 字典中的 “pic” 键 对应的值 ​​d[@"pic"]​​​ , 获取 字典 中 “des” 键 对应的值 ​​d[@"des"]​



4. 代码逻辑 与 完整代码



( 1 ) 代码逻辑 ( ① 边界处理 | ② 按钮处理 | ③ UILabel 文字切换 | ④ UIImageView 图片切换 )



代码逻辑 :

  • 1.索引边界处理 :​ 索引范围 1 ~ 5 , 不能 小于 1 或者 大于 5 , 这里需要进行限制 ; 点击 向左 切换时 索引自减 , 当 小于等于 1 时 , 索引值 仍为 1 ; 点击向右切换时 , 索引 自增 , 当 大于等于 5 时 , 索引值 仍为 5 ;
// 设置图片索引 , 注意不能 小于 1 , 边界控制
self.index -- ;
if(self.index <= 1){
self.index = 1;
}

...
// 设置图片索引 , 注意不能 超过 5 , 边界控制
self.index ++ ;
if(self.index >= self.pics.count){
self.index = (int)self.pics.count;
}
  • 2.按钮处理 :​ UIButton 的 ​enabled 属性​ 设置 ​YES​ ​NO​ 值 来 设置 ​可用​ ​禁用​ 属性 ; 显示第一张图片时 , 左 按钮 禁用 , 显示 最后一张图片时 , 右 按钮 禁用 ; 其它情况 左右按钮 都可用 ;
// 1. 设置按钮 禁用 启用 , index 为 1 和 5 时 分别启用 和 禁用 指定的按钮 , 其它情况下可以使用两个按钮
if(self.index == 1){
self.lastButton.enabled = NO;
self.nextButton.enabled = YES;
}else if(self.index == self.pics.count){
self.lastButton.enabled = YES;
self.nextButton.enabled = NO;
}else{
self.lastButton.enabled = YES;
self.nextButton.enabled = YES;
}
  • 3.UILabel 文字切换 :​ 直接 修改 UILabel 的 text 属性 ;
// ④ 设置 文字 描述
self.imageDescription.text = d[@"des"];
  • 4.文字生成格式 :​ 使用 NSString 的 ​​stringWithFormat​​ 方法 , 设置一个 字符串格式 , 使用 通配符 进行 数据替换 ; 注意 NSArray 的 count 的通配符是 %lu ;
// ② 设置提示 UILabel 文字 , 拼接字符串 , 1/5
self.indexLabel.text = [NSString stringWithFormat:@"%d/%lu", self.index, self.pics.count];
  • 5.UIImageView 图片切换 :​ 通过 调用 UIImage 的 imageNamed 方法 , 获取 UIImage 对象 ;
// ③ 设置 图片 显示
self.Image.image = [UIImage imageNamed:d[@"pic"]];


( 2 ) 完整代码



完整代码 :

//
// ViewController.m
// 3.ImageBrowser
//
// Created by octopus on 19/2/11.
// Copyright © 2019年 han. All rights reserved.
//

#import "ViewController.h"

@interface ViewController ()

// 显示图片的索引
@property (weak, nonatomic) IBOutlet UILabel *indexLabel;

// 显示图片
@property (weak, nonatomic) IBOutlet UIImageView *Image;

// 左箭头按钮
@property (weak, nonatomic) IBOutlet UIButton *lastButton;

// 右箭头按钮
@property (weak, nonatomic) IBOutlet UIButton *nextButton;

// 图片介绍
@property (weak, nonatomic) IBOutlet UILabel *imageDescription;

// 当前图片索引
@property (assign, nonatomic) int index;

// 用于保存所有图片数据的数组 , 每个数组元素存放字典数据
@property (strong, nonatomic) NSArray * pics;


@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];

// 1. 初始化图片名称数组
NSMutableDictionary * d1 = [NSMutableDictionary dictionary];
d1[@"pic"]=@"1_Mustang";
d1[@"des"]=@"Mustang(福特野马)是美国福特汽车公司推出的2005款野马汽车,最高时速232.2公里,设计源自2003 年汽车巡回展上的概念车,野马的诞生标志着美国仅存的大马力轿车获得了重生。";
NSMutableDictionary * d2 = [NSMutableDictionary dictionary];
d2[@"pic"]=@"2_Prado";
d2[@"des"]=@"普拉多是一款进口ORV,源于丰田享誉全球的LAND CRUISER车系,1996年丰田正式将LAND CRUISER FJ90命名为PRADO普拉多,即真正意义上的第一代普拉多。";
NSMutableDictionary * d3 = [NSMutableDictionary dictionary];
d3[@"pic"]=@"3_Camaro";
d3[@"des"]=@"雪佛兰 科迈罗(英文名:Chevrolet Camaro)设计于1960年,目前共发展了六代。1966年9月26日发布的1967款Camaro是以雪佛兰Nova为原型而设计的。";
NSMutableDictionary * d4 = [NSMutableDictionary dictionary];
d4[@"pic"]=@"4_LandCru";
d4[@"des"]=@"兰德酷路泽【陆地巡洋舰】是丰田汽车出品的LAND CRUISER 200,是丰田公司生产的一款进口ORV越野车(Off Road Vehicle) [1] ,它的外观在继承原有设计DNA的同时向具备新时代的“新鲜感·先进性”风格进化。是四轮驱动,轴距2850毫米,四轮碟刹的硬派越野车。";
NSMutableDictionary * d5 = [NSMutableDictionary dictionary];
d5[@"pic"]=@"5_Mondeo";
d5[@"des"]=@"福特蒙迪欧(Mondeo)是一款长安福特旗舰车型,不仅搭载多项创新科技,并在至臻品质、动力系统以及安全性能等方面实现全面提升。";

// 将字典放入数组中
self.pics = @[d1, d2, d3, d4, d5];


// 2. 初始化索引 为 1 , 并且执行 第一次 图片 切换 操作 , 显示对应的 图片 , 索引 , 及 描述
self.index = 1;

[self showImage];

}

// 显示 上一张 图片
- (IBAction)lastImage:(UIButton *)sender {
// 设置图片索引 , 注意不能 小于 1 , 边界控制
self.index -- ;
if(self.index <= 1){
self.index = 1;
}

[self showImage];
}

// 显示 下一张 图片
- (IBAction)nextImage:(UIButton *)sender {
// 设置图片索引 , 注意不能 超过 5 , 边界控制
self.index ++ ;
if(self.index >= self.pics.count){
self.index = (int)self.pics.count;
}
[self showImage];
}

// 根据 当前的 索引值 显示指定的图片 , 以及控制 左右 切换按钮是否可用
- (void) showImage {

// 1. 设置按钮 禁用 启用 , index 为 1 和 5 时 分别启用 和 禁用 指定的按钮 , 其它情况下可以使用两个按钮
if(self.index == 1){
self.lastButton.enabled = NO;
self.nextButton.enabled = YES;
}else if(self.index == self.pics.count){
self.lastButton.enabled = YES;
self.nextButton.enabled = NO;
}else{
self.lastButton.enabled = YES;
self.nextButton.enabled = YES;
}


// 2. 设置 UIImageView 和 UILabel 切换

// ① 获取对应的数据 字典
NSMutableDictionary * d = self.pics[self.index - 1];
// ② 设置提示 UILabel 文字 , 拼接字符串 , 1/5
self.indexLabel.text = [NSString stringWithFormat:@"%d/%lu", self.index, self.pics.count];
// ③ 设置 图片 显示
self.Image.image = [UIImage imageNamed:d[@"pic"]];
// ④ 设置 文字 描述
self.imageDescription.text = d[@"des"];

}




@end


( 3 ) 效果展示



效果展示 :




四. Storyboard 添加 配置 及 相关知识点




1. 添加 新界面 ( ① 新建 Storyboard | ② 配置 Storyboard | ③ 新建ViewController 代码 )



( 1 ) 添加 Storyboard ( ① File -> New -> File | ② iOS -> User Interface -> Storyboard | ③ General -> Deployment -> Main Interface 配置 Storyboard )



Main.storyboard 添加流程 :


  • 1.新建 :​ 菜单栏 File -> New -> File 选项 , 弹出 新建 对话框 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_26
  • 2.选择文件模板 :​ 在弹出的 对话框中 选择 ​iOS -> User Interface -> Storyboard​ 文件 , 点击 Next 按钮 , 进行下一步设置 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_27
  • 3.选择文件路径 :​ 最好将文件放在 主代码 路径下 , 点击 Create 进行下一步 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_28
  • 4.Xcode 设置 :​ 其 文件 创建在了 代码目录下 , Xcode 中的引用 放在了根目录 , 此时 将其拖动到 代码路径中即可 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_29
    设置完毕后的情况​ :
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_30
  • 5.设置启动 UI 文件 :​ 选中 Xcode 项目 根路径文件 , 在 ​General -> Deployment -> Main Interface​ 一栏 选择 想要启动的 UI 文件 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_31


( 2 ) Storyboard 设置 ( ① 拖动箭头设置启动界面 | ② View Controller 的 Is Initial View Controller 勾选框 设置启动界面 | ③ 关联 ViewController 代码 )



Storyboard 设置 :


  • 1.设置多个 View Controller :​ 在 Main.storyboard 中 , 可以直接将 View Controller 拖入其中 ; 注意 为 每个 ViewController 设置 4.7inch 大小 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_32
  • 2.设置 3 个 View Controller :​ 拖入 三个 ViewController , 并为其 根 View 设置 不同的背景颜色 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle_33
  • 3.拖动箭头 :​ 直接拖动 向右的 箭头 , 其指向就是第一个 启动的界面 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle_34
  • 4.属性设置启动界面 :​ 选中 ViewController , 在属性查看器中 设置 View Controller 模块下的 Is Initial View Controller 选项 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_PList_35
  • 5.关联 ViewController 代码 :​ 在 Main.Storyboard 中 虽然添加了 2 个 界面 , 但是没有与之对应的 ViewController.m 的代码 , 这里需要在 身份查看器 中 设置 Class 属性 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_36
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle_37


( 3 ) 新建 ViewController.m 文件 ( ① File -> New -> File | ② iOS -> Source -> Cocoa Touch Class | ③ Storyboard 中 身份查看器 配置 Class )



新建 ViewController.m 文件 :


  • 1.新建文件 :​ 菜单栏 ​File -> New -> File​ 选项 , 弹出 新建对话框 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_38
  • 2.创建类型选择 :​ 在弹出的 对话框中 选择 ​iOS -> Source -> Cocoa Touch Class​ 文件 , 点击 Next 按钮 , 进行下一步设置 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle_39
  • 3.设置类 :​ 选择 父类 类型为 UIViewController , 类名不要与其它 文件 重名 , 点击 Next 进行下一步设置 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle_40
  • 4.设置文件路径 :​ 在 弹出 的 对话框中 设置代码的路径 , 这里直接使用默认值即可 ; 点击 Create 按钮 , 即可生成 对应的 ViewController 代码 文件 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle_41
  • 5.Storyboard 代码对应设置 :​ 点击 Storyboard 中的 ViewController , 在 身份查看器 中配置 Class 选项 , 直接输入 刚才生成的 TestViewController 名称即可完成对应关系 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_PList_42



2. Storyboard 相关知识点 ( ① 删除 Storyboard | ② Storyboard 本质 )



( 1 ) 删除 Storyboard ( ① 删除文件及引用 | ② 删除引用 文件保留 )



删除 Storyboard :​ 选中 Storyboard 点击 Delete 键 , 就会弹出如下对话框 , 提供了 三个选项 ;

【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_43


  • 1.Move to Trash :​ 删除 Finder 中的 文件 , 及 Xcode 中的索引 , 该文件直接删除到 Trash 废纸篓 中 ;
  • 2.Remove Reference :​ 删除 Xcode 中的 引用 , 但是 文件 还是 在 该项目 下 , 可以随时 通过 拖动 恢复该文件 ;
  • 3.Cancel :​ 取消删除操作 ;


( 2 ) Storyboard 本质 ( XML 文本文件 )



Storyboard 本质 : 向 首界面 拖入 一个 UILabel , 并查看 该文件 ;

【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_44


  • 1.使用文本编辑器查看 :​ 使用 Subline 文本编辑器查看 Storyboard 界面 , 发现 其本质 是一个 纯文本 的 文件 ; 该方式 与 Android 的 布局文件相似 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_45
  • 2.xml 文本 :​ 该 文本 本质 是 一个 xml 文件 ;
  • 3.Xcode 中使用文本打开 :​ 右键点击 Storyboard 文件 , 选择 Open As -> Source Code 即可 查看 源码 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_PList_46
  • 4.查看 代码 样式 :【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_PList_47
  • 5.UILabel 代码 分析 :​ 其中 text 属性 就是 显示 文字 , rect frame 子标签 就是其 位置 和 宽高 ;

<label opaque="NO" 
userInteractionEnabled="NO"
contentMode="left"
horizontalHuggingPriority="251" verticalHuggingPriority="251"
fixedFrame="YES" text="Hello" textAlignment="natural"
lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines"
adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO"
id="JUr-dt-qtd">
<rect key="frame" x="168" y="323" width="39" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<color key="textColor" cocoaTouchSystemColor="darkTextColor"/>
<nil key="highlightedColor"/>
</label>



3. iOS 应用启动步骤简介



( 1 ) iOS 应用启动步骤



iOS 应用启动步骤 :


  • 1.程序入口 main 函数 :​ main () 函数 在 Xcode 中 代码 路径 下的 Supporting Files 目录下 的 main.m 文件中 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_48
  • 2.调用 UIApplicationMain 方法 :​ 调用 UIApplicationMain 方法 , 启动应用 ;

UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));

  • 3.查找 Storyboard :​ 查找 在 应用设置中 的 Main Interface 设置的 Storyboard 文件 , 该文件是 应用启动 加载 的 UI 界面 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_49
  • 4.查找 启动界面 :​ 查找 在 Storyboard 中 箭头指向 的 启动 ViewController ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_PList_50
  • 5.加载 UI 界面 :​ 读取 Storyboard 文件 , 加载并分析 其 XML 标签 属性 和 值 对应的 控件 , 创建这些控件 并 添加到 ViewController 中 ;
  • 6.调用 viewDidLoad 方法 :​ 界面 加载 完毕后 , 调用 ViewController.m 中的 viewDidLoad 方法 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_51
  • 7.界面 展示 :​ 将创建的 UI 界面 在手机屏幕上 展示 给用户 ;




五. Bundle 简介




( 1 ) Bundle 简介



Bundle 简介 :​ ​应用程序名称.app 是 Bundle , 是一个 目录​ ;


  • 1.Mac 中的 Bundle :​ 在 Mac 中的 Finder 中 , 点击 应用程序 目录 , 其中是一个个 “.app” 后缀 的 文件 , 这些文件 就是 Bundle , 可以右键点击 选择 ​显示包内容​ , 查看其中的 目录 内容 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle_52
  • 2.显示包内容 :​ 右键点击 app 后缀 文件 , 选择 显示包内容 选项 , 即可查看其内容 , 其 Contents 下的 内容 就是 Bundle ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_控件_53
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle_54
  • 3.iOS 中的 Bundle :​ 与 Mac 基本相同 , iOS 应用程序 , 打包好以后 , 也是一个 .app 后缀的 文件 , 也可以通过 右键 点击 该文件 , 选择 显示包内容 查看 Bundle ;
  • 4.Bundle 路径 :​ 在应用中 , 可以通过 ​​NSLog(NSHomeDirectory());​​ 打印出 沙盒路径 , 在 该路径 向后 退 两层 目录 , 可以看到 Bundle 目录 , Bundle 文件都在该 目录中 ;

//打印出的路径示例 
/Users/hanshuliang/Library/Developer/CoreSimulator/Devices/C7ECF957-38E2-4E3F-ADC1-1FC5D26B4C79/data/Containers/Data/Application/7128774A-7468-466B-9C44-962CF974F8CB

Bundle 路径 :

【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_55


  • 5.iOS 中的 .app 文件路径 :​ 在 Bundle 目录下 , Application 路径 下 的 二级 文件 就是 iOS 中的 app 后缀文件 , 右键 可查看其 内容 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle_56
  • 6.查看 Bundle 内容 :​ 右键点击 “5.NSBundleDemo.app” 文件 , 选择 显示包内容 选项 , 可以查看 Bundle 内容 , 如下图 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle_57
  • 7.创建文件 :​ 创建 1 个 新的 Storyboard 文件 , 然后 再次查看 Bundle , 即可看到 在 Bundle 中 出现了一个 新文件 ; 这个 文件 是 加密的 , 无法查看 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_58
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_控件_59


( 2 ) 图片放置 位置 ( ① 放在 Assets.xcassets [推荐] | ② 放在根目录[不推荐] )



图片放置 位置 :​ 准备两张图片 , 分别放在 代码 根目录 和 Assets.xcassets 中 ;

【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_PList_60


  • 1.放在 根目录 :​ 在 Bundle 中 也可以 看到 该图片 , 不安全 ;
  • 2.放在 Assets.xcassets 目录中 :​ 放在 该 目录下 , 打包后 放在 Assets.car 中 , 放在根目录的图片 直接显示在 Bundle 中 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_PList_61


( 3 ) NSBundle 使用 ( ① 获取 NSBundle 对象 | ② 获取 Bundle 目录下 某文件的 全路径 )



NSBundle 使用 :


  • 1.NSBundle 类 作用 :​ 获取了 NSBundle 类 , 就相当于获取了 Bundle 目录中的内容 ; 如 下图 的内容 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_62
  • 2.获取 NSBundle 对象 :​ 通过 调用 NSBundle 的 mainBundle 方法 , 获取该对象 ;

// 2. 获取当前应用程序的 Bundle
NSBundle *mainBundle = [NSBundle mainBundle];
  • 3.获取 Bundle 下的 文件路径 :​ 可以通过 pathForResource 方法 获取 某文件的 路径 , ​① 传入 文件名 和 后缀 两个参数​ , ​② 或者 传入 文件名.后缀 参数​ ;
// 3. 获取 Bundle 中 某文件 的 全路径
NSString *path = [mainBundle pathForResource:@"5_ Mondeo" ofType:@"jpeg"];
NSLog(path);

// 4. 获取 Bundle 中 某文件 的 全路径 , 使用另外一种方式
NSString *path1 = [mainBundle pathForResource:@"5_ Mondeo.jpeg" ofType:nil];
NSLog(path1);
  • 4.输出结果 :
2019-02-12 22:46:33.797 5.NSBundleDemo[3253:29735] /Users/hanshuliang/Library/Developer/CoreSimulator/Devices/C7ECF957-38E2-4E3F-ADC1-1FC5D26B4C79/data/Containers/Bundle/Application/C004925F-E20C-4122-A6E0-89D2D6B0CA7B/5.NSBundleDemo.app/5_ Mondeo.jpeg
2019-02-12 22:46:33.797 5.NSBundleDemo[3253:29735] /Users/hanshuliang/Library/Developer/CoreSimulator/Devices/C7ECF957-38E2-4E3F-ADC1-1FC5D26B4C79/data/Containers/Bundle/Application/C004925F-E20C-4122-A6E0-89D2D6B0CA7B/5.NSBundleDemo.app/5_ Mondeo.jpeg




六. Property List 简介




( 1 ) Property List 创建 ( ① New File | ② iOS -> Resource -> Property List | ③ 数据设置 | ④ 类型设置 )



PList 创建 :


  • 1.创建文件 :​ 右键 点击 代码目录 , 选择 New File 选项 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_63
  • 2.设置文件类型 :​ 选择 iOS -> Resource -> Property List 文件 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_64
  • 3.设置文件路径 :​ 设置 文件 名称 , 并 选择 文件路径 ;
  • 4.添加数据 :​ 点击 PList 中的 加号 按钮 , 即可添加数据 ;
  • 5.数据类型设置 :​ 默认 的 根元素 是 Dictionary 字典 , 这里暂时只讨论 字典 的 情况 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_控件_65


( 2 ) 获取 Property List 数据 ( ① 获取 Bundle PList 路径 | ② dictionaryWithContentsOfFile 初始化字典 | ③ 查看数据 )



获取 PList 数据 :


  • 1.查看 Bundle 中 PList 文件 :​ 之前 创建 了一个 PList 文件 , 这里进入 Bundle 目录中 查看 , 根据之前 打印的 Bundle 路径 , 查看 其 文件内容 :
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_66
  • 2.获取 Bundle 目录中 的 PList 文件 路径 :​ 调用 NSBundle 对象的 pathForResource 方法 , 获取 PList 在 Bundle 中的 全路径 ;

// 5. 获取 dictionary.plist 的 Bundle 路径
NSString *path2 = [mainBundle pathForResource:@"dictionary.plist" ofType:nil];
NSLog(path2);
  • 3.根据文件路径 初始化 字典 :​ 调用 NSDictionary 的 dictionaryWithContentsOfFile 方法 , 初始化字典 , 传入的是 PList 路径 ;
// 6. 根据 PList 路径 初始化 字典 , 前提是 这个 PList 的类型是 字典类型的
NSDictionary *dictionary = [NSDictionary dictionaryWithContentsOfFile:path2];
  • 4.调试查看字典内容 :​ 在 字典 初始化 位置 打断点 , 查看初始化的内容 ;

【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle_67


( 3 ) Property List 多种类型 数据 设置 获取 ( ① 设置 Root 类型为 NSArray | ② 设置 多类型 数据 | ③ 获取 PList 的 Bundle 路径 | ④ 初始化 数组 | ⑤ 打断点查看数据 )



PList 多种类型数据设置 :​ 上面 讲解 了 根元素 为 字典 的情况 , 这里讨论 根元素 为 数组 的情况 , 其中 ​数组的 每个元素 都可以设置 不同的类型​ ;


  • 1.设置根元素类型为数组 :【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_PList_68
  • 2.设置多个类型的数据 :​ 每个 数组 元素 可以设置 不同的 类型 , 这里设置 字典 , 数字 , 布尔 值 三个 数组元素 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_控件_69
  • 3.获取 PList 的 Bundle 路径 :​ 调用 NSBundle 对象的 pathForResource 方法 获取 对应文件的 Bundle 全路径 ;

// 7. 获取 array.plist 的 Bundle 路径
NSString *path3 = [mainBundle pathForResource:@"array.plist" ofType:nil];
NSLog(path3);
  • 4.初始化 数组 :​ 调用 NSArray 的 arrayWithContentsOfFile 方法 初始化 数组 , 传入 PList 的路径 , 注意 这个 PList 的 Root 类型 必须是 Array 类型 的 ;
// 8. 根据 PList 路径 初始化 数组 , 前提是 这个 PList 的类型是 数组类型的
NSArray *array = [NSArray arrayWithContentsOfFile:path3];
  • 5.打断点查看 数组 内容 :【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_70




七. 优化 图片 浏览器 ( ① 使用 PList | ② 懒加载 )




( 1 ) 使用 PList 存储 数据 ( ① 创建 PList 文件 | ② 数据准备 | ③ 获取 Bundle 路径 | ④ 获取 PList 的 Bundle 路径 | ⑤ PList -> 数组 )



使用 PList 存储数据 :


  • 1.创建 PList 文件 :​ 创建 名称为 car.plist 的文件 , 将其 Root 类型设置为 Array 类型 ;
  • 2.数据准备 :​ 将 图片名称 和 描述 信息 存入 plist 文件中 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle_71
  • 3.获取 Bundle 路径 :

// 1. 获取 Bundle
NSBundle *mainBundle = [NSBundle mainBundle];
  • 4.获取 PList Bundle 路径 :
// 2. 获取 plist 文件路径
NSString *path = [mainBundle pathForResource:@"car.plist" ofType:nil];
  • 5.初始化数组 :
// 3. 初始化数组
self.pics = [NSArray arrayWithContentsOfFile:path];


( 2 ) 懒加载 优化 ( ① 在 get 方法中加载数据 | ② 如果为 空 才 加载 )



懒加载优化 :


  • 1.懒加载原则 :​ ​① 用到 某 属性的时候才去 加载​ ; ​② 没有值 时 才 进行初始化​ ;
  • 2.点语法说明 :​ 以 ​​@property (strong, nonatomic) NSArray * pics;​​​ 为例 , ​​self.pics​​​ 相当于 get 方法 , 即调用了 ​​-(NSArray *) pics;​​​方法 ; set 方法调用的是 ​​-(void)setPics:(NSArray*)pics;​​​ ; 其实际的 变量名称 是 ​​_pics​​ ; ​根据 用到 属性时 才去加载 原则 , 这里将加载过程放在 get 方法中​ ;
  • 3.读取 plist 频率 :​ 一般情况下 程序 运行起来 , plist 是不会改变的 , 因此 只需要加载一次即可 ; ​根据 没有值 的时候才去 初始化 原则 , 只有当属性为 空时 , 才执行初始化操作​ ;
  • 4.代码 :

//懒加载优化 , 原则 1 : 只有使用 pics 属性时 开始优化 , 因此 代码 放在 get 方法中
- (NSArray *)pics {
// 懒加载优化 , 原则 2 : 只有 pics 属性为 空时 才开始从 list 中 初始化 数据
if(_pics == nil){
// 1. 获取 Bundle
NSBundle *mainBundle = [NSBundle mainBundle];

// 2. 获取 plist 文件路径
NSString *path = [mainBundle pathForResource:@"car.plist" ofType:nil];

// 3. 初始化数组 , 注意 此处要使用 生成的 变量名
_pics = [NSArray arrayWithContentsOfFile:path];
}
return _pics;
}




八. UIImageView 播放动画 及 内存优化




1. 动画 播放




( 1 ) UIImageView 动画 相关属性 ( ① 图片数组 | ② 动画时长 | ③ 重复次数 )



UIImageView 动画相关属性 :

  • 1.动画图片数组 :​ 多个 NSArray 数组 , 其中元素类型是 UIImage ;
@property (nullable, nonatomic, copy) NSArray<UIImage *> *animationImages; 
// The array must contain UIImages. Setting hides the single image. default is nil
  • 2.动画持续时间 :​ 单位 秒 ;
@property (nonatomic) NSTimeInterval animationDuration;         
// for one cycle of images. default is number of images * 1/30th of a second (i.e. 30 fps)
  • 3.动画重复次数 :​ 无限循环 设置 0 ;
@property (nonatomic) NSInteger      animationRepeatCount;      
// 0 means infinite (default is 0)

( 2 ) UIImageView 动画 相关方法 ( ① 开始播放 | ② 停止播放 | ③ 是否正在播放 )



UIImageView 动画相关方法 :

  • 1.开始播放​ :
- (void)startAnimating;
  • 2.停止播放​ :
- (void)stopAnimating;
  • 3.是否正在播放​ :
- (BOOL)isAnimating;


( 3 ) UIImageView 动画 执行流程 ( ① 准备 UIImage 数组 | ② 设置动画参数 UIImage数组 时长 重复次数 | ③ 启动动画 )



UIImageView 动画 执行流程 :

  • 1.首先判断 动画 是否在执行 :​ 动画执行 操作 会覆盖 上一次的 动画 , 每次 调用 startAnimating 都会 重新开始 执行动画 , 因此 当动画正在 执行时 , 不要覆盖 ; 使用 isAnimating 方法 先判断 动画是否在习性 ;
// 1. 先判断 动画是否在执行 , 如果动画在执行 , 直接退出方法
if([self.imageView isAnimating]) return;
  • 2.准备数据 :​ 准备 UIImage 数组 ;
// 2. 数据准备 , 准备 UIImage 数组
NSArray *nameArray = @[@"1_Mustang", @"2_Prado", @"3_Camaro", @"4_LandCru", @"5_Mondeo"];
NSMutableArray *imageArray = [NSMutableArray array];
for(int i = 0; i < nameArray.count; i ++){
//获取 UIImage 对象 , 并放入数组
[imageArray addObject:[UIImage imageNamed:nameArray[i]] ];
}
  • 3.设置图片 :​ 将准备好的 UiImage 数组 设置 到 animationImages 属性中 ;
// 3. 设置图片
self.imageView.animationImages = imageArray;
  • 4.设置动画参数 :​ 设置动画的 时长 ( animationDuration 属性 ) 和 重复次数 ( animationRepeatCount 属性 ) ;
// 4. 设置动画参数 : 时长 , 循环次数
self.imageView.animationDuration = 1;
self.imageView.animationRepeatCount = 1;
  • 5.开始执行动画 :​ 执行 startAnimating 方法 , 开始执行动画 ;
// 5. 开始执行动画
[self.imageView startAnimating];
  • 6.完整代码 :
//播放动画的 方法
- (IBAction)startAnimation:(UIButton *)sender {
// 1. 先判断 动画是否在执行 , 如果动画在执行 , 直接退出方法
if([self.imageView isAnimating]) return;

// 2. 数据准备 , 准备 UIImage 数组
NSArray *nameArray = @[@"1_Mustang", @"2_Prado", @"3_Camaro", @"4_LandCru", @"5_Mondeo"];
NSMutableArray *imageArray = [NSMutableArray array];
for(int i = 0; i < nameArray.count; i ++){
//获取 UIImage 对象 , 并放入数组
[imageArray addObject:[UIImage imageNamed:nameArray[i]] ];
}

// 3. 设置图片
self.imageView.animationImages = imageArray;

// 4. 设置动画参数 : 时长 , 循环次数
self.imageView.animationDuration = 1;
self.imageView.animationRepeatCount = 1;

// 5. 开始执行动画
[self.imageView startAnimating];

}



2. 图片内存 优化




( 1 ) UIImageView 动画 内存 查看 ( ① Debug Navigator 查看内存 | ② 查看 动画播放前后的内存变化 | ③ 分析内存不释放的原因 )



UIImageView 内存查看 :

  • 1.查看内存方式 :​ 内存 可以在 Debug Navigator 中 进行查看 , 前提是 应用 必须处于正在运行的状态 ;

【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_bundle_72


  • 2.运行并查看内存 :​ 播放之前 内存 是 19.9M ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_PList_73
  • 3.点击播放动画查看内存 :​ 点击播放按钮 , 及 播放 完毕之后 , 内存一直保持在 36.9M ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_iOS_74
  • 4.分析原因 :​ 这是 由于 图片 一直 驻留在内存中 没有释放 , 使用 UIImage imageNamed 方法 加载的图片 , 不会释放 ;


( 2 ) UIImage 内存分析 ( ① 使用 UIImage imageNamed:图片名称 加载图片 | ② 使用 UIImage imageWithContentsOfFile:Bundle路径名 加载图片 )



UIImage 内存分析 :

  • 1.使用 UIImage imageNamed:图片名称 加载图片 :​ 使用该方式 加载 图片 , 图片会在 内存中 驻留 , 只有需要长期保持的 图片 , 如 UI 界面的 经常显示 的 各种背景 图标 等 , 使用该方式加载 ;
UIImage *image = [UIImage imageNamed:@"1.png"];
  • 2.使用 UIImage imageWithContentsOfFile:Bundle路径名 加载图片 :​ 使用该方式加载图片时 , 如果图片没有被引用时 , 图片占用的内存就会被释放 ; 即 将图片持有变量设置为 nil 即可 ;
//2.1获取 Bundle
NSBundle *mainBundle = [NSBundle mainBundle];

//2.2获取 图片对应的 Bundle 路径
NSString *path = [mainBundle pathForResource:nameArray[i] ofType:@"jpeg"];

//2.3根据 Bundle 路径 获取 UIImage
UIImage *image = [UIImage imageWithContentsOfFile:path];


( 3 ) 内存优化 的 动画 执行 完整流程 ( ① 准备 UIImage 数组 | ② 设置动画参数 UIImage数组 时长 重复次数 | ③ 启动动画 | ④ 异步设置图片数组为 nil )



内存优化后的 动画 执行流程 :

  • 1.首先判断 动画 是否在执行 :​ 动画执行 操作 会覆盖 上一次的 动画 , 每次 调用 startAnimating 都会 重新开始 执行动画 , 因此 当动画正在 执行时 , 不要覆盖 ; 使用 isAnimating 方法 先判断 动画是否在习性 ;
// 1. 先判断 动画是否在执行 , 如果动画在执行 , 直接退出方法
if([self.imageView isAnimating]) return;
  • 2.准备数据 :​ 准备 UIImage 数组 ; 这里需要从 Bundle 中获取图片 , 因此需要将图片 放置在 Xcode 中的 Assets.xcassets 之外 ( Bundle 中无法获取其中的资源路径 ) , ​拖入一个图片文件夹 , 这里要注意 在 “Choose options for adding these files” 对话框中 选择 Create groups 选项 , 否则 就无法获取到 Bundle 中的 文件路径​ ;
// 2. 数据准备 , 准备 UIImage 数组
NSArray *nameArray = @[@"1_Mustang", @"2_Prado", @"3_Camaro", @"4_LandCru", @"5_Mondeo"];
NSMutableArray *imageArray = [NSMutableArray array];
for(int i = 0; i < nameArray.count; i ++){
//2.1获取 Bundle
NSBundle *mainBundle = [NSBundle mainBundle];

//2.2获取 图片对应的 Bundle 路径
NSString *path = [mainBundle pathForResource:nameArray[i] ofType:@"jpeg"];

//2.3根据 Bundle 路径 获取 UIImage
UIImage *image = [UIImage imageWithContentsOfFile:path];

//2.4获取 UIImage 对象 , 并放入数组
[imageArray addObject:image ];
}
  • 3.设置图片 :​ 将准备好的 UiImage 数组 设置 到 animationImages 属性中 ;
// 3. 设置图片
self.imageView.animationImages = imageArray;
  • 4.设置动画参数 :​ 设置动画的 时长 ( animationDuration 属性 ) 和 重复次数 ( animationRepeatCount 属性 ) ;
// 4. 设置动画参数 : 时长 , 循环次数
self.imageView.animationDuration = 1;
self.imageView.animationRepeatCount = 1;
  • 5.开始执行动画 :​ 执行 startAnimating 方法 , 开始执行动画 ;
// 5. 开始执行动画
[self.imageView startAnimating];
  • 6.清除动画图片方法 :​ 直接将 UIImageView 的 animationImages 动画图片数组 设置为 nil 即可 ;
//清除 UIImageView 的 动画图片
- (void) clearImage {
self.imageView.animationImages = nil;
}
  • 7.异步执行方法 :​ 需要 在动画开始 1 秒之后执行 , 代码实现如下 :
// 6. 1秒后清除 动画图片
[self performSelector:@selector(clearImage) withObject:nil afterDelay:1];
  • 8.完整代码 :
//播放动画 并释放内存
- (IBAction)startAnimationReleaseMemory:(UIButton *)sender {

// 1. 先判断 动画是否在执行 , 如果动画在执行 , 直接退出方法
if([self.imageView isAnimating]) return;

// 2. 数据准备 , 准备 UIImage 数组
NSArray *nameArray = @[@"1_Mustang", @"2_Prado", @"3_Camaro", @"4_LandCru", @"5_Mondeo"];
NSMutableArray *imageArray = [NSMutableArray array];
for(int i = 0; i < nameArray.count; i ++){
//2.1获取 Bundle
NSBundle *mainBundle = [NSBundle mainBundle];

//2.2获取 图片对应的 Bundle 路径
NSString *path = [mainBundle pathForResource:nameArray[i] ofType:@"jpeg"];

//2.3根据 Bundle 路径 获取 UIImage
UIImage *image = [UIImage imageWithContentsOfFile:path];

//2.4获取 UIImage 对象 , 并放入数组
[imageArray addObject:image ];
}

// 3. 设置图片
self.imageView.animationImages = imageArray;

// 4. 设置动画参数 : 时长 , 循环次数
self.imageView.animationDuration = 1;
self.imageView.animationRepeatCount = 1;

// 5. 开始执行动画
[self.imageView startAnimating];

// 6. 1秒后清除 动画图片
[self performSelector:@selector(clearImage) withObject:nil afterDelay:1];

}

//清除 UIImageView 的 动画图片
- (void) clearImage {
self.imageView.animationImages = nil;
}


( 4 ) NSBundle pathForResource 为 nil 解决方案 ( ① 拖入目录 选择 Create gropus | ② 查看 Xcode 项目 配置 -> Build phases 的 Bundle 配置 )



NSBundle pathForResource 为 nil 解决方案 :


  • 1.拖入目录方法 :​ 在 ​将 pic 目录 拖入 Xcode 中时 , 需要选择 Create groups 选项​ , 不能选择 Create folder reference 选项 ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_PList_75
  • 2.确认是否可以获取到 :​ ​在 Xcode 项目设置中 , 如果有 要获取的 具体的 图片 文件设置 , 那么可以获取到 , 如果只有 图片的 目录 pic , 没有具体的 图片 配置 , 那么图片就获取不到​ ;
    【 iOS 应用开发 】 UIKit 控件 ( 代码生成控件 | UIView 属性方法 | Storyboard | Bundle | Property List | 动画 | 图片内存优化 )_Bundle_76


( 5 ) 效果展示



效果展示 :

博客相关资源 :


举报

相关推荐

0 条评论