当前位置: 首页 > news >正文

UIKit之图片浏览器

功能需求

实现一个图片浏览器,点击左右按钮可以切换背景图,且更新背景图对应的索引页和图片描述内容。

分析:

  • 实现一个UIView的子类即可,该子类包含多个按钮。

实现步骤:

  1. 使用OC语言,故创建cocoa Touch类型文件。Xcode会创建.h文件和.m文件:PicBrowserDemo类。
    在这里插入图片描述

  2. 图片资源导入:注意图片不要重名
    注意各项的类型:Root是Array,其余是Dictionary

  3. 实现该类。
    该类带有多个控件,令其继承UIView。
    a. 声明类的成员变量:在.h文件中定义:,类型是strong。
    该图片浏览器需要两个可显示文字内容但不可修改的Label、两个前后图片切换的按钮以及承载图片的视图。
    在.h 文件中:

@interface PicBrowserDemo : UIView
@property(strong, nonatomic) UIImageView  *imageView;
@property(strong, nonatomic) UILabel *label1;
@property(strong, nonatomic) UILabel *label2;
@property(strong, nonatomic) UIButton *btn1;
@property(strong, nonatomic) UIButton *btn2;
@end

b. 创建plist类型文件,直接在项目下创建,plist文件属于resource类型文件,在该栏目下可找到。
选择root类型为Array,而每个元素设置为字典,因为每个字典中存图片的名称和title(描述)。

c. .m 文件:

// 1 plist:信息填写
// 2 初始化各个组件,显示的信息以第一张为基准
// 3 nxt
// 4 pre
// 5 降低冗余,合并:pre、nxt函数#import "PicBrowserDemo.h"// 写私有属性:在这里
@interface PicBrowserDemo()
// assign、strong的区别: asign表示基本类型的变量
@property(nonatomic, strong) NSArray *pic;
@property(nonatomic, assign) int index;@end// 从plist中读取到的各图片信息集合@implementation PicBrowserDemo
-(instancetype) initWithFrame:(CGRect)frame{self = [super initWithFrame:frame];if(self){// 初始化5个组件_imageView = [[UIImageView alloc] initWithFrame:CGRectMake(80, 230, 150, 150)];// 图片模式:放入如何显示的 按比例缩放,不会拉伸变形_imageView.contentMode = UIViewContentModeScaleAspectFit;// 初始化为pic中第一张图片NSDictionary *dict = self.pic[0];_imageView.image = [UIImage imageNamed:dict[@"icon"]];// 固定值写法://_imageView.image = [UIImage imageNamed:@"i1.png"];// label1:_label1 = [[UILabel alloc] initWithFrame:CGRectMake(80, 190, 150, 40)];_label2 = [[UILabel alloc] initWithFrame:CGRectMake(80, 380, 150, 40)];// text填内容_label1.text = [NSString stringWithFormat:@"%d/%ld", 1, self.pic.count];// 下面的label填入title_label2.text = dict[@"title"];// 填充方式fill_label1.textAlignment = NSTextAlignmentCenter;_label2.textAlignment = NSTextAlignmentCenter;// btn1_btn1 = [[UIButton alloc] initWithFrame:CGRectMake(30, 300, 50, 50)];_btn2 = [[UIButton alloc] initWithFrame:CGRectMake(230, 300, 50, 50)];// btn1[_btn1 setBackgroundImage:[UIImage imageNamed:@"zuo1.jpg"] forState:UIControlStateNormal];// btn2[_btn2 setBackgroundImage:[UIImage imageNamed:@"you1.png"] forState:UIControlStateNormal];// 绑定点击向前和向后[_btn1 addTarget:self action:@selector(changePages:) forControlEvents:UIControlEventTouchUpInside];//[_btn2 addTarget:self action:@selector(changePages:) forControlEvents:UIControlEventTouchUpInside];//        [_btn1 addTarget:self action:@selector(pre) forControlEvents:UIControlEventTouchUpInside];
//        //
//        [_btn2 addTarget:self action:@selector(nxt) forControlEvents:UIControlEventTouchUpInside];
//        // 用tags区分该切换前一张还是后一张_btn1.tag = 1;_btn2.tag = 2;[self addSubview: _imageView];[self addSubview: _btn1];[self addSubview: _btn2];[self addSubview: _label1];[self addSubview: _label2];}return self;
}// 重写属性pic的get方法懒加载:
/* 第一次调用一定为空,加载即可*/
- (NSArray *) pic{if(_pic == nil){// 获取plist的文件路径// nsBundle:获取手机上软件的安装路径,而非项目路径NSString *path = [[NSBundle mainBundle] pathForResource:@"pics" ofType:@"plist"];// 读取文件NSArray *array = [NSArray arrayWithContentsOfFile:path];NSLog(@"count:%ld", array.count);_pic = array;}return _pic;
}// 不需要参数:
- (void) changePages:(UIButton *)sender{switch (sender.tag) {case 1:_index--;break;case 2:_index++;break;}NSDictionary *dict = self.pic[self.index];// 上面的label填入页码_label1.text = [NSString stringWithFormat:@"%d/%ld", self.index+1, self.pic.count];// 下面的label填入title_label2.text = dict[@"title"];// 图片框填入图片:_imageView.image = [UIImage imageNamed:dict[@"icon"]];// 如果已经到了最后一张,则按钮切换为不允许点// 索引为末尾-1,则设置下一张按钮为不可点击// 没必要通过图片来设置,通过yes、no设置即可达到所需的灰色状态// 两条必须同时设置:否则会出现 翻到底再返回时,向右按钮仍然灰色self.btn2.enabled = !(_pic.count -1 == _index);self.btn1.enabled = !(0 == _index);
}// 加索引:
- (void) nxt{_index++;NSDictionary *dict = self.pic[self.index];// 上面的label:填入序号_label1.text = [NSString stringWithFormat:@"%d/%ld", self.index+1, self.pic.count];// 下面的label:填入标题_label2.text = dict[@"title"];// 图片框填入图片:_imageView.image = [UIImage imageNamed:dict[@"icon"]];// 如果已经到了最后一张,则按钮切换为不允许点// 索引为末尾-1,则设置下一张按钮为不可点击// 没必要通过图片来设置,通过yes、no设置即可达到所需的灰色状态self.btn2.enabled = !(_pic.count -1 == _index);self.btn1.enabled = !(0 == _index);
}//
- (void) pre{_index--;NSDictionary *dict = self.pic[self.index];// 上面的label:填入序号_label1.text = [NSString stringWithFormat:@"%d/%ld", self.index+1, self.pic.count];// 下面的label:填入标题_label2.text = dict[@"title"];// 图片框填入图片:_imageView.image = [UIImage imageNamed:dict[@"icon"]];// 如果为0,则设置向左不可点击且更换图片self.btn1.enabled = !(0 == _index);self.btn2.enabled = !(_pic.count -1 == _index);
}
@end

调用入口:

- (void)viewDidLoad {[super viewDidLoad];//[self test_Common_arrtibute];[self testPicBrowser];
}-(void) testPicBrowser{PicBrowserDemo *browserView = [[PicBrowserDemo alloc] initWithFrame:CGRectMake(50, 80, 300 ,700)];//[browserView setBackgroundColor: [UIColor blueColor]];[self.view addSubview:browserView];}
  1. 效果展示
  1. 首页只可向右
  2. 尾页只可向左

在这里插入图片描述
在这里插入图片描述

要注意的问题以及犯错

  1. 关于懒加载:
    设置变量同名的函数,实则为setter,判断变量指向为空,则做初始化获取操作,后续再利用都不需要,此为懒加载方式。
  1. 关于plist加载:
    使用bundle接口,, 通过plist文件名即可,该底层原理是使用了安装APP后的文件结构来获取文件,而非运行工程的目录结构。
  1. plist总是读取为空
    我的plist获取方式是读取Array接口,而我的plist中root设置为dictionary类型,因此接口不对应,获取错误了。改root为array类型即可。
  1. 初始化index报错
    switch中,tag为2是向右点击,所以应该index++。
  1. 图片浏览器初始化:
    按pic第一张的图片和title初始化即可。

相关文章:

UIKit之图片浏览器

功能需求 实现一个图片浏览器,点击左右按钮可以切换背景图,且更新背景图对应的索引页和图片描述内容。 分析: 实现一个UIView的子类即可,该子类包含多个按钮。 实现步骤: 使用OC语言,故创建cocoa Touch类…...

如何查看SNMP设备的OID

什么是OID和MIB OID OID 代表对象标识符。 OID 唯一地标识 MIB 层次结构中的托管对象。 这可以被描述为一棵树,其级别由不同的组织分配。MIB MIB(管理信息基)提供数字化OID到可读文本的映射。 使用MIB Browser扫描OID 我的设备是一台UPS SN…...

什么?你设计接口什么都不考虑?

如果让你设计一个接口,你会考虑哪些问题? 1.接口参数校验 接口的入参和返回值都需要进行校验。 入参是否不能为空,入参的长度限制是多少,入参的格式限制,如邮箱格式限制 返回值是否为空,如果为空的时候是…...

2024年3月 青少年等级考试机器人理论真题二级

202403 青少年等级考试机器人理论真题二级 第 1 题 一个机器小车,用左右两个电机分别控制左右车轮,左侧电机转速是100rpm,右侧电机转速是50rpm,则此机器小车?( ) A:原地右转 B&am…...

C语言学习【printf函数和scanf函数】

C语言学习【printf函数和scanf函数】 printf()函数和scanf()函数可以让用户与程序交流,是输入/输出函数 printf()函数 请求printf()函数打印数据的指令要与待打印数据的类型相匹配。例如,打印整数时使用%d,打印字符时使用%c。这些符号被称…...

shell正则表达式

sort命令 以行为单位对文件内容进行排序,也可以根据不同的数据类型来排序 比较原则是从首字符向后,依次按ASCII码值进行比较,最后将他们按升序输出。 sort 对行内容进行升序排序 XXX | sort 选项 sort 选项 文件 常用选项&#x…...

react组件渲染性能优化之函数组件-useCallback使用

useCallback主要就是对函数进行缓存,useCallBack这个Hooks主要是解决React.memo不能缓存事件的问题 useCallBack(fn, dependencies) :fn想要缓存的函数,dependencies有关是否更新 fn 的所有响应式值的一个列表 比如:UseCallBackOptimize组件…...

【C++】:string类的基本使用

目录 引言一,string类对象的常见构造二,string类对象的容量操作三,string类对象的访问及遍历操作四,string类对象的修改操作五,string类非成员函数六,整形与字符串的转换 引言 string 就是我们常说的"…...

多线程的代码案例

目录 单例模式 饿汉模式 懒汉模式 阻塞队列 生产者消费者模型意义: 阻塞队列使用方法 实现阻塞队列 阻塞队列实现生产者消费者模型 定时器 实现简单的定时器 工厂模式 线程池 为啥呢? 从池子里面取 比 创建线程 效率更高 线程池的创建 怎么填坑 ThreadPoolExec…...

什么是Java中的设计模式?请列举几种常见的设计模式

一、引言 在软件开发中,设计模式是解决特定设计问题的最佳实践或通用解决方案。Java作为一种广泛使用的编程语言,其设计模式在软件设计和架构中起着至关重要的作用。设计模式不仅提高了代码的可读性和可维护性,还使得代码更加灵活和可扩展。…...

绘制奇迹:Processing中的动态图形与动画

🚀 欢迎回到Processing的世界,你的艺术编程航程刚刚开始。在我们的入门篇中,你已经学会了如何用Processing绘制基本的静态图形。现在,让我们一起探索Processing强大的动态图形和动画功能,释放你的创造力,走…...

Django视图Views

Views视图 HttpRequest 和HttpResponse Django中的视图主要用来接受web请求,并做出响应。视图的本质就是一个Python中的函数视图的响应分为两大类 1)以Json数据形式返回(JsonResponse) 2)以网页的形式返回 2.1)重定向到另一个网页 (HttpRe…...

国内智能搜索工具实战教程

大家好,我是herosunly。985院校硕士毕业,现担任算法研究员一职,热衷于机器学习算法研究与应用。曾获得阿里云天池比赛第一名,CCF比赛第二名,科大讯飞比赛第三名。拥有多项发明专利。对机器学习和深度学习拥有自己独到的见解。曾经辅导过若干个非计算机专业的学生进入到算法…...

WebSocket or SSE?即时通讯的应用策略【送源码】

最近在研究H5推送,发现除了我们常用的WebSocket以外,其实还有一种协议也能实现H5推送,那就是SSE协议。 而且,当前主流的大模型平台,比如ChatGPT、通义千问、文心一言,对话时采用的就是SSE。 什么是SSE协议…...

QT实现Home框架的两种方式

在触摸屏开发QT界面一般都是一个Home页面,然后button触发进入子页面显示,下面介绍这个home框架实现的两种方式: 1.方式一:用stackedWidget实现 (1)StackedWidget控件在Qt框架中是一个用于管理多个子窗口或…...

机器学习笔记03

1.线性回归(linear regression) 是利用回归方程(函数)对一个或者多个自变量(特征值)和因变量(目标值)之间关系进行建模的一种分析方法。 线性模型: 1.线性关系&#xff1…...

【全面介绍下Spring】

🌈个人主页: 程序员不想敲代码啊 🏆CSDN优质创作者,CSDN实力新星,CSDN博客专家 👍点赞⭐评论⭐收藏 🤝希望本文对您有所裨益,如有不足之处,欢迎在评论区提出指正,让我们共…...

MYSQL-存储引擎

存储引擎就是储数据、建立索引、更新/查询数据等技术的实现方式。存储引擎是基于表的,而不是基于库的,所以存储引擎也可被 称为表类型。 存储引擎特点 . InnoDB 介绍 InnoDB是一种兼顾高可靠性和高性能的通用存储引擎,在MySQL 5.5之后,InnoDB是默认的MySQL存储引擎。 >特…...

红蓝对抗 网络安全 网络安全红蓝对抗演练

什么是红蓝对抗 在军事领域,演习是专指军队进行大规模的实兵演习,演习中通常分为红军、蓝军,演习多以红军守、蓝军进攻为主。类似于军事领域的红蓝军对抗,网络安全中,红蓝军对抗则是一方扮演黑客(蓝军&…...

springboot 序列化和反序列化

介绍 在Java中,序列化和反序列化是一种将对象转换为字节流或将字节流转换为对象的机制。通过序列化,可以将对象存储到文件中、传输到网络上,或者在分布式系统中进行对象的传递。本文将详细介绍Java序列化和反序列化的原理、使用方法和常见应用…...

wordpress后台更新后 前端没变化的解决方法

使用siteground主机的wordpress网站,会出现更新了网站内容和修改了php模板文件、js文件、css文件、图片文件后,网站没有变化的情况。 不熟悉siteground主机的新手,遇到这个问题,就很抓狂,明明是哪都没操作错误&#x…...

网络编程(Modbus进阶)

思维导图 Modbus RTU(先学一点理论) 概念 Modbus RTU 是工业自动化领域 最广泛应用的串行通信协议,由 Modicon 公司(现施耐德电气)于 1979 年推出。它以 高效率、强健性、易实现的特点成为工业控制系统的通信标准。 包…...

基于大模型的 UI 自动化系统

基于大模型的 UI 自动化系统 下面是一个完整的 Python 系统,利用大模型实现智能 UI 自动化,结合计算机视觉和自然语言处理技术,实现"看屏操作"的能力。 系统架构设计 #mermaid-svg-2gn2GRvh5WCP2ktF {font-family:"trebuchet ms",verdana,arial,sans-…...

Flask RESTful 示例

目录 1. 环境准备2. 安装依赖3. 修改main.py4. 运行应用5. API使用示例获取所有任务获取单个任务创建新任务更新任务删除任务 中文乱码问题: 下面创建一个简单的Flask RESTful API示例。首先,我们需要创建环境,安装必要的依赖,然后…...

CVPR 2025 MIMO: 支持视觉指代和像素grounding 的医学视觉语言模型

CVPR 2025 | MIMO:支持视觉指代和像素对齐的医学视觉语言模型 论文信息 标题:MIMO: A medical vision language model with visual referring multimodal input and pixel grounding multimodal output作者:Yanyuan Chen, Dexuan Xu, Yu Hu…...

CMake基础:构建流程详解

目录 1.CMake构建过程的基本流程 2.CMake构建的具体步骤 2.1.创建构建目录 2.2.使用 CMake 生成构建文件 2.3.编译和构建 2.4.清理构建文件 2.5.重新配置和构建 3.跨平台构建示例 4.工具链与交叉编译 5.CMake构建后的项目结构解析 5.1.CMake构建后的目录结构 5.2.构…...

Go 语言并发编程基础:无缓冲与有缓冲通道

在上一章节中,我们了解了 Channel 的基本用法。本章将重点分析 Go 中通道的两种类型 —— 无缓冲通道与有缓冲通道,它们在并发编程中各具特点和应用场景。 一、通道的基本分类 类型定义形式特点无缓冲通道make(chan T)发送和接收都必须准备好&#xff0…...

C++:多态机制详解

目录 一. 多态的概念 1.静态多态(编译时多态) 二.动态多态的定义及实现 1.多态的构成条件 2.虚函数 3.虚函数的重写/覆盖 4.虚函数重写的一些其他问题 1).协变 2).析构函数的重写 5.override 和 final关键字 1&#…...

AirSim/Cosys-AirSim 游戏开发(四)外部固定位置监控相机

这个博客介绍了如何通过 settings.json 文件添加一个无人机外的 固定位置监控相机,因为在使用过程中发现 Airsim 对外部监控相机的描述模糊,而 Cosys-Airsim 在官方文档中没有提供外部监控相机设置,最后在源码示例中找到了,所以感…...

【 java 虚拟机知识 第一篇 】

目录 1.内存模型 1.1.JVM内存模型的介绍 1.2.堆和栈的区别 1.3.栈的存储细节 1.4.堆的部分 1.5.程序计数器的作用 1.6.方法区的内容 1.7.字符串池 1.8.引用类型 1.9.内存泄漏与内存溢出 1.10.会出现内存溢出的结构 1.内存模型 1.1.JVM内存模型的介绍 内存模型主要分…...