我的第一个 iOS 程序:iTahDoodle

我的第一个 iOS 程序:iTahDoodle

  • 我的第一个 iOS 程序:iTahDoodle
    • 应用功能
    • 对象图
    • 应用委托对象
    • 设置视图
    • 为按钮关联动作方法
    • 为 UITableView 对象提供数据
    • 保存并加载任务数据
    • 在模拟器上运行程序
    • 下载链接

我的第一个 iOS 程序:iTahDoodle

实现了一个名为 iTahDoodle 的 iOS 应用。这是一个简单的任务管理程序,并通过 property list 文件保存数据。

完整代码见于:UestcXiye/Objective-C-Practice 的 iTahDoodle。

应用功能

用户在文本框输入文字,点击 Insert 按钮,将文本插入到一个任务数组中,用一个 TableView 展示任务数组。

对象图

采用 MVC 模式:

请添加图片描述

参考书过于远古,从创建应用开始就有很多不同的地方,慢慢摸索才做出来。这里把书中 AppDelegate 的大部分内容转到 ViewController 中实现。

应用委托对象

iOS 应用启动时,会创建一个 UIApplication 实例,用于控制应用的状态。此外,程序还会创建 AppDelegate 实例,并将其设置为 UIApplication 实例的委托对象。

应用启动完成后,UIApplication 实例会向其委托对象发送 application:didFinishLaunchingWithOptions: 消息。凡是需要在程序能够和用户交互前就完成的初始化工作,都在该方法内实现。这里我们只需要完成 UIWindow 对象的创建和初始化即可。

// AppDelegate.h
#import <UIKit/UIKit.h>

@interface AppDelegate : UIResponder <UIApplicationDelegate>

@property (nonatomic, strong) UIWindow *window;

@end
  
// AppDelegate.m
#pragma mark - 应用委托对象的回调方法

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.
    /* 凡是需要在程序能够和用户交互前就完成的初始化工作,都在该方法内完成 */
    [self createAppWindow];
    
    return YES;
}

- (void)createAppWindow;
{
    if (@available(iOS 13.0, *)) {}
    else
    {
        // 创建并设置 UIWinodw 对象
        self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
        self.window.rootViewController = [[UITabBarController alloc] init];
        // 设置 UIWindow 实例的背景颜色,并放上屏幕
        self.window.backgroundColor = [UIColor whiteColor];
        [self.window makeKeyAndVisible];
    }
}

设置视图

视图加载后,就应该设置相应的视图对象,包括:输入栏、按钮、表格视图。大致流程为:创建所有的对象,并进行相应的设置,将设置过的视图对象加入 UIWindow 对象,成为其下的子视图。

// ViewController.h
#import <UIKit/UIKit.h>

NSString *docPath(void);

@interface ViewController : UIViewController
    <UITextFieldDelegate, UIApplicationDelegate, UITableViewDelegate>
{
    UITableView *_taskTable; // 表格视图,显示所有任务
    UITextField *_taskField; // 输入框
    UIButton *_insertButton; // 插入任务按钮
}

@property (nonatomic) UITableView *taskTable; // 表格视图,显示所有任务
@property (nonatomic, retain) UITextField *taskField; // 输入框
@property (nonatomic) UIButton *insertButton; // 插入任务按钮

@end

// ViewController.m
@implementation ViewController

@synthesize taskTable = _taskTable;
@synthesize taskField = _taskField;
@synthesize insertButton = _insertButton;

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    self.tasks = [NSMutableArray array];
    
    // 设置 3 个对象的 frame 属性
    // NSLog(@"%lf, %lf", self.view.frame.size.width, self.view.frame.size.height);
    /* width: 393, height: 852 */
    CGRect tableFrame = CGRectMake(0, 115, self.view.frame.size.width, self.view.frame.size.height - 130);
    CGRect fieldFrame = CGRectMake(20, 80, 280, 30);
    CGRect buttonFrame = CGRectMake(310, 80, 70, 30);
    
    // 创建并设置 UITableView 对象
    self.taskTable = [[UITableView alloc] initWithFrame:tableFrame style:UITableViewStylePlain];
    self.taskTable.separatorStyle = UITableViewCellSeparatorStyleNone;
    // 需要创建新的单元格时,告诉 UITableView 对象要实例化哪个类
    [self.taskTable registerClass:[UITableViewCell class] forCellReuseIdentifier:@"Cell"];
    
    // 创建并设置 UITextField 对象
    self.taskField = [[UITextField alloc] initWithFrame:fieldFrame];
    self.taskField.borderStyle = UITextBorderStyleRoundedRect; // 圆角
    self.taskField.placeholder = @"Type a task, tap Insert";
    self.taskField.delegate = self;
    
    // 创建并设置 UIButton 对象
    self.insertButton = [UIButton buttonWithType:UIButtonTypeRoundedRect]; // 圆角
    self.insertButton.frame = buttonFrame;
    // 为按钮设置标题
    [self.insertButton setTitle:@"Insert" forState:UIControlStateNormal];
    
    // 将 3 个 UI 对象加入 UIWindow 实例
    [self.view addSubview:self.taskTable];
    [self.view addSubview:self.taskField];
    [self.view addSubview:self.insertButton];
}

为按钮关联动作方法

按钮的回调通过目标-动作对实现。按钮的动作是按钮被按下后需要发送的消息,按钮的目标是接收这条消息的对象。

在设置按钮时,添加目标-动作对:

// 设置目标-动作对
[self.insertButton addTarget:self action:@selector(addTask:) forControlEvents:UIControlEventTouchUpInside];

这里按钮的目标是 self,也就是 ViewController;按钮的动作是 addTask: 方法,它的实现:

#pragma mark - Actions

-(void)addTask:(id)sender
{
    NSString *text = [self.taskField text];
    if ([text length] == 0)
        return;
    NSLog(@"Task entered: %@", text);
    [self.tasks addObject:text];
    [self.taskTable reloadData];
    [self.taskField setText:@""]; // 清空文本
    [self.taskField resignFirstResponder]; // 关闭键盘
}

addTask: 方法取得输入栏的文本,添加到 task 数组去,task 数组的内容会在 taskTable 中显示,要刷新一下才会展示出新插入的内容,然后清空输入栏的文本,让输入栏取消其第一响应对象状态,以此来关闭键盘。

为 UITableView 对象提供数据

UITableView 对象不包含任何数据,需要提供一个数据源对象给它。对于本程序,我们将 ViewController 实例设置为 UITableView 对象的数据源,因此 ViewController 必须遵守 UITableViewDataSource 协议。

// ViewController.h
@interface ViewController : UIViewController<UITableViewDelegate>
...
@property (nonatomic) NSMutableArray *tasks; // 任务数组
...
@end
  
// ViewController.m
- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    ...
    // 将当前对象设置为 UITableView 对象的 dataSource
    self.taskTable.dataSource = self;
    ...
}

还要实现 UITableViewDataSource 协议的两个必需方法:

#pragma mark - 管理表格视图
// 根据指定的表格段索引给出相应表格段所包含的行数
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    // 只有一个表格段,所以直接返回任务数组的对象个数
    return [self.tasks count];
}
// 根据指定的表格段索引和行索引给出相应的 UITableViewCell 对象
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    // 创建新的 UITableViewCell 对象
    UITableViewCell *c = [self.taskTable dequeueReusableCellWithIdentifier:@"Cell"];
    // 根据模型对象(tasks 数组)重新设置 UITableViewCell 对象
    NSString *item = [self.tasks objectAtIndex:indexPath.row];
    c.textLabel.text = item;
    // 返回设置后的 UITableViewCell 对象
    return c;
}

保存并加载任务数据

当程序进入后台运行状态时,将任务数组保存在 property list 格式的文件中;在用户重启应用时,加载保存的任务。

这里添加了一个 C 语言辅助函数,返回保存文件的路径。其实现在 #import 指令之后,@implementation 指令(类声明起始处)之前。

#import "ViewController.h"

@interface ViewController ()

@end
// 辅助函数,返回保存用户任务数据的文件路径
NSString *docPath(void)
{
    NSArray *pathList = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
    return [pathList[0] stringByAppendingPathComponent:@"data.td"];
}

@implementation ViewController
...
#pragma mark - 应用委托对象的回调方法

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    NSArray *plist = [NSArray arrayWithContentsOfFile:docPath()];
    if (plist)
    {
        NSLog(@"Loading data...");
        self.tasks = [plist mutableCopy];
    }
    else
    {
        self.tasks = [NSMutableArray array];
    }
    return YES;
}

- (void)applicationDidEnterBackground:(UIApplication *)application
{
    NSLog(@"Saving data...");
    // 将任务数组保存至文件
    [self.tasks writeToFile:docPath() atomically:YES];
}

在模拟器上运行程序

至此介绍完了整个程序的实现细节。用 iOS Simulator 看看程序的效果:

在这里插入图片描述

在输入栏中输入文字,点击 Insert 按钮,就能插入任务,并在下方的 TableView 中显示:

在这里插入图片描述

下载链接

GitHub:Objective-C-Practice 中的 iTahDoodle。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/718849.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

QT——MySQL数据库联用

一、ODBC 1、ODBC简介 ODBC全称为Open Database Connectivity,是一种用于数据库操作的标准接口。要使用ODBC,首先需要安装相应的ODBC驱动程序,然后在系统中配置ODBC数据源。接着,可以通过编程语言(如C++、Java等)或者数据库工具(如SQL Server Management Studio)来连…

深度学习推理显卡设置

深度学习推理显卡设置 进入NVIDIA控制面板&#xff0c;选择 “管理3D设置”设置 "低延时模式"为 "“超高”"设置 “电源管理模式” 为 “最高性能优先” 使用锁频来获得稳定的推理 法一&#xff1a;命令行操作 以管理员身份打开CMD查看GPU核心可用频率&…

AIoT设备新一代高性能处理器瑞芯微RK3576,东胜物联RK3588等核心板定制开发

随着物联网、人工智能和嵌入式技术的不断发展&#xff0c;智能设备应用对芯片处理器的性能需求越来越高&#xff0c;以满足复杂的数据处理需求、实时性要求、复杂的算法运算和多任务处理能力。高性能的芯片可以为智能设备提供更强大的计算能力和更快速的响应速度&#xff0c;从…

通过nginx转发后应用偶发502bad gateway

序言 学习了一些东西&#xff0c;如何才是真正自己能用的呢&#xff1f;好像就是看自己的潜意识的反应&#xff0c;例如解决了一个问题&#xff0c;那么下次再碰到类似的问题&#xff0c;能直接下意识的去找到对应的信息&#xff0c;从而解决&#xff0c;而不是和第一次碰到一样…

新手如何入门Web3?

一、什么是Web3&#xff1f; Web3是指下一代互联网&#xff0c;它基于区块链技术&#xff0c;致力于将各种在线活动变得更加安全、透明和去中心化。Web3是一个广义的概念&#xff0c;涵盖了包括数字货币、去中心化应用、智能合约等在内的多个方面。它的主要特点包括去中心化、…

网络编程--网络理论基础(二)

这里写目录标题 网络通信流程mac地址、ip地址arp协议交换机路由器简介子网划分网关 路由总结 为什么ip相同的主机在与同一个互联网服务通信时不冲突公网ip对于同一个路由器下的不同设备&#xff0c;虽然ip不冲突&#xff0c;但是因为都是由路由器的公网ip转发通信&#xff0c;接…

Apache Paimon系列之:Append Table和Append Queue

Apache Paimon系列之&#xff1a;Append Table和Append Queue 一、Append Table二、Data Distribution三、自动小文件合并四、Append Queue五、压缩六、Streaming Source七、Watermark Definition八、Bounded Stream 一、Append Table 如果表没有定义主键&#xff0c;则默认为…

Vue3基础介绍

文章目录 一、简介1、简介2、性能提升3、源码升级4、拥抱TypeScript5、新特性 二、创建Vue3.0工程1、使用vue-cli创建2、使用vite创建 三、分析工程结构1、main.js2、组件中 一、简介 1、简介 2020年9月18日&#xff0c;Vue.js发布3.0版本&#xff0c;代号(One Piece)海贼王 …

怎么用AI绘画完成设计创作?

AI绘画工具为设计师提供了强大的功能和便利性&#xff0c;用AI绘画进行艺术创作能够使设计师能够更快地迭代和优化设计方案&#xff0c;提高设计效率。那么怎么用AI绘画完成设计创作? 要使用AI绘画完成设计创作&#xff0c;首先需要选择一个合适的工具。目前市场上有很多优秀的…

KVB:怎么样选择最优交易周期?

摘要 在金融交易中&#xff0c;周期的选择是影响交易成败的重要因素之一。不同的交易周期对应不同的市场环境和交易策略&#xff0c;选择合适的周期可以提高交易的成功率。本文将详细探讨交易中如何选择最优周期&#xff0c;包括短周期、中周期和长周期的特点及适用情况&#…

CVE-2023-38836(文件上传+命令执行)

简介 BoidCMS v.2.0.0 存在文件上传漏洞&#xff0c;远程攻击者可通过添加 GIF 头部绕过 MIME 类型检查&#xff0c;执行任意代码。 过程 打开靶场 对网站进行目录扫描 发现后台&#xff0c;登录弱口令账号密码 admin/password 发现文件上传位置 根据简介提示&#xff0c;…

Vue57-组件的自定义事件_解绑

给谁绑的自定义事件&#xff0c;就找谁去触发&#xff1b;给谁绑的自定义事件&#xff0c;就找谁去解绑&#xff1b; 一、解绑自定义事件 1-1、解绑一个自定义事件 到student.vue组件中去解绑。 1-2、解绑多个自定义事件 使用数组来解绑多个。 1-3、解绑所有的自定义事件 二、…

django学习入门系列之第三点《快速了解 CSS》

文章目录 CSS快速了解CSS应用方式在标签上在head标签中写到文件中问题&#xff1a;用Flask框架开发不方便 往期回顾 CSS CSS 专门用来"美化"标签 基础CSS,写简单的界面 &能看懂 &会改就行模块&#xff0c;调整和修改 快速了解 style 这种就叫css样式 &l…

aasist-bladedisc 音频反欺骗算法模型

AASIST 论文 参考ASIST: Audio Anti-Spoofing using Integrated Spectro-Temporal Graph Attention Networks https://arxiv.org/pdf/2110.01200.pdf 模型结构 aasist是一种开源的音频反欺诈的模型&#xff0c;主要的模型结构如下所示&#xff1a; 算法原理 环境配置 Dock…

Python实现逻辑回归与判别分析--西瓜数据集

数据 数据data内容如下&#xff1a; 读取数据&#xff1a; import numpy as np import pandas as pd data pd.read_excel(D:/files/data.xlsx) 将汉字转化为01变量&#xff1a; label [] for i in data[好瓜]:l np.where(i 是,1,0)label.append(int(l)) data[label] lab…

测试单选框

单选按钮&#xff1a;用于在一组互相排斥的选项中选择其中一项&#xff1b; 由一个圆圈和紧随其后的文本标题组成&#xff0c;当它被选中时&#xff0c;圆圈中就标上一个黑点。 通常将一组单选按钮放在一个组框控件中&#xff0c;在一组单选按钮中&#xff0c;第一个(Tab键顺序…

深度神经网络——什么是NLP(自然语言处理)?

自然语言处理&#xff08;NLP&#xff09; 是对使计算机能够处理、分析、解释和推理人类语言的技术和工具的研究和应用。 NLP 是一个跨学科领域&#xff0c;它结合了语言学和计算机科学等领域已建立的技术。 这些技术与人工智能结合使用来创建聊天机器人和数字助理&#xff0c;…

xml与动态SQL

XML映射文件 规范 XML映射文件的名称与Mapper接口名称一致,并且将XML映射文件和Mapper接口放置在相同包下(同包同名)。 ● XML映射文件的namespace属性为Mapper接口全限定名一致。 ● XML映射文件中sql语句的id与Mapper接口中的方法名一致,并保持返回类型一致。 动态SQL &…

【论文复现|智能算法改进】基于多策略的改进蜜獾算法及其应用

目录 1.算法原理2.改进点3.结果展示4.参考文献5.代码获取 1.算法原理 【智能算法】蜜獾算法&#xff08;HBA&#xff09;原理及实现 2.改进点 限制反向学习机制 在挖掘模式和蜂蜜模式不同路径更新的基础上引入限制反向学习机制&#xff0c;在算法迭代时&#xff0c;对当前的…

【读博日记】拓扑结构(待修正)

Topology 拓扑学 内容来源于互联网&#xff0c;还在甄别中——20240617 拓扑结构指把实体抽象成与其形状大小无关的点&#xff0c;把连接实体的线路抽象成线&#xff0c;再研究这些电线之间的关系。 所谓相似的拓扑结构&#xff1a; 例如一个圆环变成正方形、长方形、三角形…