delegate_delegates - CSDN
  • Delegate委托的使用

    2018-07-17 19:11:13
    Delegate委托的使用 委托的说明 委托(delegate)是Cocoa的一个术语,表示将一个对象的部分功能转交给另一个对象。 比如对象A希望对象B知道将要发生或已经发生某件事情,对象A可以把对象B的引用存为一个实例变量...

    Delegate委托的使用

    委托的说明

    委托(delegate)是Cocoa的一个术语,表示将一个对象的部分功能转交给另一个对象。

    比如对象A希望对象B知道将要发生或已经发生某件事情,对象A可以把对象B的引用存为一个实例变量。这个对象B称为委托。当事件发生时,它检查委托对象是否实现了与该事件相适应的方法。如果已经实现,则调用该方法。

    由于松耦合的原因,一个对象能成为多个对象的委托。某些情况下,相较于通过继承让子类实现相关的处理方法,可以有效减少代码复杂度。所以iOS中也大量的使用了委托。

    委托的实例

    //定义个协议
    protocol loadingDeleagte {
        func didLoading(text: String)
    }
    class HomeViewController: UIViewController {
    
        @IBOutlet weak var textFlied: UITextField!
    
        //2.声明一个委托代理
        var delegate: loadingDeleagte?
    
        override func viewDidLoad() {
            super.viewDidLoad()
    
        }
    
        @IBAction func backBtnClick(_ sender: AnyObject) {
    
            print("点击了")
            //3实例一个 ViewController类
            let loading = ViewController()
            //指定委托代理是 loading 的实例
            delegate = loading
            //调用委托实现的协议方法
            delegate?.didLoading(text: textFlied.text!)
        }
    
        override func touchesBegan(_ touches: Set<UITouch>, with event: UIEvent?) {
    
            UIApplication.shared.keyWindow?.endEditing(true)
        }
        override func didReceiveMemoryWarning() {
            super.didReceiveMemoryWarning()
            // Dispose of any resources that can be recreated.
        }
    
    
    
    }
    import UIKit
    
    class ViewController: UIViewController {
    
    
        @IBOutlet weak var textLable: UILabel!
        @IBOutlet weak var NextBtn: UIButton!
        override func viewDidLoad() {
            super.viewDidLoad()
    
    
    
        }
    
    }
    
    //4实现LoadingDelegate协议
    extension ViewController : loadingDeleagte {
    
        func didLoading(text: String) {
    
            print(text)
    
            //值已经传过来了
    
        }
    }

    实际开发中容易遇到的问题

    • 实际开发中容易遇到的问题
      1.新建的另一个页面的的controller对象,不是要跳转的页面的controller。
      2.delegate没有设置好,导致获取不到对应controller的控件
    • 关键解决方法:
    //获取到对应页面的controller
    let secondView = self.storyboard?.instantiateViewController(withIdentifier: "second") as! addTagsViewController
            //设置secondView中的代理为当前ViewController自身
            secondView.delegate=self
            self.navigationController!.pushViewController(secondView,animated:true)

    secondView中传值回去

    if((delegate)) != nil{
                delegate?.didLoading(text: "传值回去")
                self.navigationController?.popViewController(animated: true)

    参考资料

    http://www.hangge.com/blog/cache/detail_810.html

    https://www.cnblogs.com/ningmengcao-ios/p/5952872.html

    展开全文
  • 做.NET开发很久,最近重新温习《C#高级编程》一书。发现很多曾经似懂非懂的问题,其实也是能够慢慢钻研慢慢理解的。 所以,打算开写《C#高级编程系列》博文。...Delegate委托,在.NET中应用的非常广泛。

    做.NET开发很久,最近重新温习《C#高级编程》一书。发现很多曾经似懂非懂的问题,其实也是能够慢慢钻研慢慢理解的。

    所以,打算开写《C#高级编程系列》博文。其中会借鉴《C#高级编程》一书的概念,也会参照其他高手的博文,希望大家谅解。有不对的地方,欢迎指正。

    (另:本博文不会讲解定义,语法方面的基础知识。)


    下面如题,我们来讲委托。

    Delegate委托,在.NET中应用的非常广泛。会涉及到Lambda表达式,事件,匿名方法等(请关注后续博文)。

    那么何为委托?

    通俗的来讲,委托除了必须指定delegate关键字和没有方法实体之外,和指定方法没有更多区别。你可以当它是一个占位符,比如你在写代码的时候并不知道你将要处理的是什么。你只需要知道你将要引入的参数类型和输出类型是什么并定义它即可。这就是书本上所传达的方法签名必须相同的意思。


    下面我们来定义一个基本的委托:

        public class Test
        {
            //定义委托
            public delegate void D_Math(int a, int b);
            public void Add(int a, int b)
            {
                Console.WriteLine("Add方法结果:{0}", a + b);
            }
            public void Cut(int a, int b)
            {
                Console.WriteLine("Cut方法结果:{0}", a - b);
            }
        }
        [TestClass]
        public class UnitTest1
        {
            [TestMethod]
            public void TestMethod1()
            {
                Test t = new Test();
                Test.D_Math D = new Test.D_Math(t.Add);//委托实例化,也可Test.D_Math D =t.Add;
                D += t.Cut;//委托可以以队列方式执行多个方法,以+=运算符或者-=来增加或者取消队列中的方法
                D(5, 6);
    
            }
        }
    执行结果:


    以上看出来委托实用的地方了吗?即委托可以执行任何引入参数类型相同且返回类型相同的方法,甚至可以执行签名相同的方法队列。


    那么我们的方法签名(即引入参数和输出参数)真的必须与委托完全一致吗?答:不是的,我们不能忽略协变与逆变。

    我们这里简单介绍一下协变与逆变的知识。

    “协变”是指能够使用与原始指定的派生类型相比,派生程度更大的类型。

    “逆变”则是指能够使用派生程度更小的类型。

    那么,我们的委托也是接受协变与逆变的。

    意思是,如果定义一个delegate,那么不仅仅签名完全相同的方法可以赋值给delegate变量

    如果一个方法的参数表符合delegate声明,但返回的类型是delegate声明返回类型)的派生类,那也可以将这个方法赋值给这个delegate变量。

    如果一个方法的返回类型符合delegate的声明,但参数是(delegate声明参数类型)的祖先类,那也可以将这个方法赋值给这个delegate变量。

    如果一个方法的参数和返回类型都符合上面两行的假设,那也可以将这个方法赋值给这个delegate变量


    以下以两个简单示例解释协变与逆变:


    协变:

          public class A { }
        public class B:A { }//B继承自A
        public class Test
        {
            //定义委托
            public delegate A D_Math();
            public B Add()
            {
                return new B();
     
            }
            public A Add2() 
            {
                return new A();
            }
        }
        [TestClass]
        public class UnitTest1
        {
            [TestMethod]
            public void TestMethod1()
            {
                Test.D_Math d = new Test.D_Math(new Test().Add);//委托返回A,而Add方法返回B,此为协变。
            }
        }

    逆变:

     public class A { }
        public class B:A { }//B继承自A
        public class Test
        {
            //定义委托
            public delegate void D_Math(B b);
            public void Add(B b)
            {
     
            }
            public void Add2(A a) 
            {
     
            }
        }
        [TestClass]
        public class UnitTest1
        {
            [TestMethod]
            public void TestMethod1()
            {
                Test.D_Math d = new Test.D_Math(new Test().Add2);//委托引入参数B,而Add方法参数为A类型,此为协逆变。
            }
        }

    以上是本篇对于委托的讲解,欢迎大家补充与修正。


    更多WEB开发技术请加群:Asp.Net高级群 号码:261882616  博主以及同事和你共同探讨感兴趣的话题。

    展开全文
  • c# delegate知识

    2018-08-30 11:18:29
    一、引用方法 委托是寻址方法的.NET版本。...如:delegate int ReturnIntHandler(int a,int b);//int是返回类型,a和b是引用类型,这是委托执行的方法必须满足如下格式:int method(int param1,int p...

    一、引用方法

    委托是寻址方法的.NET版本。委托是类型安全的类,它定义了返回类型和参数的类型。委托是对方法的引用,也可以对多个方法进行引用,委托可以理解为指向方法地址的指针。

    如:delegate int ReturnIntHandler(int a,int b);//int是返回类型,a和b是引用类型,这是委托执行的方法必须满足如下格式:int method(int param1,int param2);

     

    二、委托

    当要把方法传递给其它方法时,需要使用委托。委托是一种特殊类型的对象,其特殊之处在于,我们以前定义的所有对象都包含数据,而委托包含的只是一个或多个方法的地址。

     

    1、声明委托

    委托使用关键字 delegate 进行定义。

    定义委托基本上就是定义一个新类,所以可以在定义类的任何相同地方定义委托。可以在委托定义上应用常见的访问修饰符:public、private、protected等。其访问作用域也雷同于类。

     

    2、使用委托

    为了减少输入量,只需要委托实例,就可以只传递地址的名称。这称为委托推断。

    delegate int CalculateMethodInvoker(int x, int y);
        class Program
        {
            static void Main(string[] args)
            {
                //创建委托对象
                CalculateMethodInvoker calculateMethodInvoker = CalculateHelper.Sum;
                //等同于CalculateMethodInvoker calculateMethodInvoker = new CalculateMethodInvoker(CalculateHelper.Sum);//委托的实例化,指向Sum方法,其实委托也是可以定义,实例化调用的,不只是lambda表达式的调用方式
                int x = 100, y = 200;
                Console.WriteLine("x,y相加:{0}", Calculate(calculateMethodInvoker, x, y));
                calculateMethodInvoker = CalculateHelper.Multiply;
                Console.WriteLine("x,y相乘:{0}", Calculate(calculateMethodInvoker, x, y));
                Console.ReadKey();
            }
            public static int Calculate(CalculateMethodInvoker calculateMethodInvoker, int x, int y)
            {
                //return calculateMethodInvoker(x, y);
                //return calculateMethodInvoker.Invoke(x, y);//是不是当前线程都可以
                IAsyncResult result = calculateMethodInvoker.BeginInvoke(x, y, null, calculateMethodInvoker);//异步,这里只是做展示,EndInvoke类似于async中的await,这里不能实现异步效果
                return calculateMethodInvoker.EndInvoke(result);
            }
    
        }
        public class CalculateHelper
        {
            public static int Sum(int x, int y)
            {
                return x + y;
            }
            public static int Multiply(int x, int y)
            {
                return x * y;
            }
        }

     

    3、Action<T>和Func<T>委托

    除了为每个参数和返回类型定义一个新的委托类型外,还可以使用Action<T>和Func<T>委托。

    泛型Action<T>委托表示引用一个void返回类型的方法,没有泛型参数的Action类可调用没有参数的方法,如Action 等价于 delegate void mydelegate;  Action<int,int>等价于delegate void mydelegate(int param1,int param2);

    泛型Func<T>委托表示引用一个有返回值的方法,泛型的最后一个参数时Func的返回值类型,如Func<int,int,bool>,等价于delegate bool mydelegate(int param1,int param2);

     

    4、多播委托

    委托也可以包含多个方法。这种委托成为多播委托。如果调用多播委托,就可以按顺序连续调用多个方法。为此,委托的签名就必须返回void;否则,就只能得到委托调用的最后一个方法的结果。多播委托识别运算符“-”、“+”、“-=”、“+=”以从委托中增加或删除方法调用。

    如:

    class Program
        {
            static void Main(string[] args)
            {
                Action<int, int> calFunc = CalculateHelper.Sum;
                calFunc += CalculateHelper.Multiply;//多播加
                int x = 100, y = 200;
                Calculate(calFunc, x, y);
                calFunc =calFunc- CalculateHelper.Multiply;//多播减
                Calculate(calFunc, x, y);
                Console.ReadKey();
            }
            public static void Calculate(Action<int, int> calculateMethodInvoker, int x, int y)
            {
                Console.WriteLine("运行结果:");
                //calculateMethodInvoker(x, y);
                foreach (Action<int, int> item in calculateMethodInvoker.GetInvocationList())//遍历,这里需要转为为当前类型委托
                {
                    try
                    {
                        item(x, y);//执行委托指向方法
                    }
                    catch (Exception ex)
                    {
                        Console.WriteLine(ex.Message);
                    }
                }
            }
        }

    如果通过委托调用的其中一个方法抛出异常,整个迭代就会停止。解决的方法是,使用Delegate类中定义的GetInvocationList()方法获取Delegate对象数组,再使用循环遍历执行,在过程中捕获异常,来继续下一次迭代。

     

    5、匿名方法

    匿名方法是用作委托的参数的一段代码。

    如:

    Action<int, int> calFunc = delegate (int i, int j)
    {
        Console.WriteLine("x,y相加:{0}", i + j);
    };

    在匿名方法中不可使用跳转语句(break、goto或continue),在匿名方法内部不能访问不安全代码,不能访问在匿名方法外部使用的ref和out参数。

     

    三、lambda表达式

    C#3.0后,可以使用lambda把实现代码赋予委托,只要有委托参数类型的地方,就可以使用lambda表达式。

    如:

    Action<int, int> calFunc = (i, j) =>
    {
        Console.WriteLine("x,y相加:{0}", i + j);
    };

     

    1、参数

    lambda表达式有几种定义参数的方式。如果只有一个参数,只写出参数名就足够了。如果除一个参数以外,需要圆括号把参数名括起来。

    例子:

    Action<int> one = i =>
    {
        //method body
    };
    Action<int, int> two = (i, j) =>
    {
        //method body
    };

     

    2、多行代码

    如果lambda表示只有一条语句,在方法块内就不需要花括号和return语句,因为编译器会隐式添加return。

    如:

    Func<int> lambdaOne = () => 0;

    如果实现代码超过一行,就需要使用return语句显式返回。

    如:

    {
        int i = 0;
        i++;
        ++i;
        return i;
    };

     

    3、闭包

    通过lambda表达式可以访问lambda表达式块外部的变量。这称为闭包。

    如:

    int param = 10;
    Action<int> lambdaSecond = (i) =>
    {
        Console.WriteLine(i + param);
    };
    lambdaSecond(3);
    Console.ReadKey();

     

    四、事件

    事件基于委托,为委托提供了一种发布/订阅机制。

    如:

    class Program
        {
            static void Main(string[] args)
            {
                AlarmClock alarmClock = new AlarmClock();
                Student zsStudent = new Student("张三");
                alarmClock.ItsGetUpClockEvent += zsStudent.ItsGetUpClock;
                alarmClock.ItsGetUpClock();
                Student lsStudent = new Student("李四");
                //WeakEventManager<AlarmClock, EventArgs>.AddHandler(alarmClock, "ItsGetUpClockEvent", lsStudent.ItsGetUpClock);
                ////弱事件,System.Windows,WPF中经常用到
                //alarmClock.ItsGetUpClock();
                Console.ReadKey();
            }
    
        }
        //事件发布类
        public class AlarmClock
        {
            public event EventHandler<EventArgs> ItsGetUpClockEvent;
            public void ItsGetUpClock()
            {
                Console.WriteLine("时间到,起床了!");
                ItsGetUpClockEvent?.Invoke(this, new EventArgs());//判断是否订阅事件
            }
        }
        //事件侦听类
        public class Student
        {
            public string Name { get; set; }
            public Student(string name)
            {
                this.Name = name;
            }
            public void ItsGetUpClock(object sender, EventArgs e)
            {
                Console.WriteLine("{0}关掉闹钟,起床了。", Name);
            }
        }

    事件最常用的地方是Winform和Wpf窗体中,而Invoke的经典使用场景如下(非当前线程更改窗体文本):

     private void ShowExecLog(string log)
            {
                if (this.richTextBox1.InvokeRequired)//判断是否是当前线程
                {
                    this.richTextBox1.Invoke(new ShowLogHandler(ShowLog), log);
                }
                else
                {
                    this.richTextBox1.Text += log;
                }
            }
    
            public void ShowLog(string log)
            {
                this.richTextBox1.Text += log;
            }
    
    
            public delegate void ShowLogHandler(string log);

     

    展开全文
  • 关于delegate(代理)总结

    2017-04-16 13:53:10
    stackoverflow 上讲解:...   delegate是将需要处理交给自己的代理。 在自己的对应的类中.h文件中申明对应的delegate @class CSPopMenu; @protocol CSPopMenuDelegate @optional -(void)PopMenuDimi
    stackoverflow  上讲解:http://stackoverflow.com/a/12660523/4563358
    

     

    delegate是将需要处理交给自己的代理。

    在自己的对应的类中.h文件中申明对应的delegate

    @class CSPopMenu;
    @protocol CSPopMenuDelegate <NSObject>
    @optional
    -(void)PopMenuDimiss:(CSPopMenu *)popMenu;
    @end

    插入一个可选择的方法,定义一个协议。

    @property(nonatomic,weak)id <CSPopMenuDelegate> delegate;

    delegate属性设定。

    在类的.m文件中

    -(void)dismiss
    {
        if ([self.delegate respondsToSelector:@selector(PopMenuDimiss:)]) {
            [self.delegate PopMenuDimiss:self];
        }
        [self removeFromSuperview];
      }

    调用对应的delegate的方法。

     

    要对这个类进行相关的操作,那么首先你要成为这个类的一个代理

     CSPopMenu *menuView= [[CSPopMenu alloc]initWithContentView:menuTableView];
        menuView.popMenuPosition = CSPopMenuBackgroundleft;
        [menuView showRect:CGRectMake(100, 100, 100, 100)];
        menuView.delegate = self;

    把当前的类成为对应的类的一个代理。

    然后就可以调用代理方法

    //设置对应的转动的方向
    -(void)PopMenuDimiss:(CSPopMenu *)popMenu
    {
        CSMainBtn *mainBtn = (CSMainBtn *)self.navigationItem.titleView;
        [mainBtn setImage:[UIImage imageNamed:@"navigationbar_arrow_down"] forState:UIControlStateNormal];
        
    }

    得到的效果如图

    使得首先右边的箭头改变方向。

     

    展开全文
  • 在c#里面,有的时候一些代码的实现必须用到委托,比如:线程...这时候,就需要使用到委托(delegate)。委托其实是这样的,为某些实现写一个函数,并将其赋值给委托(相当于函数指针),在使用 的时候直接通过委托名来
  • 谈C#中的Delegate

    2017-11-08 16:57:40
     Delegate是Dotnet1.0的时候已经存在的特性了,但由于在实际工作中一直没有机会使用Delegate这个特性,所以一直没有对它作整理。这两天,我再度翻阅了一些关于Delegate的资料,并开始正式整理这个C#中著名的特性。...
  • 相信使用过C#语言的人们,对于委托应该是记忆深刻,委托具有很多不错的特性,但最令人感到兴奋的是它可以简化很多复杂的开发同时具有低耦合与对象闭包的特性。  委托在C/C++中可以解决最直观的就有问题,一个是...
  • C#中delegate详解

    2018-06-28 11:31:21
    首先,delegate是什么?有过C语言或者C++基础的同学可以把他当做C语言和C#的函数的指针。委托(Delegate) 是存有对某个方法的引用的一种引用类型变量。引用可在运行时被改变。委托是一个类型安全的对象,它指向...
  • c#的delegate和event

    2019-02-21 15:25:43
    delegate是什么 委托(delegate) 是存有对某个方法的引用的一种引用类型变量,引用可在运行时被改变。如果不好理解,可以把委托理解成为函数指针,但它们是有区别的。 delegate和C++中的函数指针: 函数指针...
  • block与delegate的区别

    2018-08-30 18:25:10
    1.从源头上理解和区别block和delegate delegate运行成本低,block的运行成本高。 block出栈需要将使用的数据从栈内存拷贝到堆内存,当然对象的话就是加计数,使用完或者block置nil后才消除。delegate只是保存了一...
  • jQuery的 delegate问题

    2019-07-03 00:12:51
    习惯了bind,用惯了live,就不习惯delegate了呀有木有... 支持为动态生成的标签元素绑定事件也许就live和delegate了吧,不过新版本已经不支持live了,只有delegate delegate真的比较特殊呀,不同于其他事件绑定的...
  • 一、delegate优势  1.非常严格的语法。所有将听到的事件必须是在delegate协议中有清晰的定义。  2.如果delegate中的一个方法没有实现那么就会出现编译警告/错误  3.协议必须在controller的作用域范围内定义 ...
  • 做过IOS开发的都应该知道TableView有两个属性,delegate和dataSource。这就是代理最好的体现,tableView在设计之初并不知道这个tableView将来会放在哪里,存储的是什么东西,这里数据源就起到了关键性作用:对于设计...
  • 在jQuery1.7中 .delegate()已被.on()取代。对于早期版本,它仍然使用事件委托的最有效手段。 在事件绑定和委派,delegate()和on在一般情况下,这两种方法是等效的。 .delegate() 指定的元素(属于被选元素的子元素)...
  • 今天我们要来介绍另一种方式:使用delegate传递消息。  delegate称为委托,同时也是一种代理设计模式。使用委托避免了类与类的耦合度过高。利用委托赋值更加安全可控,委托赋值在不暴露自己类的属性的前提下就可以...
  • delegate() 方法为指定的元素(属于被选元素的子元素)添加一个或多个事件处理程序,并规定当这些事件发生时运行的函数。 使用 delegate() 方法的事件处理程序适用于当前或未来的元素(比如由脚本创建的新元素)。 ...
  • 关于C#中Delegate的使用

    2019-01-07 15:44:10
    用了很久的Delegate,但一直迷迷糊糊的,每次用到时都得从网上再查一遍资料。今天在查资料时发现一篇讲的比较浅显易懂的文章,分享一下。里面展示了委托的创建,应用和加入删除,感觉挺不错的。而且,再结合我得理解...
  • Unity 项目中委托Delegate用法案例 Unity中Delegate的用法场景 Chinar - 本文提供全流程,中文翻译。助力快速理解 C# Delegate的基本用法 Unity 中,委托多用于当某个值,或者物体状态发生改变的时候 其他一些操作...
  • Delegate的BeginInvoke()

    2016-08-12 20:50:18
    Delegate的BeginInvoke() 谈到异步操作,就不得不说异步委托,可以说异步委托在实现异步操作方面可谓有得天独厚的优势。那么什么是异步委托呢?异步委托就是定义一个方法,开一个新线程,让这个方法在后台执行。...
  • delegate: 1,“一对一”,对同一个协议,一个对象只能设置一个代理delegate,所以单例对象就不能用代理; 2,代理更注重过程信息的传输:比如发起一个网络请求,可能想要知道此时请求是否已经开始、是否收到了...
1 2 3 4 5 ... 20
收藏数 246,708
精华内容 98,683
关键字:

delegate