UI学习2

UI学习2

定时器和视图移动

NSTimer是Foundation框架提供的定时器,可以在指定时间间隔后执行某个方法。通过定时器,我们可以让视图连续移动,实现简单的动画效果。

我们先定义一个定时器对象

objectivec 复制代码
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    NSTimer* time;
}
@property (retain, nonatomic) NSTimer* timeView;
@end
objectivec 复制代码
#import "ViewController.h"

@interface ViewController ()
  
@end

@implementation ViewController
@synthesize timeView = time;

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 创建"启动定时器"按钮
    UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    button.frame = CGRectMake(100, 100, 100, 100);
    [button setTitle:@"启动定时器" forState:UIControlStateNormal];
    [button addTarget:self action:@selector(pressStart) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:button];
    
    // 创建"停止定时器"按钮
    UIButton *buttonStop = [UIButton buttonWithType:UIButtonTypeRoundedRect];
    buttonStop.frame = CGRectMake(100, 200, 100, 100);
    [buttonStop setTitle:@"停止定时器" forState:UIControlStateNormal];
    [buttonStop addTarget:self action:@selector(pressStop) forControlEvents:UIControlEventTouchUpInside];
    [self.view addSubview:buttonStop];
    
    // 创建一个蓝色方块,设置初始位置和大小
    UIView *view = [[UIView alloc] init];
    view.frame = CGRectMake(0, 0, 80, 80);   // 初始位置 (0,0)
    view.backgroundColor = [UIColor blueColor];
    [self.view addSubview:view];
    view.tag = 101;   // 设置标签,便于在定时器回调中获取该视图
}

// 启动定时器的方法
- (void)pressStart {
    // 如果定时器已经存在,先停止并释放
    if (time != nil) {
        [time invalidate];
        time = nil;
    }
    // 创建并启动一个重复定时器,每 0.1 秒调用 updateTimer: 方法
    // 注意:必须将定时器赋值给 time 变量,否则 pressStop 无法停止
    time = [NSTimer scheduledTimerWithTimeInterval:0.1 target:self selector:@selector(updateTimer:) userInfo:@"小明" repeats:YES];
}

// 定时器回调方法
- (void)updateTimer:(NSTimer *)timer {
    // 打印 userInfo 中的信息
    NSLog(@"%@ test", timer.userInfo);
    // 通过 tag 获取之前创建的蓝色方块
    UIView *view = [self.view viewWithTag:101];
    // 每次移动视图的 origin 向右下各增加 1 点
    view.frame = CGRectMake(view.frame.origin.x + 1,
                            view.frame.origin.y + 1,
                            80, 80);
}

// 停止定时器的方法
- (void)pressStop {
    if (time != nil) {
        [time invalidate];   // 停止定时器
        time = nil;          // 清空指针,防止野指针
    }
}

@end
  • scheduledTimerWithTimeInterval:0.1 表示每隔 0.1 秒触发一次。
  • target:self 指定回调方法所在的对象。
  • selector:@selector(updateTimer:) 时间到了就调用 updateTimer: 方法。
  • userInfo:@"小明" 可以携带额外信息,回调里通过 timer.userInfo 取出。
  • repeats:YES 表示重复执行,否则只执行一次。
  • invalidate 让定时器失效,并且要把指针清空,避免再次调用时出现野指针。

UISwitch

UISwitch常用于开/关状态,常用于设置选项

objectivec 复制代码
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController

{
    UISwitch* _switch;
}

@property (retain, nonatomic) UISwitch* mySwitch;
@end
objectivec 复制代码
#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController
@synthesize mySwitch = _switch;

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 创建 UISwitch 开关控件
    _switch = [[UISwitch alloc] init];
    // 设置开关的位置(大小固定,只有 origin 有效,width/height 被忽略)
    _switch.frame = CGRectMake(100, 100, 80, 40);
    // 设置开关的背景颜色
    _switch.backgroundColor = [UIColor redColor];
    // 设置开关初始状态为开启
    _switch.on = YES;
    // 重复设置 on 状态(无额外效果)
    [_switch setOn:YES];
    // 带动画地设置开关状态(这里再次设为 YES,因为已经是 YES,动画无变化)
    [_switch setOn:YES animated:YES];
    // 将开关添加到当前视图
    [self.view addSubview:_switch];
    
    // 设置开关开启时的轨道颜色(蓝色)
    [_switch setOnTintColor:[UIColor blueColor]];
    // 设置开关滑块的颜色(红色)
    [_switch setThumbTintColor:[UIColor redColor]];
    
    // 为开关添加事件:值改变时调用 swChange: 方法
    [_switch addTarget:self action:@selector(swChange:) forControlEvents:UIControlEventValueChanged];
    
    // 创建 UILabel 标签
    UILabel *label = [[UILabel alloc] init];
    label.text = @"张璐阳控制器";
    label.font = [UIFont systemFontOfSize:16];
    // 设置标签位置和大小(x=100, y=110, width=100, height=200)
    label.frame = CGRectMake(100, 110, 100, 200);
    label.textColor = [UIColor greenColor];
    [self.view addSubview:label];
}

// 开关状态改变时调用的方法
- (void)swChange:(UISwitch *)sw {
    if (sw.on == YES) {
        NSLog(@"已打开");
    } else if (sw.on == NO) {
        NSLog(@"已关闭");
    }
}

@end
  • 虽然 frame 可以设置位置,但开关的尺寸是系统固定的,宽高设置会被忽略。
  • addTarget:action:forControlEvents: 监听值改变事件,当用户拨动开关时就会调用 swChange: 方法。
  • 通过 sw.on 获取当前开关状态,做对应的逻辑处理。

UISlider和UIprogressView

UISlider 允许用户在最小值和最大值之间选择一个值,常用于音量、亮度调节等,UIProgressView 用于显示任务完成进度,如下载进度、播放进度等。

objectivec 复制代码
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    UIProgressView* pro;
    UISlider* sli;
}

@property (retain, nonatomic) UIProgressView* Pro;
@property (retain, nonatomic) UISlider* Sli;
@end
objectivec 复制代码
#import "ViewController.h"

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    // 创建进度条 UIProgressView
    pro = [[UIProgressView alloc] init];
    // 设置进度条的位置和大小(x=100, y=100, width=200, height=40,但高度固定,实际只有约2~4点)
    pro.frame = CGRectMake(100, 100, 200, 40);
    // 设置进度条已完成部分的颜色(红色)
    pro.progressTintColor = [UIColor redColor];
    // 设置进度条未完成部分的颜色(黑色)
    pro.trackTintColor = [UIColor blackColor];
    // 设置初始进度为 0.5(50%)
    pro.progress = 0.5;
    // 设置进度条样式(默认样式)
    pro.progressViewStyle = UIProgressViewStyleDefault;
    // 将进度条添加到当前视图
    [self.view addSubview:pro];
    
    // 创建滑动条 UISlider
    sli = [[UISlider alloc] init];
    // 设置滑动条的位置和大小(x=40, y=100, width=300, height=40)
    sli.frame = CGRectMake(40, 100, 300, 40);
    // 设置滑动条的最大值(100)
    sli.maximumValue = 100;
    // 设置滑动条的最小值(0)
    sli.minimumValue = 0;
    // 设置滑动条的初始值(50)
    sli.value = 50;
    // 设置滑动条左侧(最小值一侧)轨道的颜色(蓝色)
    sli.minimumTrackTintColor = [UIColor blueColor];
    // 设置滑动条右侧(最大值一侧)轨道的颜色(绿色)
    sli.maximumTrackTintColor = [UIColor greenColor];
    // 设置滑块(圆形按钮)的颜色(橙色)
    sli.thumbTintColor = [UIColor orangeColor];
    // 为滑动条添加事件监听:值改变时调用 presssli 方法
    [sli addTarget:self action:@selector(presssli) forControlEvents:UIControlEventValueChanged];
    // 将滑动条添加到当前视图
    [self.view addSubview:sli];
}

// 滑动条值改变时调用的方法
- (void)presssli {
    // 根据滑动条的当前值计算进度(归一化到 0~1 范围)
    pro.progress = (sli.value - sli.minimumValue) / (sli.maximumValue - sli.minimumValue);
    // 打印当前滑动条的值
    NSLog(@"位置在%f", sli.value);
}

@end
  • minimumValue / maximumValue 决定了滑动条的数值范围。
  • 值改变时触发 presssli 方法。

等待指示器和警告对话框

objective 复制代码
#import <UIKit/UIKit.h>

@interface ViewController : UIViewController
{
    UIAlertController* _alertView;
    UIActivityIndicatorView* _activityIndicator;
}

@property (retain, nonatomic) UIAlertController* alertView;
@property (retain, nonatomic) UIActivityIndicatorView* activityIndicator;
@end
objectivec 复制代码
#import "ViewController.h"

// 类扩展,用于声明私有属性(原代码未展示,但实际需要)
@interface ViewController ()
// 注意:实际使用前应在 @interface 中声明 _alertView 和 _activityIndicator
// 例如:
// @property (nonatomic, strong) UIAlertController *alertView;
// @property (nonatomic, strong) UIActivityIndicatorView *activityIndicator;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    // 循环创建两个按钮
    for (int i = 0; i < 2; i++) {
        // 创建圆角矩形按钮
        UIButton* btn = [UIButton buttonWithType:UIButtonTypeRoundedRect];
        // 设置按钮位置:x=100, y 从 100 开始,每个按钮间隔 100 点
        btn.frame = CGRectMake(100, 100 + 100 * i, 100, 40);
        // 根据循环索引设置按钮标题
        if (i == 0) {
            [btn setTitle:@"提示对话框" forState:UIControlStateNormal];
        } else if (i == 1) {
            [btn setTitle:@"等待" forState:UIControlStateNormal];
        }
        // 设置按钮标签,方便在点击方法中区分不同按钮
        btn.tag = 101 + i;
        // 添加点击事件监听
        [btn addTarget:self action:@selector(pressBtn:) forControlEvents:UIControlEventTouchUpInside];
        // 将按钮添加到当前视图
        [self.view addSubview:btn];
    }
}
// 按钮点击回调方法
-(void) pressBtn : (UIButton*) btn {
    // 根据按钮标签执行不同操作
    if (btn.tag == 101) {
        // 创建警告框控制器(UIAlertController),样式为弹窗(Alert)
        _alertView = [UIAlertController alertControllerWithTitle:@"警告" message:@"手机电量过低" preferredStyle:UIAlertControllerStyleAlert];
        // 创建"取消"动作,样式为取消样式,点击后不做额外处理(handler 为 nil)
        UIAlertAction* cancle = [UIAlertAction actionWithTitle:@"取消" style:UIAlertActionStyleCancel handler:nil];
      [_alertView addAction:cancle];
        // 创建"新的"动作,样式为默认样式,点击后也不做处理
        UIAlertAction* newAction = [UIAlertAction actionWithTitle:@"新的" style:UIAlertActionStyleDefault handler:nil];
        [_alertView addAction:newAction];
        // 创建"确认"动作,并添加一个 block 回调,点击时输出日志
        UIAlertAction* confirm = [UIAlertAction actionWithTitle:@"确认"
 style:UIAlertActionStyleDefault handler:^(UIAlertAction* _Nonnull action) {
            NSLog(@"确认");
        }];
        [_alertView addAction:confirm];
        // 以模态方式显示警告框
        [self presentViewController:_alertView animated:YES completion:nil];
    } else if (btn.tag == 102) {
        // 创建活动指示器(菊花转圈),并设置其位置和大小
        _activityIndicator = [[UIActivityIndicatorView alloc] initWithFrame:CGRectMake(157, 300, 100, 100)];
        // 设置指示器样式为大号(白色)
        _activityIndicator.activityIndicatorViewStyle = UIActivityIndicatorViewStyleLarge;
        // 将指示器添加到当前视图
        [self.view addSubview:_activityIndicator];
        // 开始动画(旋转显示)
        [_activityIndicator startAnimating];
    }
}
@end
  • UIAlertController:使用 alertControllerWithTitle:message:preferredStyle:创建,样式有 UIAlertControllerStyleAlert(弹窗)和 ActionSheet(底部上滑)。
  • UIAlertAction:代表一个按钮,可以设置标题、样式和点击后的回调 handler
  • presentViewController:animated:completion: 显示对话框。
  • UIActivityIndicatorView:创建后设置样式(UIActivityIndicatorViewStyleLarge 为大号),调用 startAnimating 开始旋转,stopAnimating 停止。

生命周期

  1. init / initWithCoder:
  • 调用时机:控制器通过代码或 Storyboard/XIB 创建时。
  • 作用:执行最基本的初始化,此时视图尚未加载。
  • 注意:一般不在这里操作界面相关的属性,因为视图还未存在。
  1. loadView
  • 调用时机 :当控制器的 view 被访问但为 nil 时调用。
  • 作用:创建控制器的根视图。如果使用 Storyboard 或 XIB,通常不需要重写此方法;纯代码方式可以在这里自定义根视图。
  • 注意不要 手动调用此方法。如果重写,必须自己创建 self.view,并且不要调用 [super loadView]
  1. viewDidLoad
  • 调用时机:视图加载完成后调用(只调用一次)。
  • 作用:进行界面初始化、添加子视图、加载数据、设置通知等。
  • 注意 :此时视图的 frame 可能还未最终确定(因为布局尚未计算),不要在这里依赖视图的尺寸进行精细布局。
objectivec 复制代码
- (void)viewDidLoad {
    [super viewDidLoad];
    // 添加子视图、设置初始数据
    self.view.backgroundColor = [UIColor whiteColor];
    UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
    btn.frame = CGRectMake(100, 100, 100, 40);
    [btn setTitle:@"点我" forState:UIControlStateNormal];
    [self.view addSubview:btn];
}
  1. viewWillAppear:
  • 调用时机:视图即将添加到视图层级上并显示在屏幕上时调用(每次出现都会调用)。
  • 作用:执行每次显示前需要做的操作,比如更新数据、刷新界面、注册键盘通知等。
  • 参数animated 表示是否有动画。
  1. viewDidAppear:
  • 调用时机:视图已经完全显示在屏幕上后调用(每次出现都会调用)。
  • 作用:开始动画、启动定时器、发起网络请求等。用户已经看到界面,适合做需要可见后才执行的操作。
  1. viewWillDisappear:
  • 调用时机:视图即将从视图层级中移除(即将被遮盖或关闭)时调用。
  • 作用:保存用户输入、停止正在进行的任务、释放临时资源等。
  1. viewDidDisappear:
  • 调用时机:视图已经从视图层级中移除后调用。
  • 作用:停止动画、移除通知、清理不需要的资源。
  1. didReceiveMemoryWarning
  • 调用时机:系统内存紧张时调用。
  • 作用 :释放可重建的资源(如缓存图片、未显示的视图等)。如果控制器有不再需要的视图,系统会自动将 view 设为 nil
objectivec 复制代码
- (void)didReceiveMemoryWarning {
    [super didReceiveMemoryWarning];
    // 清理缓存等可重建的资源
}
  1. dealloc
  • 调用时机:控制器被释放时调用。
  • 作用:清理通知、定时器、代理等,避免内存泄漏。
objectivec 复制代码
- (void)dealloc {
    [[NSNotificationCenter defaultCenter] removeObserver:self];
    [timer invalidate];
    timer = nil;
}
相关推荐
sp_fyf_20242 小时前
【大语言模型】 语言模型学习什么以及何时学习?隐式课程假说
人工智能·学习·语言模型
拥抱AGI2 小时前
Qwen3.5开源矩阵震撼发布!从0.8B到397B,不同规模模型性能、显存、速度深度对比与选型指南来了!
人工智能·学习·程序员·开源·大模型·大模型训练·qwen3.5
sp_fyf_20242 小时前
【大语言模型】从失败中学习:在微调大型语言模型作为智能体时整合负例
人工智能·深度学习·学习·机器学习·语言模型·自然语言处理
秋雨梧桐叶落莳3 小时前
【iOS】 AutoLayout初步学习
学习·macos·ios·objective-c·cocoa·xcode
for_ever_love__3 小时前
Objective-C学习UI 的初步了解(2)
学习·ui·objective-c
m0_716765233 小时前
数据结构--顺序表的插入、删除、查找详解
c语言·开发语言·数据结构·c++·学习·算法·visual studio
我要成为嵌入式大佬3 小时前
学习linux的部分疑惑与解答(非专业)
学习
Дерек的学习记录3 小时前
Unreal Eangie 5:蓝图编程
开发语言·学习·ue5
AI科技星3 小时前
基于v≡c第一性原理:密度的本质与时空动力学
人工智能·学习·算法·机器学习·数据挖掘