属性 | 类型 | 解释 |
---|---|---|
currentThread | NSThread | 获取当前线程的一些信息 |
threadDictionary | NSMutableDictionary(readOnly) | 线程的一些本地属性,可以使用setObject:forkey:来配置 |
threadPriority | double(0.0~1.0) | 线程优先级,最高为1.0(已废弃,用qualityOfService) |
qualityOfService | NSQualityOfService枚举 | 线程优先级 |
callStackReturnAddresses | NSArray (readOnly),类属性 |
返回在该线程中函数调用的地址的一个数组 |
callStackSymbols | NSArray (readOnly),类属性 |
使用代码的方式获取调用栈 |
name | NSString | 线程名,主线程名为main |
stackSize | NSUInteger | 线程使用的栈大小,默认512K,需要设置为4K的正整数倍,需要在start前设置,之后设置可以改变大小(表现为取值)但是不会影响栈区的真实页数 |
isMainThread(类属性,实例属性) | BOOL(readOnly) | 是否是主线程 |
mainThread(类属性) | NSThread(readOnly) | 获取主线程. |
executing | BOOL(readOnly) | 线程是否正在执行,执行前和执行完毕都会返回NO. |
finished | BOOL(readOnly) | 线程是否完成 |
cancelled | BOOL(readOnly) | 线程是否取消,只有调用了- (void)cancell 才会取消,如果线程执行完毕再调用- (void)cancell 也是会返回YES… |
// MAKR: 类方法
/// 创建一个线程并且执行.
+ (void)detachNewThreadWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
/// 同上
+ (void)detachNewThreadSelector:(SEL)selector toTarget:(id)target withObject:(nullable id)argument;
/// 当前进程里面是否有多个子线程(一般来说.点击暂停看调用堆栈都是多个线程的,所以说个人觉得这个属性并没有什么卵用)
+ (BOOL)isMultiThreaded;
/// 当前线程睡眠date
+ (void)sleepUntilDate:(NSDate *)date;
/// 当前线程睡眠ti(秒)
+ (void)sleepForTimeInterval:(NSTimeInterval)ti;
/// 退出当前线程
+ (void)exit;
/// 获取线程优先级
+ (double)threadPriority;
/// 设置线程优先级
+ (BOOL)setThreadPriority:(double)p;
// MARK: 实例方法
/// 下面这三个方法都需要调用`- (void)start`来开启线程
- (instancetype)init API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)) NS_DESIGNATED_INITIALIZER;
- (instancetype)initWithTarget:(id)target selector:(SEL)selector object:(nullable id)argument API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
- (instancetype)initWithBlock:(void (^)(void))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));
/// 取消线程
- (void)cancel API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
/// 开启线程
- (void)start API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
/// 当子类化NSThread的时候可以通过重写该方法来改变入口
- (void)main API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0)); // thread body method
/*
// @params:wait 一个布尔值,指定当前线程是否阻塞,直到在主线程上的接收器上执行指定的选择器之后。 指定YES以阻止此线程; 否则,指定NO以使此方法立即返回。
如果当前线程也是主线程,并且您传递YES,则立即执行消息,否则执行将排队等待下一次运行循环。
*/
/// 在主线程上执行方法...wait代表是等thread线程执行完毕才会执行下面的语句,否则异步执行.
@interface NSObject (NSThreadPerformAdditions)
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray *)array;
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(nullable id)arg waitUntilDone:(BOOL)wait;
// equivalent to the first method with kCFRunLoopCommonModes
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait modes:(nullable NSArray *)array API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
- (void)performSelector:(SEL)aSelector onThread:(NSThread *)thr withObject:(nullable id)arg waitUntilDone:(BOOL)wait API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
// equivalent to the first method with kCFRunLoopCommonModes
- (void)performSelectorInBackground:(SEL)aSelector withObject:(nullable id)arg API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
@end
/// 将要变成多线程的通知
FOUNDATION_EXPORT NSNotificationName const NSWillBecomeMultiThreadedNotification;
/// 已经变成单线程的通知
FOUNDATION_EXPORT NSNotificationName const NSDidBecomeSingleThreadedNotification;
/// 线程将要退出的通知
FOUNDATION_EXPORT NSNotificationName const NSThreadWillExitNotification;
typedef NS_ENUM(NSInteger, NSQualityOfService) {
/// 与用户交互有关的.高优先级,需要立即响应.
NSQualityOfServiceUserInteractive = 0x21,
/// 由用户发起的需要立即得到结果的任务,优先级比NSQualityOfServiceUserInteractive低
NSQualityOfServiceUserInitiated = 0x19,
/// 不需要马上返回结果的任务,优先级比NSQualityOfServiceUserInitiated低
NSQualityOfServiceUtility = 0x11,
/// 后台任务,可能是在后台备份用户数据什么的,优先级比NSQualityOfServiceUtility低
NSQualityOfServiceBackground = 0x09,
/// 默认优先级.比NSQualityOfServiceUserInitiated低比NSQualityOfServiceUtility高.
NSQualityOfServiceDefault = -1
} API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
当你启动应用的时候,需要XX秒才进入主屏
可千万别说这需求木有,我之前公司的老大就这么要求过.说是进入首页的速度太快了.得等个几秒钟再进去.(目的是让用户多看看启动图…这…)
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
```
/// 线程休眠2秒(因为这里是主线程,所以就做到了延迟2秒进入主屏的需求...)
[NSThread sleepForTimeInterval:2];
```
return YES;
}
也不是一定是准时的2秒,毕竟随着三方库的加入可能越来越大了.解决方案可以是1.把时间改短.2.异步加载三方库…
异步网络请求,主线程刷新UI
这个可能是最多的一种应用情况了.
- (void)viewDidLoad {
dispatch_async...抱歉,走错片场了.
NSThread *thread = [[NSThread alloc] initWithTarget:self selector:(requestNetWork:) object:params];
[thread start];
}
/// params为请求参数
- (void)requestNetWork:(id)params {
/// 假装request已经处理完毕了
[self.session dataTaskWithRequest:request completionHandler:^ (NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) completionHandler {
if (!error) {
//请求成功.去主线程处理UI
[self performSelectorOnMainThread:@selector(refreshUI:) withObject:arg waitUntilDone:NO];
}
}];
}
- (void)refreshUI:(id)arg {
/// 主线程刷新UI
}