iOS多线程篇:NSThread简单介绍和使用

一、什么是NSThread

NSThread是基于线程使用,轻量级的多线程编程方法(相对GCD和NSOperation),一个NSThread对象代表一个线程,

需要手动管理线程的生命周期,处理线程同步等问题。

二、NSThread方法介绍

1)动态创建


1

NSThread * newThread = [[NSThread alloc]initWithTarget:self

selector:@selector(threadRun) object:nil];

动态方法返回一个新的thread对象,需要调用start方法来启动线程

2)静态创建


1

[NSThread detachNewThreadSelector:@selector(threadRun) toTarget:self withObject:nil];

由于静态方法没有返回值,如果需要获取新创建的thread,需要在selector中调用获取当前线程的方法

3)线程开启


1

[newThread start];

4)线程暂停


1

2

[NSThread sleepForTimeInterval:1.0]; (以暂停一秒为例)

[NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:1.0]];

NSThread的暂停会有阻塞当前线程的效果

5)线程取消


1

[newThread cancel];

取消线程并不会马上停止并退出线程,仅仅只作(线程是否需要退出)状态记录

6)线程停止


1

[NSThread exit];

停止方法会立即终止除主线程以外所有线程(无论是否在执行任务)并退出,需要在掌控所有线程状态的情况下调用此方法,

否则可能会导致内存问题。

7)获取当前线程


1

[NSThread currentThread];

8)获取主线程


1

[NSThread mainThread];

9)线程优先级设置

iOS 8以前使用


1

[NSThread setThreadPriority:1.0];

这个方法的优先级的数值设置让人困惑,因为你不知道你应该设置多大的值是比较合适的,因此在iOS8之后,threadPriority添加了

一句注释:To be deprecated; use qualityOfService below

意思就是iOS 8以后推荐使用qualityOfService属性,通过量化的优先级枚举值来设置

qualityOfService的枚举值如下:

  • NSQualityOfServiceUserInteractive:最高优先级,用于用户交互事件
  • NSQualityOfServiceUserInitiated:次高优先级,用于用户需要马上执行的事件
  • NSQualityOfServiceDefault:默认优先级,主线程和没有设置优先级的线程都默认为这个优先级
  • NSQualityOfServiceUtility:普通优先级,用于普通任务
  • NSQualityOfServiceBackground:最低优先级,用于不重要的任务

比如给线程设置次高优先级:


1

[newThread setQualityOfService:NSQualityOfServiceUserInitiated];

三、线程间通信

常用的有三种:

1、指定当前线程执行操作


1

2

3

[self performSelector:@selector(threadRun)];

[self performSelector:@selector(threadRun) withObject:nil];

[self performSelector:@selector(threadRun) withObject:nil afterDelay:2.0];

2、(在其他线程中)指定主线程执行操作


1

[self performSelectorOnMainThread:@selector(threadRun) withObject:nil

waitUntilDone:YES];

注意:更新UI要在主线程中进行

3、(在主线程中)指定其他线程执行操作


1

2

[self performSelector:@selector(threadRun) onThread:newThread

withObject:nil waitUntilDone:YES];

//这里指定为某个线程

[self performSelectorInBackground:@selector(threadRun) withObject:nil];

//这里指定为后台线程

四、线程同步

线程和其他线程可能会共享一些资源,当多个线程同时读写同一份共享资源的时候,可能会引起冲突。线程同步是指是指在一定的时间内只允许

某一个线程访问某个资源

iOS实现线程加锁有NSLock和@synchronized两种方式。

五、线程的创建和使用实例:模拟售票

情景:某演唱会门票发售,在广州和北京均开设窗口进行销售,以下是代码实现

先监听线程退出的通知,以便知道线程什么时候退出


1

[[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(threadExitNotice)

name:NSThreadWillExitNotification object:nil];

设置演唱会的门票数量


1

_ticketCount = 50;

新建两个子线程(代表两个窗口同时销售门票)


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

NSThread * window1 = [[NSThread alloc]initWithTarget:self

selector:@selector(saleTicket) object:nil];

window1.name = @"北京售票窗口";

[window1 start];

NSThread * window2 = [[NSThread alloc]initWithTarget:self

selector:@selector(saleTicket) object:nil];

window2.name = @"广州售票窗口";

[window2 start];

线程启动后,执行saleTicket,执行完毕后就会退出,为了模拟持续售票的过程,

我们需要给它加一个循环

- (void)saleTicket {

    while (1) {

    //如果还有票,继续售卖

        if (_ticketCount > 0) {

        _ticketCount --;

        NSLog(@"%@", [NSString stringWithFormat:@"剩余票数:%ld 窗口:%@", _ticketCount, [NSThread currentThread].name]);

        [NSThread sleepForTimeInterval:0.2];

    }

    //如果已卖完,关闭售票窗口

    else {

        break;

    }

}

}

执行结果:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

2016-04-06 19:25:36.637 MutiThread[4705:1371666] 剩余票数:9 窗口:广州售票窗口

2016-04-06 19:25:36.637 MutiThread[4705:1371665] 剩余票数:8 窗口:北京售票窗口

2016-04-06 19:25:36.839 MutiThread[4705:1371666] 剩余票数:7 窗口:广州售票窗口

2016-04-06 19:25:36.839 MutiThread[4705:1371665] 剩余票数:7 窗口:北京售票窗口

2016-04-06 19:25:37.045 MutiThread[4705:1371666] 剩余票数:5 窗口:广州售票窗口

2016-04-06 19:25:37.045 MutiThread[4705:1371665] 剩余票数:6 窗口:北京售票窗口

2016-04-06 19:25:37.250 MutiThread[4705:1371665] 剩余票数:4 窗口:北京售票窗口

2016-04-06 19:25:37.250 MutiThread[4705:1371666] 剩余票数:4 窗口:广州售票窗口

2016-04-06 19:25:37.456 MutiThread[4705:1371666] 剩余票数:2 窗口:广州售票窗口

2016-04-06 19:25:37.456 MutiThread[4705:1371665] 剩余票数:3 窗口:北京售票窗口

2016-04-06 19:25:37.661 MutiThread[4705:1371665] 剩余票数:1 窗口:北京售票窗口

2016-04-06 19:25:37.661 MutiThread[4705:1371666] 剩余票数:1 窗口:广州售票窗口

2016-04-06 19:25:37.866 MutiThread[4705:1371665] 剩余票数:0 窗口:北京售票窗口

2016-04-06 19:25:37.867 MutiThread[4705:1371666] <nsthread: 0x7fdc91e289f0>

{number = 3, name = 广州售票窗口} Will Exit

2016-04-06 19:25:38.070 MutiThread[4705:1371665] <nsthread: 0x7fdc91e24d60>

{number = 2, name = 北京售票窗口} Will Exit</nsthread: 0x7fdc91e24d60>

</nsthread: 0x7fdc91e289f0>

可以看到,票的销售过程中出现了剩余数量错乱的情况,这就是前面提到的线程同步问题。

售票是一个典型的需要线程同步的场景,由于售票渠道有很多,而票的资源是有限的,当多个渠道在短时间内卖出大量

的票的时候,如果没有同步机制来管理票的数量,将会导致票的总数和售出票数对应不上的错误。

我们在售票的过程中给票加上同步锁:同一时间内,只有一个线程能对票的数量进行操作,当操作完成之后,其他线程

才能继续对票的数量进行操作。


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

- (void)saleTicket {

    while (1) {

    @synchronized(self) {

        //如果还有票,继续售卖

        if (_ticketCount > 0) {

        _ticketCount --;

        NSLog(@"%@", [NSString stringWithFormat:@"剩余票数:%ld 窗口:%@", _ticketCount, [NSThread currentThread].name]);

        [NSThread sleepForTimeInterval:0.2];

        }

        //如果已卖完,关闭售票窗口

        else {

                break;

            }

        }

    }

}

运行结果:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

2016-04-06 19:31:27.913 MutiThread[4718:1406865] 剩余票数:11 窗口:北京售票窗口

2016-04-06 19:31:28.115 MutiThread[4718:1406866] 剩余票数:10 窗口:广州售票窗口

2016-04-06 19:31:28.317 MutiThread[4718:1406865] 剩余票数:9 窗口:北京售票窗口

2016-04-06 19:31:28.522 MutiThread[4718:1406866] 剩余票数:8 窗口:广州售票窗口

2016-04-06 19:31:28.728 MutiThread[4718:1406865] 剩余票数:7 窗口:北京售票窗口

2016-04-06 19:31:28.929 MutiThread[4718:1406866] 剩余票数:6 窗口:广州售票窗口

2016-04-06 19:31:29.134 MutiThread[4718:1406865] 剩余票数:5 窗口:北京售票窗口

2016-04-06 19:31:29.339 MutiThread[4718:1406866] 剩余票数:4 窗口:广州售票窗口

2016-04-06 19:31:29.545 MutiThread[4718:1406865] 剩余票数:3 窗口:北京售票窗口

2016-04-06 19:31:29.751 MutiThread[4718:1406866] 剩余票数:2 窗口:广州售票窗口

2016-04-06 19:31:29.952 MutiThread[4718:1406865] 剩余票数:1 窗口:北京售票窗口

2016-04-06 19:31:30.158 MutiThread[4718:1406866] 剩余票数:0 窗口:广州售票窗口

2016-04-06 19:31:30.363 MutiThread[4718:1406866] <nsthread: 0x7ff0c1637320>

{number = 3, name = 广州售票窗口} Will Exit

2016-04-06 19:31:30.363 MutiThread[4718:1406865] <nsthread: 0x7ff0c1420cb0>

{number = 2, name = 北京售票窗口} Will Exit</nsthread: 0x7ff0c1420cb0>

</nsthread: 0x7ff0c1637320>

可以看到,票的数量没有出现错乱的情况。

线程的持续运行和退出

我们注意到,线程启动后,执行saleTicket完毕后就马上退出了,怎样能让线程一直运行呢(窗口一直开放,

可以随时指派其卖演唱会的门票的任务),答案就是给线程加上runLoop


1

2

//先监听线程退出的通知,以便知道线程什么时候退出

[[NSNotificationCenter defaultCenter]addObserver:self

selector:@selector(threadExitNotice)

name:NSThreadWillExitNotification object:nil];


1

2

//设置演唱会的门票数量

_ticketCount = 50;

新建两个子线程(代表两个窗口同时销售门票)


1

2

3

4

NSThread * window1 = [[NSThread alloc]initWithTarget:self

selector:@selector(thread1) object:nil];

[window1 start];

NSThread * window2 = [[NSThread alloc]initWithTarget:self

selector:@selector(thread2) object:nil];

[window2 start];

接着我们给线程创建一个runLoop


1

2

3

4

5

6

7

8

9

10

- (void)thread1 {

    [NSThread currentThread].name = @"北京售票窗口";

    NSRunLoop * runLoop1 = [NSRunLoop currentRunLoop];

    [runLoop1 runUntilDate:[NSDate date]]; //一直运行

}

- (void)thread2 {

    [NSThread currentThread].name = @"广州售票窗口";

    NSRunLoop * runLoop2 = [NSRunLoop currentRunLoop];

    [runLoop2 runMode:NSDefaultRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:10.0]]; //自定义运行时间

}

然后就可以指派任务给线程了,这里我们让两个线程都执行相同的任务(售票)


1

2

[self performSelector:@selector(saleTicket) onThread:window1

withObject:nil waitUntilDone:NO];

[self performSelector:@selector(saleTicket) onThread:window2

withObject:nil waitUntilDone:NO];

运行结果:


1

2

3

4

5

6

7

8

9

10

11

12

13

2016-04-06 19:43:22.585 MutiThread[4762:1478200] 剩余票数:11 窗口:北京售票窗口

2016-04-06 19:43:22.788 MutiThread[4762:1478201] 剩余票数:10 窗口:广州售票窗口

2016-04-06 19:43:22.993 MutiThread[4762:1478200] 剩余票数:9 窗口:北京售票窗口

2016-04-06 19:43:23.198 MutiThread[4762:1478201] 剩余票数:8 窗口:广州售票窗口

2016-04-06 19:43:23.404 MutiThread[4762:1478200] 剩余票数:7 窗口:北京售票窗口

2016-04-06 19:43:23.609 MutiThread[4762:1478201] 剩余票数:6 窗口:广州售票窗口

2016-04-06 19:43:23.810 MutiThread[4762:1478200] 剩余票数:5 窗口:北京售票窗口

2016-04-06 19:43:24.011 MutiThread[4762:1478201] 剩余票数:4 窗口:广州售票窗口

2016-04-06 19:43:24.216 MutiThread[4762:1478200] 剩余票数:3 窗口:北京售票窗口

2016-04-06 19:43:24.422 MutiThread[4762:1478201] 剩余票数:2 窗口:广州售票窗口

2016-04-06 19:43:24.628 MutiThread[4762:1478200] 剩余票数:1 窗口:北京售票窗口

2016-04-06 19:43:24.833 MutiThread[4762:1478201] 剩余票数:0 窗口:广州售票窗口

2016-04-06 19:43:25.039 MutiThread[4762:1478201]

<nsthread: 0x7fe0d3c24360>{number = 3, name = 广州售票窗口}

Will Exit</nsthread: 0x7fe0d3c24360>

可以看到,当票卖完后,两个线程并没有退出,仍在继续运行,当到达指定时间后,线程2退出了,

如果需要让线程1退出,需要我们手动管理。

比如我们让线程完成任务(售票)后自行退出,可以这样操作


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

- (void)saleTicket {

    while (1) {

        @synchronized(self) {

        //如果还有票,继续售卖

        if (_ticketCount > 0) {

        _ticketCount --;

            NSLog(@"%@", [NSString stringWithFormat:@"剩余票数:%ld 窗口:%@", _ticketCount, [NSThread currentThread].name]);

            [NSThread sleepForTimeInterval:0.2];

        }

        //如果已卖完,关闭售票窗口

        else {

            if ([NSThread currentThread].isCancelled) {

            break;

        }else {

            NSLog(@"售卖完毕");

            //给当前线程标记为取消状态

            [[NSThread currentThread] cancel];

            //停止当前线程的runLoop

            CFRunLoopStop(CFRunLoopGetCurrent());

            }

        }

      }

    }

}

运行结果:


1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

2016-04-06 20:08:38.287 MutiThread[4927:1577193] 剩余票数:10 窗口:北京售票窗口

2016-04-06 20:08:38.489 MutiThread[4927:1577194] 剩余票数:9 窗口:广州售票窗口

2016-04-06 20:08:38.690 MutiThread[4927:1577193] 剩余票数:8 窗口:北京售票窗口

2016-04-06 20:08:38.892 MutiThread[4927:1577194] 剩余票数:7 窗口:广州售票窗口

2016-04-06 20:08:39.094 MutiThread[4927:1577193] 剩余票数:6 窗口:北京售票窗口

2016-04-06 20:08:39.294 MutiThread[4927:1577194] 剩余票数:5 窗口:广州售票窗口

2016-04-06 20:08:39.499 MutiThread[4927:1577193] 剩余票数:4 窗口:北京售票窗口

2016-04-06 20:08:39.700 MutiThread[4927:1577194] 剩余票数:3 窗口:广州售票窗口

2016-04-06 20:08:39.905 MutiThread[4927:1577193] 剩余票数:2 窗口:北京售票窗口

2016-04-06 20:08:40.106 MutiThread[4927:1577194] 剩余票数:1 窗口:广州售票窗口

2016-04-06 20:08:40.312 MutiThread[4927:1577193] 剩余票数:0 窗口:北京售票窗口

2016-04-06 20:08:40.516 MutiThread[4927:1577194] 售卖完毕

2016-04-06 20:08:40.516 MutiThread[4927:1577193] 售卖完毕

2016-04-06 20:08:40.517 MutiThread[4927:1577193]

<nsthread: 0x7fb719d54000>{number = 2, name = 北京售票窗口} Will Exit

2016-04-06 20:08:40.517 MutiThread[4927:1577194]

<nsthread: 0x7fb719d552f0>{number = 3, name = 广州售票窗口}

Will Exit</nsthread: 0x7fb719d552f0></nsthread: 0x7fb719d54000>

如果确定两个线程都是isCancelled状态,可以调用[NSThread exit]方法来终止线程。

NSThread

  • 一个NSThread对象就代表一条线程
  • NSThread会在执行完任务函数是被自动收回
  • 一些常用的函数
    //创建线程
    NSThread *thread = [[NSThread alloc]initWithTarget:self selector:@selector() object:nil];
    //object存的是参数

    //修改参数名
    thread.name = @"我的多线程";

    //获取主线程
    NSThread *thread = [NSThread mainThread];

    //创建线程并自动启动
    [NSThread detachNewThreadSelector:@selector() toTarget:self withObject:nil];

    //隐士创建
    [self performSelectorInBackground:@selector() withObject:nil];

    //获取当前线程
    [NSThread currentThread]

    //启动线程
    - (void)start;

    //阻塞(暂停)线程
    + (void)sleepUntilDate:(NSDate *)date;
    + (void)sleepForTimeInterval:(NSTimeInterval)ti;
    // 进入阻塞状态

    //停止当前正在运行的进程
    + (void)exit;
    // 进入死亡状态,一旦死亡则不能重启

资源共享

  • 1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源
  • 当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题

解决办法互斥锁

  • 互斥锁使用格式

    • @synchronized(锁对象) { // 需要锁定的代码 }
    • 只用一把锁,多锁是无效的
  • 互斥锁的优缺点
    • 优点:能有效防止因多线程抢夺资源造成的数据安全问题
    • 缺点:需要消耗大量的CPU资源
  • 互斥锁的使用前提:多条线程抢夺同一块资源
  • 互斥锁的示例代码
#import "ViewController.h"

@interface ViewController ()
/** 售票机1*/
@property (strong,nonatomic) NSThread *threadOne;
/** 售票机2*/
@property (strong,nonatomic) NSThread *threadTwo;
/** 售票机3*/
@property (strong,nonatomic) NSThread *threadThree;
/** 售票机4*/
@property (strong,nonatomic) NSThread *threadFour;
/** 售票机5*/
@property (strong,nonatomic) NSThread *threadFive;

/** 数量*/
@property (assign,nonatomic) NSInteger count;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    //创建线程
    self.threadOne = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"one"];
    self.threadTwo = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"two"];
    self.threadThree = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"three"];
    self.threadFour = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"four"];
    self.threadFive = [[NSThread alloc] initWithTarget:self selector:@selector(run:) object:@"five"];
    self.count = 100;
}

-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event
{
    //开始线程
    [self.threadOne start];
    [self.threadTwo start];
    [self.threadThree start];
    [self.threadFour start];
    [self.threadFive start];
}

- (void)run:(NSString *)param
{
    while (1) {
        //self是锁对象
        @synchronized(self)
        {

            if (self.count > 0) {
                _count--;
                NSLog(@"%zd-----%@",self.count,[NSThread currentThread]);
            }
            else
            {
                NSLog(@"卖完了----%@",[NSThread currentThread]);
                break;
            }
        }
    }
}
@end

时间: 2025-01-16 11:56:45

iOS多线程篇:NSThread简单介绍和使用的相关文章

iOS开发多线程篇—NSOperation简单介绍

iOS开发多线程篇—NSOperation简单介绍 一.NSOperation简介 1.简单说明 NSOperation的作?:配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤: (1)先将需要执行的操作封装到一个NSOperation对象中 (2)然后将NSOperation对象添加到NSOperationQueue中 (3)系统会?动将NSOperationQueue中的NSOpe

OS开发多线程篇—NSOperation简单介绍

iOS开发多线程篇—NSOperation简单介绍 一.NSOperation简介 1.简单说明 NSOperation的作?:配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤: (1)先将需要执行的操作封装到一个NSOperation对象中 (2)然后将NSOperation对象添加到NSOperationQueue中 (3)系统会?动将NSOperationQueue中的NSOpe

关于ios多线程GCD的简单介绍

很久没写博客了,实在太忙了,没有时间写.现在终于空闲下来了,今天就给大家介绍下ios开发里GCD的用法. 刚开始学习的新手,或许对多线程很迷茫,那么什么是线程呢?其实很简单,不要想那么复杂. 1.我们通常知道进程,就是正在执行中的程序,每个进程有自己独立的内存空间,进程之间互相不干涉.(就比如你打开微信) 2.什么是线程?线程是进程执行的基本单元.进程中的任务是在线程中执行的,进程在启动后会自动蜕化为主线程(ios UI Main thread),然后在执行任务. 3.线程的串航执行,比如我要下

【iOS开发】NSOperation简单介绍

iOS开发多线程篇—NSOperation简单介绍 一.NSOperation简介 1.简单说明 NSOperation的作?:配合使用NSOperation和NSOperationQueue也能实现多线程编程 NSOperation和NSOperationQueue实现多线程的具体步骤: (1)先将需要执行的操作封装到一个NSOperation对象中 (2)然后将NSOperation对象添加到NSOperationQueue中 (3)系统会?动将NSOperationQueue中的NSOpe

iOS开发数据库篇—FMDB简单介绍

iOS开发数据库篇—FMDB简单介绍 一.简单说明 1.什么是FMDB FMDB是iOS平台的SQLite数据库框架 FMDB以OC的方式封装了SQLite的C语言API 2.FMDB的优点 使用起来更加面向对象,省去了很多麻烦.冗余的C语言代码 对比苹果自带的Core Data框架,更加轻量级和灵活 提供了多线程安全的数据库操作方法,有效地防止数据混乱 3.FMDB的github地址 https://github.com/ccgus/fmdb 二.核心类 FMDB有三个主要的类 (1)FMDa

iOS开发拓展篇-XMPP简单介绍

iOS开发拓展篇-XMPP简单介绍 一.即时通讯简单介绍 1.简单说明 即时通讯技术(IM)支持用户在线实时交谈.如果要发送一条信息,用户需要打开一个小窗口,以便让用户及其朋友在其中输入信息并让交谈双方都看到交谈的内容 有许多的IM系统,如AOL IM.Yahoo IM. MSN以及QQ,它们最大的区别在于各自通讯协议的实现,所以即时通讯技术的核心在于它的传输协议 协议用来说明信息在网络上如何传输,如果有了统一的传输协议,那么应当可以实现各个IM之间的直接通讯,为了创建即时通讯的统一标准,目前已

iOS开发UI篇-UIWindow简单介绍

iOS开发UI篇—UIWindow简单介绍 一.简单介绍 UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的view,最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了 一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWindow.也就说,没有UIWindow,就看不见任何UI界面 补充:UIWindow是创建的第一个视图控件(创建的第一个

文顶顶 iOS开发UI篇—Kvc简单介绍

ios开发UI篇—Kvc简单介绍 一.KVC简单介绍 KVC key valued coding 键值编码 KVC通过键值间接编码 补充: 与KVC相对的时KVO,即key valued observer 键值观察.监听某一个模型的属性,只要模型属性的值一变化就通知你. 二.使用KVC 1.KVC基本使用介绍 (1)代码示例: 新建一个命令行项目,用以演示KVC的用法 完成之后为项目添加一个Person类. 为Person类添加两个属性(name和age),注意这两个属性的类型. 1 #impo

iOS开发UI篇—UIWindow简单介绍

iOS开发UI篇—UIWindow简单介绍 - 文顶顶 - 博客园 文顶顶 iOS开发UI篇—UIWindow简单介绍 iOS开发UI篇—UIWindow简单介绍 一.简单介绍 UIWindow是一种特殊的UIView,通常在一个app中只会有一个UIWindow iOS程序启动完毕后,创建的第一个视图控件就是UIWindow,接着创建控制器的view,最后将控制器的view添加到UIWindow上,于是控制器的view就显示在屏幕上了 一个iOS程序之所以能显示到屏幕上,完全是因为它有UIWi

iOS开发UI篇—Modal简单介绍

iOS开发UI篇—Modal简单介绍 一.简单介绍 除了push之外,还有另外一种控制器的切换方式,那就是Modal 任何控制器都能通过Modal的形式展?出来 Modal的默认效果:新控制器从屏幕的最底部往上钻,直到盖住之前的控制器为? 二.代码说明 新建一个项目,在Application的代理中添加window和控制器. TXAppDelegate.m文件 1 #import "TXAppDelegate.h" 2 #import "TXOneViewController