IOS学习笔记2-NSThread,链式编程

1,NSThread

1.1 创建线程的方法

#pragma mark - 创建线程的方法

//创建线程的方法 3
- (void)test3
{
    //隐式的创建线程,通过这种方法实际上也会创建新的线程
    [self performSelectorInBackground:@selector(run) withObject:nil];
}

//创建线程的方法 2
- (void)test2
{
    //通过类方法创建一个新线程
    [NSThread detachNewThreadSelector:@selector(run) toTarget:self withObject:nil];
}

//创建线程的方法 1
- (void)test1
{
    //1,实例化一个线程对象
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
    //2,让线程开始工作,
    [thread start];
}
- (void)run
{
    // 1,睡到指定的时间点
    //    [NSThread sleepUntilDate:[NSDate dateWithTimeIntervalSinceNow:5.0]];
    for (int i = 0; i < 10; i++) {
        //2,[NSThread sleepForTimeInterval:0.3f] 这个类方法,让当前进程睡一会
        [NSThread sleepForTimeInterval:0.3f];
        //3,[NSThread currentThread] 通过这个类方法,打印出当前的进程
        NSLog(@"%@ %d", [NSThread currentThread], i);
        //4,[NSThread mainThread] 获取主线程
        NSThread *main = [NSThread mainThread];
    }
    
    //5.在指定线程上执行操作
    [self performSelector:@selector(run1) onThread:[NSThread mainThread] withObject:nil waitUntilDone:YES];
    
    //6.在主线程上执行操作
    [self performSelectorOnMainThread:@selector(run1) withObject:nil waitUntilDone:YES];
    
    //7.在当前线程执行操作
    [self performSelector:@selector(run1) withObject:nil];
    
}
 

1.2 线程的属性

#pragma mark - 线程的属性
- (void)test4
{
    /*
     1,thread.name = @"my thread";    //设置线程的名字,打印出来,方便程序出错的时候查找是哪里出错了
     2,thread.threadPriority = 0.5;  //线程的优先级,是一个浮点数,0.0 ~ 1.0.默认值是0.5,开发时候一般不要去修改优先级,否则可能会导致程序出错,另外,需要被调用很多很多次,才能体现出来优先级的作用。
     */
    
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(run) object:nil];
    thread.name = @"my thread";
    thread.threadPriority = 0.5;
    //3. 放到可调度线程池,等待被调度。 这时候是就绪状态
    [thread start];
    
    //4,  一旦强制终止,就在不能重新启动
    //     一旦强制终止,后面的代码都不会执行
    [NSThread exit];
}

1.3 为什么只能在主线程中更新UI

/*
 线程安全的概念: 就是在多个线程同时执行的时候,能够保证资源信息的准确性.
 
 "UI线程" -- 主线程
 ** UIKit 中绝对部分的类,都不是”线程安全“的
 怎么解决这个线程不安全的问题?
 
 苹果约定,所有程序的更新UI都在主线程进行, 也就不会出现多个线程同时改变一个资源。
 
 // 在主线程更新UI,有什么好处?
 1. 只在主线程更新UI,就不会出现多个线程同时改变 同一个UI控件
 2. 主线程的优先级最高。也就意味UI的更新优先级高。 会让用户感觉很流畅
 */

1.4 互斥锁 Demo

#pragma mark - 卖票
/**
 1. 开发比较复杂的多线程程序时,可以先在主线程把功能实现
 2. 实现功能以后,再把耗时的功能再放到子线程
 3. 再增加一个线程,建议开发的时候,线程一个一个增加
 */
/**
 加锁,互斥锁
 加锁,锁定的代码尽量少。
 加锁范围内的代码, 同一时间只允许一个线程执行
 互斥锁的参数:任何继承 NSObject *对象都可以。
 要保证这个锁,所有的线程都能访问到, 而且是所有线程访问的是同一个锁对象
 */
- (void)saleTicktes
{
    while (YES) {
        
        // 模拟一下延时,卖一张休息1秒
        [NSThread sleepForTimeInterval:1.0];

        // 不会写单词,怎么办?
//        [[NSUserDefaults standardUserDefaults] synchronize];

        // 为什么没有提示
        // 因为苹果不推荐我们使用加锁。因为加锁,性能太差。
        @synchronized(self){ // 开发的时候,一般就使用self就OK
            //1. 判断是否还有票,
            if (self.tickets > 0) {
                // 2. 如果有票,就卖一张
                self.tickets--;
                
                NSLog(@"剩余的票数--%d--%@", self.tickets, [NSThread currentThread]);

            }else{
                // 3. 如果没有就返回
                NSLog(@"没票了");
                break;
            }
        }
    }
}

1.5 原子属性和非原子属性(nonatomic,atomic

@property(nonatomic, assign) int tickets;

@property(atomic, strong)NSObject *obj;
// nonatomic 非原子属性
// atomic 原子属性--默认属性
// 原子属性就是针对多线程设计的。 原子属性实现 单(线程)写 多(线程)读
// 因为写的安全级别要求更高。 读的要求低一些,可以多读几次来保证数据的正确性
// 如果同时重写了setter和getter方法,"_成员变量" 就不会提供
// 可以使用 @synthesize 合成指令,告诉编译器属性的成员变量的名称
@synthesize obj = _obj;
- (NSObject *)obj
{
    return _obj;
}

// atomic情况下, 只要重写了set方法,getter也得重写
- (void)setObj:(NSObject *)obj
{
    // 原子属性内部使用的 自旋锁
    // 自旋锁和互斥锁
    // 共同点: 都可以锁定一段代码。 同一时间, 只有线程能够执行这段锁定的代码
    // 区别:互斥锁,在锁定的时候,其他线程会睡眠,等待条件满足,再唤醒
    // 自旋锁,在锁定的时候, 其他的线程会做死循环,一直等待这条件满足,一旦条件满足,立马去执行,少了一个唤醒过程
    
    @synchronized(self){ // 模拟锁。 真实情况下,使用的不是互斥锁。 而是自旋锁
        _obj = obj;
    }
}

2,OC中的链式编程

实现过程见Demo。思路,要实现链式编程可以让函数返回值是对象本身即可,使用函数返回值就可以直接使用'.'操作符来调用其他函数,但是!这样写,调用的方法不能有参数,因为OC中有参数的方法必须使用中括号来调用, 为了实现传递参数,我们可以使用block代码块,让函数的返回值是一个block代码块,对象.[方法名],得到的结果是一个block代码块,然后我们再取执行block,执行block代码块的方法就是对象.[方法名](), 括号中是block代码块的参数,这样我们就实现了链式编程,,详见代码。


Demo

</pre><pre name="code" class="objc">typedef  WHAttributeText *(^WHBlockFloat)(CGFloat);
typedef  WHAttributeText *(^WHBlockColor)(UIColor *);
typedef  WHAttributeText *(^WHBlockNumber)(NSNumber *);<p><pre name="code" class="objc">- (WHBlockFloat)paraLineSpacing;
- (WHBlockFloat)paraSpacing;
- (WHAttributeText *(^)(NSTextAlignment))paraAlignment;
- (WHBlockFloat)paraFirstLineHeadIndent;
- (WHBlockFloat)paraMinimumLineHeight;
- (WHBlockFloat)paraLineSpacing
{
    return ^(CGFloat lineSpacing){
        _whParagrahStyle.lineSpacing = lineSpacing;
        return self;
    };
}
- (WHBlockFloat)paraSpacing
{
    return ^(CGFloat paragraphSpacing){
        _whParagrahStyle.paragraphSpacing = paragraphSpacing;
        return self;
    };
}
- (WHAttributeText *(^)(NSTextAlignment))paraAlignment
{
    return ^(NSTextAlignment alignment){
        _whParagrahStyle.alignment = alignment;
        return self;
    };
}
使用:
对象. paraHeadIndent(8).paraLineSpacing(10);

3,IOS开发中的结构体

3.1 结构体和字符串之间的相互转换

如下所示,其它结构体也有类似的函数

结构体和字符串之间相互转换:
NSString *NSStringFromCGPoint(CGPoint point);
NSString *NSStringFromCGRect(CGRect rect);
CGPoint CGPointFromString(NSString *string);
CGRect CGRectFromString(NSString *string);

3.2,CGRect放大或缩小,中心为原点

//对一个CGRect进行修改 以这个的中心来修改 正数表示更小(缩小) 负数表示更大(放大)  
CGRect CGRectInset(CGRect rect, CGFloat dx, CGFloat dy);  

3.3 比较两个矩形是否相交

bool CGRectIntersectsRect(CGRect rect1, CGRect rect2);

3.4 初始为0的  结构体

const CGPoint CGPointZero;  
const CGRect CGRectZero;  
const CGSize CGSizeZero;

3.5 偏移

CGRect类型的矩形,相对于x,y,的偏移

CGRect CGRectOffset(CGRect rect, CGFloat dx, CGFloat dy)

3.6 获取屏幕尺寸

CGrect screenBounds = [ [UIScreen mainScreen]bounds];//返回的是带有状态栏的Rect    
CGRect viewBounds = [ [UIScreen mainScreen]applicationFrame];//不包含状态栏的Rect    
//screenBounds 与 viewBounds 均是相对于设备屏幕来说的    
//所以 screenBounds.origin.x== 0.0 ;   screenBounds.oringin.y = 0.0;   screenBounds.size.width == 320;  screenBounds.size.height == 480(或者其他分辨率有所差异)    
//所以 screenBounds.origin.x== 0.0 ;   screenBounds.oringin.y = 20.0;(因为状态栏的高度是20像素)   screenBounds.size.width == 320;  screenBounds.size.height == 480 







 





  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值