zoukankan      html  css  js  c++  java
  • IOS随机随学

    1.Objective-C是一种面向对象的语言。

    2.Objective-C类声明和实现包括两个部分:接口部分和实现部分。

    3.Objective-C中方法不是在“.”运算符,而是采用“[]”运算符。有时候方法调用也称为:消息发送。

    4.Objective-C中的协议类似于Java中的接口与C++的纯虚类,只有接口部分定义没有实现部分,即只有h文件没有m文件。

    5.Objective-C数据类型可以分为:基本数据类型、对象类型和id类型。

    (I)基本数据类型有:int、float、double和char类型

    (II)对象类型就是类或协议所声明的指针类型,例如:

    NSAutoreleasePool* pool,其中NSAutoreleasePool是一个类,NSAutoreleasePool*是它指针类型。

    (III)id类型可以表示任何类型,一般只是表示对象类型,不表示基本数据类型。

    6. %i 表示十进制的整数,%o表示8进制整数,%#x表示十六进制整数。

    7.%f表示浮点数,%e表示科学计数法,%g表示浮点数。

    8.Objective—C中声明常量使用关键字const:

    9.Objective-C中变量可以分为成员变量、局部变量和局部变量。

    10.Objective-C的类声明和实现包括两个部分:接口部分和实现部分。

    @interface Song:NSObject{

    }

    @end

    @implementation Song

    @end

    11.声明property的语法为:@property(参数)类型 名字;

    这里的“擦数”主要分为3大类:

    (I)读写属性(readwrite/readonly);

    (II)内存管理(assign/retain/copy),

    (III)原子性atomicity(nonatomic),是关系线程线程安全的,atomicity是原子性的线程安全的,但是会影响性能。如果确定不考虑线程安全问题可以使用nonatomic

    12.@public、@private和@protected作用域限定只能修饰的实例成员变量,不能修饰类变量,更不能修饰方法。

    13.子类不能继承父类中作用域限定符为@private的成员变量。子类可以重写父类的方法,及命名与父类同名的成员变量。

    14.id是泛类型(generic data type),可以用来存放各种类型对象,使用id也就是使用“动态类型”。

    15.分类(Category)允许向一个类文件中添加新的方法声明,它不需要使用子类机制,并且在类实现的文件中的同一个名字下定义这些方法。其语法示例实现:

    #import "ClassName.h"

    @interface ClassName(CategoryName)

    //方法声明

    @end

    分类本质上是通过Objective-C的动态绑定而实现的,通过分类使用能够达到比继承更好的效果。

    16.协议(Protocol)与Java的Interface(接口)或者C++的纯虚类形同,就是用来声明接口的。协议只是定义了方法的列表,协议不负责实现方法,目的是让别的类来实现。

    协议只有接口部分,没有实现部分,所以没有m文件,关键字@protocol,协议可以继承别的协议,协议中不能定义成员变量。

    协议的实现是在类声明的父类之后,加上<>,与类的当个继承不同,协议可以实现多个,表示要实现这个协议,如果有多个协议要实现“,”号分隔:<P1,P2>

    17.Objective-C为每个对象提供一个内部计数器,这个计数器跟踪对象的引用次数。所有类都继承自NSObject的对象retain和release方法。

    19.内存释放池(Autorelease pool)提供了一个对象容器,每次对象发送autorelease消息时,对象的引用计数并不真正变化,而是向内存释放池中添加一条记录,记下对象的这种要求,直到当内存释放池发送drain或release消息时,当池被销毁前通知池中的所有对象,全部发送release消息真正将引用计数减少,

    20.在OC中,-号表示是实例方法,得有对象来调用的,+号表示类方法,可以用类名直接调用。

    21.类的定义使用@interface关键字,而实现用@implementation关键字。

    22.Objective-C的内存管理基于引用计数。如果要使用一个对象,并希望确保在使用期间对象不被释放,需要保证在使用过程中引用计算>0,在使用过后,把引用计数-1。当引用计数==0时,就会调用销毁方法了、

    (I)+1操作

    alloc     创建对象时调用alloc,为对象分配内存,对象引用计数加一。

    copy     拷贝一个对象,返回新对象,引用计数加一。

    retain    引用计数加一,获得对象的所有权

    (II)-1操作

    release  引用计数减一,释放所有权。如果引用计数减到零,对象会被释放。

    autorelease  在未来某个时机释放。

    23.内存管理,我们需要遵循一些基本原则:

    (1)保证只带有alloc,copy,retain的函数才会让引用计数+1。

    (II)在对象的dealloc函数中释放对象,完全依赖引用计数来完成对象的释放。

    (III)永远不要直接调用dealloc来释放对象,完全依赖引用计数器来完成对象的释放。

    (IV)有很多类方法可以直接出创建autorelease对象

    (V)在把一个参数传递出去的时候,因为要交由别人来释放,一般都设置成autorelease对象。

    24.进行:程序实体,独立单位,线程容器,老板。

    线程:不拥有资源,指令集,打工仔。

    25.GCD函数前缀:dispatch_

    获取主队列:dispatch_get_main_queue

    获取全局队列:dispatch_get_global_queue

    自定义队列:dispatch_queue_create

    26.图片展示:

      let img=UIImage(named:"IMG_0022");
      let imgView=UIImageView(image:img);
      self.view.addSubview(imgView);
    View Code

    27.打开网络风火轮

      UIApplication.sharedApplication().networkActivityIndicatorVisible=true;
    View Code

    28. 读取iOS应用的配置信息

            let mainBundle=NSBundle.mainBundle();
            let identifier=mainBundle.bundleIdentifier;
            let info=mainBundle.infoDictionary;
            let bundleId=mainBundle.objectForInfoDictionaryKey("CFBundleName");
            let version=mainBundle.objectForInfoDictionaryKey("CFBundleShortVersionString");
            print("[identifier]:(identifier)
    ")
            print("[bundleId]:(bundleId)
    ");
            print("[version]:(version)
    ");
            print("[info]:(info)
    ");
    View Code

    29.画两个矩形

            let rect1=CGRectMake(30, 50, 200, 200);
            let view1=UIView(frame:rect1);
            view1.backgroundColor=UIColor.brownColor();
            
            let rect2=CGRectMake(50, 80, 200, 200);
            let view2=UIView(frame:rect2);
            view2.backgroundColor=UIColor.greenColor();
    
            self.view.addSubview(view1);
            self.view.addSubview(view2);
    View Code

    30. 按钮

          override func viewDidLoad() {
            super.viewDidLoad()
            // Do any additional setup after loading the view, typically from a nib.
            let rect1=CGRectMake(30, 50, 200, 200);
            let view1=UIView(frame:rect1);
            view1.backgroundColor=UIColor.blueColor();
            
            self.view.addSubview(view1);
            
            let btAdd=UIButton(frame:CGRectMake(30, 350, 80, 30));
            btAdd.backgroundColor=UIColor.grayColor();
            btAdd.setTitle("Add",forState:UIControlState.Normal);
            btAdd.addTarget(self, action: "addView:", forControlEvents: UIControlEvents.TouchUpInside);
            
            self.view.addSubview(btAdd);
            
            
            let btBack=UIButton(frame:CGRectMake(120, 350, 80, 30));
            btBack.backgroundColor=UIColor.greenColor();
            btBack.setTitle("Switch",forState:UIControlState.Normal);
            btBack.addTarget(self, action: "bringViewBack:", forControlEvents: UIControlEvents.TouchUpInside);
            
            self.view.addSubview(btBack);
            
            let btAdd1=UIButton(frame:CGRectMake(210, 350, 80, 30));
            btAdd1.backgroundColor=UIColor.yellowColor();
            btAdd1.setTitle("Remove",forState:UIControlState.Normal);
            btAdd1.addTarget(self, action: "removeView:", forControlEvents: UIControlEvents.TouchUpInside);
            
            self.view.addSubview(btAdd1);
            
            
            
            
        }
        func addView(sender:UIButton!)
        {
            let rect=CGRectMake(60, 90, 200, 200);
      
            let view3=UIView(frame:rect);
            view3.backgroundColor=UIColor.redColor();
            view3.tag=1;
            self.view.addSubview(view3);
        }
        func bringViewBack(sender:UIButton!)
        {
            let view=self.view.viewWithTag(1);
            self.view.sendSubviewToBack(view!);
        }
        func removeView(sender:UIButton!)
        {
            let view=self.view.viewWithTag(1);
            view?.removeFromSuperview();
        }
    View Code

    31.给图像视图添加边框效果、圆角效果、阴影效果

            let image=UIImage(named:"120");
            
            let imageView=UIImageView(image:image);
            
            imageView.frame=CGRectMake(24, 80, 272, 410);
           
            
            imageView.layer.shadowColor=UIColor.blackColor().CGColor;
            imageView.layer.shadowOffset=CGSizeMake(10.0, 10.0);
            imageView.layer.shadowOpacity=0.45;
            imageView.layer.shadowRadius=5.0;
            
            
            imageView.layer.cornerRadius=5.0;
            imageView.layer.masksToBounds=true;
            
            imageView.layer.borderWidth=10;
            imageView.layer.borderColor=UIColor.lightGrayColor().CGColor;
          
            self.view.addSubview(imageView);
    View Code

    32.UIView视图的渐变效果

            let rect=CGRectMake(60, 120, 200,200);
            let gradientView=UIView(frame:rect);
            let gradientLayer=CAGradientLayer();
            gradientLayer.frame=gradientView.frame
            let fromColor=UIColor.yellowColor().CGColor;
            let midColor=UIColor.redColor().CGColor;
            let toColor=UIColor.purpleColor().CGColor;
            
            gradientLayer.colors=[fromColor,midColor,toColor];
            view.layer.addSublayer(gradientLayer);
            self.view.addSubview(gradientView);
    View Code

    33.UIView视图的纹理填充

        
            let image=UIImage(named: "120");
            let patternColor=UIColor.init(patternImage:image!);
            self.view.backgroundColor=patternColor;
    View Code

    34.CGAffineTransform放射变换的使用 

            let rect=CGRectMake(30, 150, 200, 50);
            let view=UIView(frame:rect);
            view.backgroundColor=UIColor.brownColor();
            self.view.addSubview(view);
            
            var transform=view.transform;
            transform=CGAffineTransformRotate(transform, 3.14/4);
            view.transform=transform;
    View Code

    35.UITapGestureRecognizer手势之单击、长按、双击

            override func viewDidLoad() {
            super.viewDidLoad()
            let rect=CGRectMake(30, 80, 200, 256);
          
            let imageView=UIImageView(frame: rect);
            
            let image=UIImage(named: "120");
            imageView.image=image;
            
            imageView.userInteractionEnabled=true;
            self.view.addSubview(imageView);
            
            let guesture=UITapGestureRecognizer(target:self,action:"singleTap");
            
          
            
            let guesture1=UILongPressGestureRecognizer(target:self,action:"longPress:")
            
            
            let guesture2=UITapGestureRecognizer(target:self,action:"doubleTap");
            guesture2.numberOfTapsRequired=2;
            guesture2.numberOfTouchesRequired=1;
           
     
            imageView.addGestureRecognizer(guesture);
            
            imageView.addGestureRecognizer(guesture1);
            
            imageView.addGestureRecognizer(guesture2);
            
            
        }
        
        func singleTap()
        {
            let alertView=UIAlertController(title:"Infomation",message: "Single Tap",
                preferredStyle: UIAlertControllerStyle.Alert)
            let OKAction=UIAlertAction(title:"OK",style: .Default){(action)in}
            alertView.addAction(OKAction);
            self.presentViewController(alertView,animated:true,completion:nil);
        }
        
        
        func longPress(gesture:UILongPressGestureRecognizer)
        {
            if(gesture.state==UIGestureRecognizerState.Began)
            {
                let alertView=UIAlertController(title:"Information",message:"Long Press",
                    preferredStyle:UIAlertControllerStyle.Alert );
                let OKAction=UIAlertAction(title:"OK",style: .Default){(action)in}
                
                alertView.addAction(OKAction)
                self.presentViewController(alertView, animated: true, completion: nil);
            }
        }
        
        func doubleTap()
        {
            let  alertView=UIAlertController(title:"Information",message: "Double Tap",
                preferredStyle: UIAlertControllerStyle.Alert);
            let OKAction=UIAlertAction(title:"OK",style:.Default){(action)in}
            alertView.addAction(OKAction);
            self.presentViewController(alertView, animated: true, completion: nil);
        }
    View Code

    36打电话

    (1)使用UIApplication 的openUrl方法实现

    View Code

    37.多线程

    (1)ios多线程特殊的规则:必须在主线程更新UI

    (2)IOS有三种多线程编程的技术,分别是:

    (a)NSThread

    (b)NSOperation

    (c)GCD(Grand Central Dispatch)

    (d)这三种编程方式从上到下,抽象度层次是从低到高的,抽象度越高的使用越简单,也是Apple最推荐使用的。

    (3)多线程的好处:

    (a)多个线程可以提高应用程序的感知响应。

    (b)多个线程可以提高应用程序在多核系统上的实时性能。

    (4)GCD 

    (a)GCD的工作原理:把任务放到对应队列中,根据可用的处理资源,安排这些任务在任何可用的处理器核心上执行。

    (b)一个任务可以是一个函数或者是一个block。

    (c)GCD中队列称为dispatch queue,它可以保证先进来的任务先得到执行。

    (d)dispatch queue分类

    (I)main dispatch queue(系统提供的)

    (i)全局性的serial queue,所有和UI操作相关的任何都放到这个queue里面,在主线程中执行。

    (ii)宏dispatch_get_main_queue()

    (II)global dispatch queue(系统提供的)

    (i)可以随机地执行多个任务,但是执行完成的顺序是随机的。一般后台执行的任务放到这个queue里面。

    (ii)函数dispatch_get_global_queue(0,0);

    (III)自定义的dispatch queue

    (i)和main dispatch queue类似,同时只执行一个任务,区别在于自定义queue里面放的任何一般和UI操作无关。serial queue通常用于同步访问特定的资源或数据,比如多个线程对同一个文件的写入。

    (ii)dispatch_queue_create("SerialQueue",DISPATCH_QUEUE_SERIAL);

    (5)提交任务到dispatch queue

    (a)同步提交

    void dispatch_sync(dispatch_queue_t queue,dispatch_block_t block);

    (b)异步提交

    void dispatch_async(dispatch_queue_t queue,dispatch_block_t block);

    (6)GCD的应用场合

    (a)主要应用在本地的多线程处理上,比如解析从网络传输过来的数据。

    (b)对于网络方面的多线程控制,更多使用NSOperation,因为NSOperation的控制粒度更加精细。

    38.进程

    (1)每个进程之间是独立的,每个进程均运行在其专用且受保护的内存空间内。

    (2)1个进程要想执行任务,必须得有线程(每1个进程至少要有1条线程)

    (3)线程是进程的基本执行单元,一个进程(程序)的所有任务都在线程中执行

    (4)线程的串行

    (a)1个线程中任务的执行是串行的

    (b)如果要在1个线程中执行多个任务,那么只能一个一个地顺序执行这些任务。也就是说,在同一时间内,1个线程只能执行1个任务。

    (5)什么事多线程

    (a)1个进程中可以开启多条线程,每条线程可以并行(同时)执行不同的任务。

    (6)多线程的原理

    (a)同一时间,CPU只能处理1条线程,只有1条线程在工作(执行)

    (b)多线程并发(同时)执行,其实是CPU快速地在多条线程之间调度(切换)。

    (c)如果CPU调度线程的时间足够快,就造成了多线程并发执行的假象。

    (d)如果线程非常非常多,(i)CPU会在N多线程之间调度,CPU会累死,消耗大量的CPU资源。(ii)每条线程被调度执行的频次会降低(线程的执行效率降低)

    (7)多线程的优点:

    (a)能适当提高程序的执行效率

    (b)能适当提高资源利用率(CPU、内存利用率)

    (8)多线程的缺点

    (a)开启线程需要占用一定的内存空间(默认情况下,主线程占用1M,子线程占用512KB),如果开启大量的线程,会占用大量的内存空间,降低程序的性能。

    (b)线程越多,CPU在调度线程上的开销就越大。

    (c)程序设计更加复杂:比如线程之间的通信、多线程的数据共享

    (9)主线程

    (a)一个IOS程序运行后,默认会开启1条线程,称为“主线程”或“UI线程”

    (b)主线程的主要作用

    (i)显示、刷新UI界面

    (ii)处理UI事件(比如点击事件、滚动事件、拖拽事件等)

    (c)主线程的使用注意:别将比较耗时时的操作放在主线程中

    (d)耗时操作会卡住主线程,严重影响UI的流畅度,给用户一种“卡”的坏体验

    (e)解决方案:将耗时操作放在子线程(后台线程、非主线程)

    (10)IOS中多线程的实现方案

    (a)PThread:<C语言>

    (i)一套通用的多线程API

    (ii)适用于UnixLinuxWindows等系统

    (iii)跨平台、可移植

    (iv)使用难度大

    (v)简单案例

    void *run(void *data){
        NSThread *current=[NSThread currentThread];
        NSLog(@"Click----%@",current);
            for (int i=0; i<10000; i++) {
                //3.输出线程
                NSLog(@"%@",current);
            }
        return NULL;
    }
    - (IBAction)btnClick {
        //1。获得当前的线程
       NSThread *current=[NSThread  currentThread];
        NSLog(@"btnClick----%@",current);
        
        //2.执行一些耗时操作:创建一条子线程
        pthread_t threadId;
        pthread_create(&threadId, NULL, run, NULL);
    }
    View Code

    (b)NSThread:(OC)

    (i)使用更加面向对象

    (ii)简单易用,可直接操作线程对象

    (c)GCD:(C)

    (i)旨在替代NSThread等线程技术

    (ii)充分利用设备的多核

    (d)NSOperation:(oc)

    (i)基于GCD(底层是GCD)

    (ii)比GCD多了一些更简单使用的功能

    (iii)使用更加面向对象

    (11)NSThread线程

    (a)一个NSThread对象就代表一条线程

    (b)创建、启动线程

    NSThread*thread=[[NSThread alloc]initWithTarget:self selector:@selector(run) object:nil];

    [thread start];

    线程一启动,就会在线程thread中执行self的run方法

    (c)主线程相关用法

    +(NSThread*)mainThread;//获得主线程

    -(BOOL)isMainThread;//是否为主线程

    +(BOOL) isMainThread;//是否为主线程

    (d)获得当前线程

    NSThread *current=[NSThread currentThread];

    (e)线程的调度优先级

    +(double) threadPriority;

    +(BOOL)setThreadPriority:(double)p;

    -(double) threadPriority;

    -(BOOL)setThreadPriority:(double)p;

    调度优先级的取值范围是0.0~1.0,默认0.5,值越大,优先级越高

    (f)线程的名字

    -(void)setName:(NSString*)n;

    -(NSString*)name;

    (g)创建线程后自动启动线程

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

    (h)隐式创建并自动启动线程

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

    (12)控制线程状态

    (a)启动线程

    -(void)start;

    //进入就绪状态->运行状态。当线程任务执行完毕,自动进入死亡状态

    (b)阻塞(暂停)线程

    +(void) sleepUntilDate:(NSDate*) date;

    +(void)sleepForTimeInterval:(NSTimeInterval)ti;

    //进入阻塞状态

    (c)强制停止线程

    +(void)exit;

    //进入死亡状态

    //注意:一旦线程停止(死亡)了,就不能再次开启线程

    (d)示例

    -(void) test
    {
        
        NSLog(@"test- 开始-%@",[NSThread currentThread].name);
     //[NSThread sleepForTimeInterval:5];阻塞状态
        
    //    NSDate *date=[NSDate dateWithTimeIntervalSinceNow:5.0];
    //    [NSThread sleepUntilDate:date];
        
        for (int i=0; i<1000; i++) {
            
        
        NSLog(@"test- %d-%@",i,[NSThread currentThread].name);
            
            if(i==50){
                [NSThread exit];//线程退出,等同于return;
     
            }
        }
        
        NSLog(@"test- 结束--%@",[NSThread currentThread].name);
    }
    View Code

    (13)多线程的安全隐患

    (a)1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源。

    (b)比如多个线程访问同一个对象、同一个变量、同一个文件

    (c)当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题

    (14)安全隐患解决---互斥锁

    (a)互斥锁使用格式

    @synchronized(锁对象){//需要锁定的代码}

     //注意:锁定1份代码只能用1把锁,用多把锁是无效的

    (b)互斥锁的优缺点

    (I)优点:能有效防止因多线程抢夺资源造成的数据安全问题

    (II)缺点:需要消耗大量的CPU资源

    (c)互斥锁的使用前提:多条线程抢夺同一块资源

    (d)线程同步的意思是:多条线程按顺序地执行任务。

    (e)互斥锁,就是使用了线程同步技术

    (15)原子和非原子属性

    (a)OC在定义属性时有nonatomic和atomic两种选择

    (b)atomic:原子属性,为setter方法加锁(默认就是atomic)

    (c)nonatomic:非原子属性,不会为setter方法加锁

    (d)atomic加锁原理

    @property (assign,atomic) int age;

    -(void) setAge:(int)age

    {

      @synchronized(self){

        _age=age;  

      }

    }

    (e)原子和非原子属性的选择

    nonatomic和atomic对比

    atomic:线程安全,需要消耗大量的资源

    nonatomic:非线程安全,适合内存小的移动设备

    (16)线程间通信

    (a)什么叫做线程间通信:在1个进程中,线程往往不是孤立存在的,多个线程之间需要经常进行通信。

    (b)进程间通信的体现

    (I)1个线程传递数据给另1个线程

    (II)在1个线程中执行完特定任务后,转到另1个线程继续执行任务。

    (c)线程间通信常用方法

    -(void)performSelectorOnMainThread:(SEL)aSelector WithObject:(id)arg waitUntilDone:(BOOL)wait;

    -(void)performSelector:(SEL)aSelector onThread:(NSThread*)thr withObject:(id)arg waitUntilDone:(BOOL)wait;

    (d)示例

    -(void)touchesBegan:(NSSet*)touches withEvent:( UIEvent *)event
    {
        [self performSelectorInBackground:@selector(download)withObject:nil];
    }
    -(void) download
    {
           //1.下载图片
        NSLog(@"--------begin");
        NSURL *url=[NSURL URLWithString:@"http://pic32.nipic.com/20130829/12906030_124355855000_2.png"];
        NSLog(@"--------begin");
        NSData *data=[NSData dataWithContentsOfURL:url];//耗时
        NSLog(@"--------end");
        UIImage *image=[UIImage imageWithData:data];
        
        //回到主线程显示图片
    //    [self performSelectorOnMainThread:@selector(settingImage:) withObject:image waitUntilDone:NO];
        
    //    [self.imageView performSelectorOnMainThread:@selector(setImage:)withObject:image waitUntilDone:NO];
    [self.imageView performSelector:@selector(setImage:)onThread:[NSThread mainThread]withObject:image waitUntilDone:NO];
        
    }
    -(void)settingImage:(UIImage *)image
    {
    
        //2.显示图片```
        self.imageView.image=image;
    }
    View Code

    (17)GCD

    (a)GCD的优势

    (I)GCD是苹果公司为多核的并行运算提出的解决方案

    (II)GCD会自动利用更多的CPU内核(比如双核、四核)

    (III)GCD会自动管理线程的生命周期(创建线程、调度任务、销毁线程)

    (IV)程序员只需要告诉GCD想要执行什么任务,不需要编写任何线程管理代码

    (b)GCD中有2个核心概念

    (I)任务:执行什么操作

    (II)队列:用来存放任务

    (c)GCD的使用就2个步骤

    (I)定制任务

    (II)确定想要做的事情

    (d)将任务添加到队列中

    (I)GCD会自动将队列中的任务取出,放到对应的线程中执行

    (II)任务的取出遵循队列的FIFO原则:先进先出,后进后出

    (f)GCD中有2个用来执行任务的函数

    (I)用同步的方式执行任务

    dispatch_sync(dispatch_queue_t queue,dispatch_block_t block);

    queue:队列

    block:任务

    (II)用异步的方式执行任务

    dispatch_async(dispatch_queue_t queue,dispatch_block_t block);

    (III)同步和异步的区别

    (i)同步:在当前线程中执行

    (ii)异步:在另一条线程中执行

    (18)队列的类型

    (a)GCD的队列可以分为2大类型

    (I)并发队列(Concurrent Dispatch Queue)

    (i)可以让多个任务并发(同时)执行(自动开启多个线程同时执行任务)

    (ii)并发功能只能在异步(dispatch_async)函数下才有效

    (b)串型队列(serial Dispatch Queue)

    (i) 让任务一个接着一个地执行(一个任务执行完毕后,在执行下一个任务)

    (b)比较:同步、异步、并发、串行

    同步和异步决定了要不要开启新的线程

    (I)同步:在当前线程总执行任务,不具备开启新线程的能力。

    (II) 异步:在新的线程中执行任务,具备开启新线程的能力。

    并发和串行决定了任务的执行方式

    (I)并发:多个任务并发(同时)执行。

    (II)串行:一个任务执行完毕后,再执行下一个任务。

    (19)并发队列

    (a)GCD默认已经提供了全局的并发队列,供整个应用使用,不需要手动创建。

    (b)使用dispatch_get_global_queue函数获得全局的并发队列

    dispatch_queue_t dispatch_get_global_queue(

      dispatch_queue_priority_t priority,//队列的优先级

      unsigned long flags);//此参数暂时无用,即0即可

    dispatch_queue_t queue=dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT,0);//获得全局并发队列

    (c)全局并发队列的优先级

    (I)#define DISPATCH_QUEUE_PRIORITY_HIGH 2//高

    (II)#define DISPATCH_QUEUE_PRIORITY_DEFAULT 0  //默认  中

    (III)#define DISPATCH_QUEUE_PRIORITY_LOW(-2) //低

    (IV)#define DISPATCH_QUEUE_PRIORITY_BACKGROUND INT16_MIN  //后台

    (20)串行队列

    (a)GCD中获取串行有2钟途径

    (I)使用dispatch_queue_create函数创建串行队列

    dispatch_queue_t  queue=dispatch_queue_create(const char *label,//队列名称

    dispatch_queue_attr_t attr);//队列属性,一般用NULL即可

    dispatch_queue_queue=dispatch_queue_create("cn.itcast.queue",NULL);//创建

    dispatch_release(queue);//非ARC需要释放手动创建的队列

    (b)使用主队列(跟主线程相关的队列)

    (I)主队列是GCD自带的一种特殊的串行队列

    (II)放在主队列中的任务,都会放在主线中执行

    (III)使用dispatch_get_main_queue()获得主队列

    (IV)使用dispatch_get_main_queue()获得主队列

    dispatch_queue_t queue=dispatch_get_main_queue();

    (21)各种队列的执行效果

                全局并发队列                                手动创建串行队列                              主队列

    同步(sync)      没有开启新线程/串行执行任务         没有开启新线程/串行执行任务       没有开启新线程/串行执行任务(卡死)

    异步(async)    有开启新线程/并发执行任务              有开启新线程/串行执行任务           没有开启新线程/串行执行任务

    (22)延迟执行

    (a)ios常见的延迟执行有2种方式

    (I)调用NSObject的方式

    [self performSelector:@selector(run) withObject:nil afterDelay:2.0];//2秒后再调用self的run方法

    (2)使用GCD函数

    dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(2.0*NSEC_PER_SEC)),dispatch_get_main_queue(),^{

      //2秒后异步执行这里的代码....

    });

    (23)一次性代码

    (I)使用dispatch_once函数能保证某段代码在程序运行过程中只被执行1次

    (2)static dispatch_once_t onceToken;

    dispatch_once(&onceToken,^{

      //只执行1次的代码(这里默认是线程安全的)

    });

    (24)队列组

    (a)有这么1种需求:

    (I)首先:分别异步执行2个耗时的操作

    (II)其次:等2个异步操作都执行完毕后,再回到主线程执行操作

    如果想要快速高效地实现上述需求,可以考虑用队列组

    39.单例模式

    (1)单利模式在ARCMRC环境下的写法有所不同,可以用宏判断是否为ARC环境

    #if __has_feature(objc_arc)

    40.NSOperation

    (1)NSOperationde的作用:配合使用NSOperation和NSOperationQueue也能实现多线程编程

    (2)NSOperation和NSOperationQueue实现多线程的具体步骤

    (I)先将需要执行的操作封装到一个NSOperation封装到一个NSOperation对象中

    (II)然后将NSOperation对象添加到NSOperationQueue中

    (III)系统会自动将NSOperationQueue中的NSOperation取出来

    (III)将取出的NSOperation中封装放到的操作放到一个新线程中执行。

    (3)NSOperation的子类

    (a)NSOperation是一个抽象类,并不具备封装操作的能力,必须使用它的子类

    (b)使用NSOperation子类的方式有3种

    (I)NSInvocationOperation

    (II)NSBlockOperation

    (III)自定义子类继承NSOperation,实现内部相应的方法。

    (4)NSInvocationOperation

    (I)创建NSInvocationOperation对象

    -(id)initWithTarget:(id)target selector:(SEL)sel object:(id)arg;

    (II)调用start方法开始执行操作

    -(void)start;

    一旦执行操作,就会调用target的sel方法

    (IV)注意:默认情况下,调用了start方法后并不会开一条新线程去执行操作,而是在当前线程同步执行操作。

    (V)只有将NSOperation放到一个NSOperationQueue中,才会异步执行操作。

    (5)NSBlockOperation

    (a)创建NSBlockOperation对象

    +(id)blockOperationWithBlock:(void(^)(void))block;

    (b)通过addExecutionBlock:方法添加更多的操作

    -(void)addExecutionBlock:(void(^)(void))block;

    注意:只要NSBlockOperation封装的操作数>1,就会异步执行操作

    (6)NSOperationQueue

    (a)NSOperationQueue的作用:

    (I)NSOperation可以调用start方法来执行任务,但默认是同步执行的

    (II)如果将NSOperation添加到NSOperationQueue(操作队列)中,系统会自动异步执行NSOperation中的操作

    (b)添加操作到NSOperationQueue中

    -(void) addOperation:(NSOperation*)op;

    -(void)addOperationWithBlock:(void(^)(void))block;

    (7)并发数

    (a)什么是并发数:同时执行的任务数。比如,同时开3个线程执行3各任务,并发数就是3。例: queue.maxConcurrentOperationCount=3;

    (8)队列的取消、暂停、恢复

    (a)取消队列的所有操作

    -(void)cancelAllOperations;

    提示:也可以调用NSOperation的-(void)cancel方法取消单个操作

    (b)暂停和恢复队列

    -(void)setSuspended:(BOOL)b;//YES代表暂停队列,NO代表恢复队列

    (9)操作优先级

    (a)设置NSOperation在Queue中的优先级,可以改变操作的优先级

    -(NSOperationQueuePriority)queuePriority;

    -(void) setQueuePriority:(NSOperationQueuePriority)p;

    (b)优先级的取值

    (I)NSOperationQueuePriorityVeryLow=-8L;

    (II)NSOperationQueuePriorityLow=-4L;

    (III)NSOperationQueuePriorityNormal=0;

    (IV)NSOperationQueuePriorityHigh=4;

    (V)NSOperationQueuePriorityVeryHigh=8;

    (10)操作依赖

    (a)NSOperation之间可以设置依赖来保证执行顺序

    (b)比如一定要操作执行完后,才能执行操作B可以这么写

    [operationB addDependency:operationA];//操作B依赖于操作A

    (c)可以在不同queue的NSOperation之间创建依赖关系

    (d)注意:不能相互依赖

    41.SDWebImage框架:用于处理图片下载:https://github.com/rs/SDWebImage

  • 相关阅读:
    1130
    Oracle 数据库常用操作语句大全
    Oracle用sys登陆报:ORA-28009:connection as sys should be as sysdba
    导出数据报ORA-39002: 操作无效 ORA-39070: 无法打开日志文件。 ORA-39087: 目录名 DUMP_DIR 无效
    SGI STL源码stl_bvector.h分析
    SGI STL源码stl_vector.h分析
    CGI 萃取技术 __type_traits
    迭代器iterator和traits编程技法
    智能指针分析及auto_ptr源码
    C++深拷贝和浅拷贝细节理解
  • 原文地址:https://www.cnblogs.com/heisaijuzhen/p/5417183.html
Copyright © 2011-2022 走看看