delegate底层 ios - CSDN
  • iOS 简单代理(delegate)实现

    千次阅读 2020-04-04 22:14:53
    昨天做了一个demo,用到了简单代理。 delegateios编程的一种设计模式。我们可以用这个设计模式来让单继承的objective-c类表现出它父类之外类的特征。昨天这个代理实现如下:
    展开全文
  • iOS开发中,协议和类别是用的非常多的功能。协议(delegate):声明一系列的方法,可由任何类实施,即使遵守该协议的类没有共同的超类。协议方法定义了独立于任何特定类的行为。简单的说,协议就是定义了一个接口...

    在iOS开发中,协议和类别是用的非常多的功能。

    协议(delegate):声明一系列的方法,可由任何类实施,即使遵守该协议的类没有共同的超类。协议方法定义了独立于任何特定类的行为。简单的说,协议就是定义了一个接口,其他类负责来实现这些接口。如果你的类实现了一个协议的方法时,则说该类遵循此协议。

    协议的申明:

     恩是这样的  每天晚上8:30都有一节【免费的】iOS高级直播课程,讲iOS安全攻防,AR技术,ARKit技术,移动架构,支付宝,底层,高级进阶等,逆向,音视频处理技术,新技术开发,OpenGL ES,人工智能,进阶,区块链讲解,都是纯干货分享,需要进阶的伙伴可以加我QQ群:319819749群内都是1-6年开发,欢迎加入一起深入一起交流
    [objc] view plain copy
    1. @protocol MyProtocol  
    2. @required  
    3. -(void) method1;  
    4. @optional  
    5. -(void)method2;  
    6. @end  
    一个协议定义了一系列的方法,这些方法在对象之间建立合约,而无需使那些对象成为任何特定类的实例,此合约使那些对象能够相互通信。一个对象想要告诉另一个对象它遇到的事件或者它可能想要寻求有关事件的建议。

    比如tableview继承了UITableViewDelegate协议,这样通过调用指定的tableview的特定方法就能传递那些tableview的通知了,在头文件(.h)文件中,该类采用一个协议,就要将该协议的名称放在尖括号(<……>)中,并且放在它继承的类的名称后面,比如:

    [objc] view plain copy
    1. @interface MyViewController : UIViewController<UITableViewDelegate,UITableViewDataSource>  

    对于许多委托协议来说,采用一个协议仅仅是实现该协议定义的方法,有些协议要求明确的声明支持该协议,而协议可以指定必须实现方法和可选方法。


    类别(category):类别是Objective-C的一项功能,可扩展类的接口,而无需对类进行子类化。category 可以为已经存在的类增加方法,而不需要增加一个子类。而且,我们可以在不知道某个类内部实现的情况下,为该类增加方法。如果我们想增加某个框架(framework)中的类的方法,category 就非常有效。比如,如果想在NSString 上增加一个方法,那么就可以这样做:

    [objc] view plain copy
    1. @interface NSString (extension)  
    2. -(void) method;  
    3. @end  

    categoty没有父类,类后面的括号里写类别的名字。

    [objc] view plain copy
    1. @implementation NSString(extension)    
    2.   
    3. -(void) method{  
    4.      ……  
    5. }  
    6.   
    7. @end  

    这个时候就可以在NSString类的对象上调用这个方法了。

    注意:类别并不能为类声明新的实例变量,他只包含方法。然而在类作用域内所有实例变量,都能被这些类别访问。他们包括为类声明的所有的实例变量,甚至那些被@private 修饰的变量。可以为一个类添加多个类别,但每个类别名必须不同,而且每个类别都必须声明并实现一套不同的方法。


    要记住,我们通过 category 来修改一个类的时候,他对应应用程序里这个类所有对象都起作用。跟子类不一样,category 不能增加成员变量。我们还可以用 category里重写类原先存在的方法(但是并不推荐这么做)。


    可以将类别作为一种手段,对头文件中的相关方法声明进行分组,甚至还可以将不同的类别声明放在不同的头文件中,框架在其所有的头文件中使用这些技巧达到清晰明确的效果,还可以使用称为类别扩展的匿名类别,在实现文件(.m)文件中声明专有的属性和专有的方法,类扩展看起来类似于类别,只是圆括号之间没有文本。

    展开全文
  • 当你开始写iOS程式不久,应该开始面对到很多的delegate, 不管是用别人的library或是自己写library,可能都逃不了delegate。 为了怕有些人不知道什么是delegate,在这边简单的介绍一下, delegate中文叫做委托...

    转:http://popcornylu.blogspot.com/2011/07/delegate.html

    当你开始写iOS程式不久,应该开始面对到很多的delegate,
    不管是用别人的library或是自己写library,可能都逃不了delegate。
    为了怕有些人不知道什么是delegate,在这边简单的介绍一下,
    delegate中文叫做委托,通常会用在class内部把一些事件处理"委托"给别人去完成。
    举个例子,XML Parser可能他知道怎么parse xml,但是parse到的东西要怎么处理xml parser可能不知道。
    所以NSXMLParser就提供了一个NSXMLParserDelegate给client去实作,
    当parse到某个element的时候,就callback delegate所定义的message,
    让他client自己去决定怎么去处理这个element。
    好吧,我承认我解释的很模糊,不过我这篇本来就不是要你搞懂什么是delegate,
    而是针对使用或是设计delegate的时候,可能会要注意的事情。

    在我们的class中设计delegate的时候,我们通常会有几个注意事项。
    假设我的class叫做MyClass,那我们可能会有定义一个MyClassDelegate这个protocol当作我的delegate protocol。
    而MyClass中我们可能是这样写。
    @protocol MyClassDelegate <NSObject>
    - (void) myClassOnSomeEvent:(MyClass*)myClass;
    @end

    @interface MyClass
    {
        id<MyClassDelegate> _delegate;
    }
    @property (nonatomic, assign) delegate;
    @end
    上面的code我们注意到delegate此property是定义为@property (assign)。
    为什么我们不用retain而要用assign呢?
    原因就是在于iOS的reference counting的环境中,我们必须解决circular count的问题。
    让我们来写写我们平常都怎么用delegate的,下面的code我想大家应该不陌生
    - (void)someAction
    {
       myClass = [MyClass new];
       myClass.delegate = self;
       ....
    }
    这边很快的就出现circular reference了
    假设上面的code是写在一个myViewController的物件当中,
    之后一旦myViewController的reference count变成1的时候,
    myViewController跟myClass这两个兄弟两只剩下互相retain,那就变成了孤岛,也​​就因此造成了memory leak!!!


    也因为这样,iOS官方文件才会要建议我们所以的delegate都要用assign property。
    也就是所谓"weak reference"的property,他的特色就是虽然会持有对方的reference,但是不会增加retain count。
    如此下来,当myViewController的retain count变成0,则会dealloc。
    同时在dealloc中,也一并把myClass release,则myClass也跟着被release。
    - (void)dealloc
    {
       [myClass release];
       [super dealloc];
    }



    事情就结束了吗? 还没有唷...
    这边还有一个大家常常忘记的重点,那就是上面的dealloc这样写会有潜在危险。
    应该要改成这样
    - (void)dealloc
    {
       myClass.delegate = nil;
       [myClass release];
       [super dealloc];
    }
    你可能会很纳闷,myClass不是马上就会被release了吗? 干嘛要先把他的delegate设成nil?
    那是因为我们假设myClass会马上会被dealloc,但是现实状况这个是不一定的,
    有可能里面内部有建个NSURLConnection,或是正在做某件事情而让其他物件也retain myClass。
    如果myClass没有马上dealloc,那他的myClass.delegate不就正指向一个不合法的位置了吗? (此种pointer称作dangling pointer)



    解决方法是在MyViewController的dealloc中,在release myClass之前,
    要先把原本指向自己的delegate改设成nil,这样才可以避免crash发生。
    在我之前写的project,很大一部份的crash都是这样造成的,因为这个问题通常不是每次都发生,
    但是发生的时候确很难在重新复制,所以不可不慎啊。



    但是很兴奋的是到了iOS5中的Automatic Reference Counting 这个问题可以有所改善。
    在ARC中提出了一个新的weak reference的概念来取代原本的assign,
    weak reference指到的物件若是已经因retain count归零而dealloc了,则此weak reference也自动设成nil。
    而原本​​旧的这种assign的作法,在ARC中叫做__unsafe_unretained,这只是为了相容iOS4以下的版本。

    回顾重点:
    如果你是写library给别人用的,记得把你的delegate设成assign property,这样才不会造成circular reference
    当你是要始用别人的library,记得在你自己dealloc的时候,把delegate设成nil,以避免crash的事情发生。
    展开全文
  • 最近的项目遇到了网络请求,需要在请求完成后回调delegate的方法。然而回调时经常遇到这种情况:delegate已经被释放,这时调用其方法则会引起crash。 objc的runtime中有两种判断类型的方式比较靠谱,他们可以直接...
    
    

    最近的项目遇到了网络请求,需要在请求完成后回调delegate的方法。然而回调时经常遇到这种情况:delegate已经被释放,这时调用其方法则会引起crash

    objc的runtime中有两种判断类型的方式比较靠谱,他们可以直接取得任意一个objc_object(和id是完全一样的数据类型)的类或者类名。其函数如下:

    //Returns the class name of a given object.
    const char *object_getClassName(id obj);
     
    //Returns the class of an object.
    Class object_getClass(id object);

    第一个函数可以返回任意一个id的类名,第二个函数可以返回任意一个id的Class。这两个函数各有优劣。使用第一个函数判断类型是否改变的优点是在 iphone开发环境下默认公开,可以随便调用,缺点是要使用几字节的内存空间用于存放字符串,而且做字符串比较要稍微多花费一些CPU时间。第二个函数 优点是可以将获取的Class指针做为int型保存起来,只需要4字节,且比较起来节约CPU时间,坏处是我们要手动声明一下此函数才可以在自己的代码里 使用,否则会出现一个warning,提示“Implicit declaration of function ‘object_getClass’ is invalid in C99”,不过手动声明一下只要加一行代码就可以,也不麻烦。

    下面是一个实例:

    // WebService.h
    
    #import <Foundation/Foundation.h>
    
    @protocol ServiceDelegate;
    
    @interface WebService : NSObject {
        id <ServiceDelegate> _myDelegate;
        Class _originalClass;
    }
    
    @property (nonatomic, assign) id myDelegate;
    
    - (void)postDataWithURL:(NSString *)myURL postData:(NSDictionary *)dataDic setDelegate:(id)theDelegate;
    - (void)serviceFun:(NSDictionary *)paramDic;
    
    @end
    
    @protocol ServiceDelegate <NSObject>
    - (void)serviceCallBack:(id)resultObject serviceFlag:(NSInteger)flag;
    @end
    // WebService.m
    
    #import "WebService.h"
    
    Class object_getClass(id object);
    
    @implementation WebService
    
    @synthesize myDelegate = _myDelegate;
    
    - (void)postDataWithURL:(NSString *)myURL postData:(NSDictionary *)dataDic setDelegate:(id)theDelegate
    {
        self.myDelegate = theDelegate;
        _originalClass = object_getClass(theDelegate);
        [NSThread detachNewThreadSelector:@selector(serviceFun:) toTarget:self withObject:dataDic];
    }
    
    - (void)serviceFun:(NSDictionary *)paramDic
    {
        Class currentClass = object_getClass(self.myDelegate);
        if (currentClass == _originalClass) {
            // 如果delegate没有被释放
        }
    }
    
    
    
    
    第二种方法

    http://pingguohe.net/2011/09/01/howtojudgewhetheradelegateisreleased/#comment-983

    困惑了相当长时间的一个问题了,实际上在Xcode4中会出现 

    if ((int)delegate->isa == classIsa) { 

    这行报错,member reference base type 'id<HTTPRequestDelegate>' is not a structure or union

    因为ide不认为它是NSObject对象,只要对它转为NSObject对象即可。

    //************************************************************************************

    Cocoa中回调delegate的方法时判断delegate是否已经被释放

    这个需要是因为最近在做网络请求的底层,需要在请求完成时回调某delegate的某方法。
    然而回调时经常遇到这种情况:delegate已经被release了。如果delegate已经被dealloc掉,则无法调用其方法,否则引起程序crash。

    此篇文章中博客作者也有相同的问题:http://longtimenoc.com/archives/objective-c-delegate的那些事儿

    首先,我们此时无法用if (nil = delegate)判断delegate是否已经被dealloc掉,因为被dealloc之后,delegate对象也不是空的,大部分情况下是一个objc_object*类型的C指针。

    其次,我们又会想到在本对象中先对delegate retain一次,这样回调时不会崩溃了。但是这样会出现一个retain cycle,本对象和delegate都永远不会被释放了。

    再次,我想到是否可以用isKindOfClass判断是否被dealloc。然而此时也不能用[delegate isKindOfClass]判断是否已经被dealloc,因为isKindOfClass是NSObject协议中的方法,此时delegate如果不是NSObject,对其发送isKindOfClass消息会导致crash。

    此时很小部分情况下,delegate会是NSObject,可能是NSDictioary,也可能是原本的类。而大部分情况下,delegate已经不是NSObject。所以此时任何形式的[delegate method]都会导致crash,因为任何的[delegate method]的前提都是:delegate是一个NSObject。

    无奈之下我又想到,使用delegate->isa判断delegate是不是NSObject。这里介绍一下,objective-c中所有对象都是结构体,每个结构体中都有一个名为isa的指针指向其类。而类也是一种结构体,类的isa指向其父类。处于最底层的结构体是无isa的,NSObject的isa指向的也是NSObject。isa具体的值是运行时确定的。
    一开始的思路是用delegate->isa->isa->isa->…一直指下去,如果isa与NSObject的isa相同,则说明delegate是一个NSObject。但是这样是行不通的,因为如果delegate不是NSObject,只是objc_object*,一直指下去却指不到NSObject的话,总会指到最底层的结构体,而此结构体无isa,如果访问结构体内没有的东西,程序又会crash了。

    说了这么多,结论就是这个问题很是蛋疼。再做不出来我就要把释放本对象的责任交给用户了。

    等等,如果在本对象初始化后,delegate传进来时保存delegate的isa,此时delegate一定未被dealloc(为什么?因为是单线程的),在回调时判断delegate此时的isa和当时保存的isa是否一样,就可以解决了。
    代码如下:
    协议声明:

    @protocol HTTPRequestDelegate <NSObject>
     
    @optional
     
    - (void) requestDidLoadResponse:(NSString *)responseDictionary;
    - (void) requestDidFailedLoadResourceURLWithError:(NSError *)error;
     
    @end

    类声明:

    @interface MyClass : NSObject <FooDelegate,BarDelegate>
    {
        ...
        int classIsa;
        id <HTTPRequestDelegate> delegate;
    }
     
    @property (nonatomic,assign) id <HTTPRequestDelegate> delegate;
     
    @end

    类实现:

    @implementation MyClass
     
    @synthesize delegate;
     
    - (id)initWithDelegate:(id)requestDelegate
    {
        self = [super init];
        if (self) {
            //TODO:Send request,etc.
            self.delegate = requestDelegate;
        }
        return self;
    }
     
    - (void)setDelegate:(id<HTTPRequestDelegate>)iDelegate
    {
        delegate = iDelegate;
        NSString *delegateDescription = [[iDelegate class] description];
        classIsa = (int)objc_getClass([delegateDescription UTF8String]);
    }
     
    - (void)callback
    {
        if ((int)delegate->isa == classIsa) {
            if ([delegate respondsToSelector:@selector(requestDidLoadResponse:)]) {
                    NSString *responseString = @"foobar";
                    [delegate requestDidLoadResponse:responseString];
            }
        }
    }

    然而由于多线程的原因(发出请求和回调发生是在两个线程上的),会有极少数的情况(测试中发生概率在万分之一以内,和CPU有关)在if ((int)delegate->isa == classIsa)判断时,delegate当前的isa会和本对象初始化时isa相等,也就是说delegate未被dealloc,而调用回调时,delegate已被dealloc,导致程序crash。避免这种小概率事件的方法是,在delegate中发送请求前[self retain]一下,然后在回调到达时[self release]一下,这样除了避免崩溃以外,还会确保请求已经发送完毕,不会被发送一半。

    以上。

    –OpenThread


    展开全文
  • iOS底层原理之架构设计

    千次阅读 2019-07-18 14:58:56
    iOS底层原理之架构设计
  • iOS代理机制实现原理和应用

    千次阅读 2017-11-30 14:51:28
    代理(Delegate)是iOS开发中的一种重要的消息传递方式,是iOS开发中普遍使用的通用设计模式,iOS集成开发环境Xcode中,提供大量的控件,例如UITableView,UIScrollViewDelegate ,UISearchView等都是用代理机制实现...
  • 虽然距离WWDC2011和iOS 5已经快一年时间,但是很多开发者并没有利用新方法来提高自己的水平,这点在ARC的使用上非常明显(特别是国内,基本很少见到同行转向ARC)。我曾经询问过一些同行为什么不转向使用ARC,很多人的...
  • 一、分类 1.分类的作用? 声明私有方法,分解体积大的类文件,把framework的私有方法公开 2.... 运行时决议,可以为系统类添加分类 。... 说得详细些,在运行时时期,将 Category 中的实例方法列表、协议列表、...
  • 从开始从事OC工作到现在大概1年多了,从当初接触oc的"协议"的不明白,到现在代码中随处可见的委托,协议,其中感悟颇多。 ...首先,大家应该都明白的是委托是协议的一种,顾名思义,就是委托他人帮自己去做什么...
  • IOS中不同组件的通信

    千次阅读 2014-08-14 15:48:37
    iOS中两种方式实现
  • iOS底层网络协议

    2019-08-08 16:22:28
    HTTP的通信分为两大步骤: 发送请求 和 接收... 请求: 一个请求包含以下内容: ...请求头:包含了对客户端的环境描述,客户端能接受的数据类型,客户端请求的主机地址等信息 Host: 192.168.1.105:8080 // 客户端想访问...
  • AFNetworking基本是iOS开发中的网络第三方库标配,本文基于AFNetworking3.1.0版本。咱们主要从使用的角度来介绍AFNetworking的发起Get请求的过程,偏重于解读过程,解读当你使用AFNetworking发起一个Get请求的时候,...
  • block和delegateiOS开发者经常用到的技术,也常常出现在各种面试题里,你经常听到他们之间的对比。 我的态度是每个成熟的技术并没有明显的优劣,不应该用谁好谁劣来评判他们,而应该看谁更适合应用场景,在合适的...
  • int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); //NSStringFromClass好处 //1.不会写错 ... ...
  • iOS防止崩溃机制以及底层原理

    千次阅读 2018-11-23 18:00:52
    iOS防止崩溃机制以及底层原理开发的目的是什么? 吴杰 2018-11-19 在你影响中是否有这样子的晚上,当刚刚躺下准备美美的睡一觉的时候,突然接到您的上司的电话,一接起来发现是你上司!“**啊,刚刚上线的X.X.X...
  • delegateiOS中一种常见的设计模式,是一种消息传递的的方式,常见的消息传递方式还有以下几种: 通知:在iOS中由通知中心进行消息接收和消息广播,是一种一对多的消息传递方式。 代理:是一种通用的设计模式,...
  • 多层view时delegate为nil的问题解决

    千次阅读 2016-10-18 11:22:16
    问题描述:我在一个tab的DashboardController页面上增加了一个包含两个页面大小的UIScrollView实现左右滑动分页效果,然后在UIScrollView的左右两页都分辨包涵了一个自定义的继承UIViewController的子页面...
  • iOS 底层Runloop的详解

    2019-01-17 14:38:25
    有人做了两年多的iOS开发,对iOS和Objective-C深层次的了解还十分有限,大多还停留在会用API的级别,这是件挺可悲的事情。想学好一门语言还是需要深层次的了解它,这样才能在使用的时候得心应手,出现各种怪异的问题...
  • 还有很多其它类似的情况会导致app受到干扰,在app受到干扰时,会产生一些系统事件,这时UIApplication会通知它的delegate对象,让delegate代理来处理这些系统事件。delegate可处理的事件包括: (1)应用程序的生命...
  • 100家知名企业今年来iOS面试题合集: 你要的这里都有; 企业要的这里也有; 从基础开始到进阶、深入底层 整理出188个面试题,全是干货 这些全部是题目跟类目,每个题目都会有相对的答案,由于字数太多所以我...
1 2 3 4 5 ... 20
收藏数 7,363
精华内容 2,945
热门标签
关键字:

delegate底层 ios