3

在 iPhone 中,每个 UIControl 都有预定义的委托方法,但是我们将如何创建自己的自定义委托方法

4

3 回答 3

19

在你的头文件之前@interface,插入

@protocol YourDelegate <NSObject> 

@optional
- (void) anOptionalDelegateFunction;

@required
- (void) aRequiredDelegateFunction;

@end

和下@interface

@property (nonatomic, assign) id<YourDelegate> delegate;
// Remember to synthesize in implementation file

现在你可以调用你的 .m 文件

[delegate aRequiredDelegateFunction];

在委托中

  • 像往常一样包含<YourDelegate>在 .h 文件中
  • 在 .m 中,将具有自定义委托的类的委托属性分配给self
于 2012-08-18T17:13:02.347 回答
1

创建自定义委托和协议 iOS | Swift 和 Objective-C

协议

协议是指定代理将实现的接口的方法列表。我们可以使用两种委托:Option 和 Required。它们很容易解释,但不同之处在于Required会抛出一个错误,让你知道你的类不符合协议。默认情况下还需要协议方法,因此如果您希望它是可选的,请不要忘记该可选关键字。如果您使用的是 swift,如果您需要可选方法,还需要添加 @objc 前缀。

迅速

//
//  MyTimer.swift
//  SwiftProtocol
//
//  Created by Barrett Breshears on 10/11/14.
//  Copyright (c) 2014 Sledge Dev. All rights reserved.
//

import UIKit

// set up the MyTimerDelegate protocol with a single option timer function
@objc protocol MyTimerDelegate{
       optional func timerFinished()
}


class MyTimer: UIViewController {

   // this is where we declare our protocol
   var delegate:MyTimerDelegate?

   // set up timer variables and labels
   var timer:NSTimer! = NSTimer()
   var labelTimer:NSTimer! = NSTimer()
   var timerLabel:UILabel! = UILabel()
   var timerCount = 0
   var duration = 0

   override func viewDidLoad() {
      super.viewDidLoad()

      // Do any additional setup after loading the view.
      timerLabel = UILabel(frame: self.view.frame)
      timerLabel.textAlignment = NSTextAlignment.Center
      self.view.addSubview(timerLabel)
   }

    override func didReceiveMemoryWarning() {
       super.didReceiveMemoryWarning()
       // Dispose of any resources that can be recreated.
   }

   func startTimer(timerDuration:Double){
       self.duration = Int(timerDuration)
       timerLabel.text = String(format: "%d", duration)

       timer = NSTimer.scheduledTimerWithTimeInterval(timerDuration, target: self, selector: Selector("timerFired:"), userInfo: nil, repeats: false)

       labelTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: Selector("updateLabel:"), userInfo: nil, repeats: true)


       }

             timer.invalidate()
       }
       if(labelTimer.valid){
           labelTimer.invalidate()
       }
        // ************************************** \\
        // ************************************** \\
        // This is the important part right here
       // we want to call our protocol method
       // so the class implementing this delegate will know
       // when the timer has finished
       // ************************************** \\
       // ************************************** \\
       delegate?.timerFinished!()

     }

    func updateLabel(timer:NSTimer){
      duration = duration - 1
      timerLabel.text = String(format: "%d", duration)
    }


        /*
       // MARK: - Navigation

       // In a storyboard-based application, you will often want to do a little preparation before navigation
     override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
      // Get the new view controller using segue.destinationViewController.
     // Pass the selected object to the new view controller.
    }
    */

}

这是一个非常简单的例子,但这就是正在发生的事情。UIViewController 有一个启动计时器方法,它设置了两个计时器:一个在总时间完成时触发,另一个每秒触发一次以更新计时器标签。当总持续时间计时器完成时,将调用 timerFired 方法,这就是我们运行委托的 timerFinished 方法的地方。现在让我们用 Objective-C 做同样的事情。

Objective-C

   //
   //  MyTimer.h
   //  ObjectIveCProtocol
   //
   //  Created by Barrett Breshears on 10/11/14.
   //  Copyright (c) 2014 Sledge Dev. All rights reserved.
   //

   #import 

   // set up the MyTimerDelegate protocol with a single option timer finished function
   @protocol MyTimerDelegate 
   @optional
    -(void)timerFinished;

   @end

   @interface MyTimer : UIViewController
   // this is where we declare our protocol
   @property (nonatomic, strong) id delegate;
   // set up timer variables and labels
   @property (nonatomic, strong) NSTimer *timer;
   @property (nonatomic, strong) NSTimer *labelTimer;
   @property (nonatomic, strong) UILabel *timerLabel;
   @property (nonatomic, assign) int timerCount;
   @property (nonatomic, assign) int duration;

   - (void)startTimer:(float)duration;

   @end

   //
   //  MyTimer.m
   //  ObjectIveCProtocol
   //
   //  Created by Barrett Breshears on 10/11/14.
   //  Copyright (c) 2014 Sledge Dev. All rights reserved.
   //

    #import "MyTimer.h"



    @interface MyTimer ()

    @end

    @implementation MyTimer

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        _timer = [[NSTimer alloc] init];
        _labelTimer = [[NSTimer alloc] init];
        _timerCount = 0;
        _duration = 0;


        _timerLabel = [[UILabel alloc] initWithFrame:self.view.frame];
        [self.view addSubview:_timerLabel];
        [_timerLabel setTextAlignment:NSTextAlignmentCenter];

    }

    - (void)didReceiveMemoryWarning {
        [super didReceiveMemoryWarning];
        // Dispose of any resources that can be recreated.
    }

    - (void)startTimer:(float)duration{
       _duration = (int)duration;
       _timerLabel.text = [NSString stringWithFormat:@"%d", _duration];

       _timer = [NSTimer scheduledTimerWithTimeInterval:duration target:self selector:@selector(timerFired:) userInfo:nil repeats:NO];

        _labelTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(updateLabel:) userInfo:nil repeats:YES];


     }

    - (void)timerFired:(NSTimer *)timer {
          if ([_timer isValid]) {
               [_timer invalidate];
          }
          _timer = nil;
          if ([_labelTimer isValid]) {
              _labelTimer invalidate];
          }
          _labelTimer = nil;
          // ************************************** \\
          // This is the important part right here
          // we want to call our protocol method here
          // so the class implementing this delegate will know
         // when the timer has finished
         // ************************************** \\
         [_delegate timerFinished];
     }

     - (void)updateLabel:(NSTimer *)timer{
          _duration = _duration - 1;
          _timerLabel.text = [NSString stringWithFormat:@"%d", 
          _duration];
      }

 @end

所以同样的事情只是语法不同。UIViewController 有一个启动计时器方法,它设置了两个计时器:一个在总时间完成时触发,另一个每秒触发一次以更新计时器标签。当总持续时间计时器完成时,将调用 timerFired 方法,这就是我们运行委托的 timerFinished 方法的地方。

代表们

现在我们已经设置了所有协议,我们所要做的就是实现它们。我们将通过创建一个委托来做到这一点。委托是一个符合协议的变量,类通常使用它来通知事件,在这种情况下是计时器完成。为此,我们将协议添加到类声明中,让我们的类知道它必须遵守委托。然后我们将委托方法添加到我们的类中。

迅速

     //
     //  ViewController.swift
     //  Swift-Protocol

     //  Created by Barrett Breshears on 10/11/14.
     //  Copyright (c) 2014 Sledge Dev. All rights reserved.


     import UIKit

      // add our MyTimerDelegate to our class
     class ViewController: UIViewController, MyTimerDelegate {

            var timer:MyTimer = MyTimer()

            override func viewDidLoad() {
               super.viewDidLoad()

               timer.view.frame = self.view.frame
               // ************************ \\
               // This is where we let the delegate know 
               // we are listening for the timerFinished method
               // ************************ \\
               timer.delegate = self
               self.view.addSubview(timer.view)
               timer.startTimer(10.0)        
           }

           override func didReceiveMemoryWarning() {
                 super.didReceiveMemoryWarning()
                 // Dispose of any resources that can be recreated.
             }

          // ************************ \\
          // This is where our delegate method is fired
           // ************************ \\
          func timerFinished(){
              timer.startTimer(10.0)
              println("Hey my delegate is working")
          }

  }

所以这里重要的是我们将 timer.delegate 设置为 self 以便调用 ViewController 的方法 timerFinished() 类。

Objective-C

        //
        //  ViewController.h
        //  ObjectIveCProtocol
        //
        //  Created by Barrett Breshears on 10/10/14.
        //  Copyright (c) 2014 Sledge Dev. All rights reserved.


         #import 
         #import "MyTimer.h"

         // add our MyTimerDelegate to our class
         @interface ViewController : UIViewController 

         @property (nonatomic, strong) MyTimer *timer;

         @end



         //  ViewController.m
         //  ObjectIveCProtocol
         //  Created by Barrett Breshears on 10/10/14.
         //  Copyright (c) 2014 Sledge Dev. All rights reserved.


         #import "ViewController.h"

         @interface ViewController ()

         @end

         @implementation ViewController

            - (void)viewDidLoad {
                 [super viewDidLoad];
                 // Do any additional setup after loading the view, typically from a nib.
                 _timer = [[MyTimer alloc] init];
                 _timer.view.frame = self.view.frame;
                 _timer.delegate = self;
                 [self.view addSubview:_timer.view];
                 [_timer startTimer:10.0];

             }

             - (void)didReceiveMemoryWarning {
                  [super didReceiveMemoryWarning];
                  // Dispose of any resources that can be recreated.
            }
             -(void)timerFinished{
                   [_timer startTimer:10.0];
                   NSLog(@"Hey my delegate is working!");
              }

            @end

当我们运行代码时,我们看到计时器标签被添加并设置为 10 秒计时器。它倒计时,当它到达 0 时通知视图控制器,重新启动计时器并打印“嘿,我的代表正在控制台中工作”。

如果您对代码有任何疑问或发现本教程有帮助,请在下面的评论中告诉我!我很感激反馈。也不要忘记在推特上关注我。我一直在寻找 iOS 开发者来发推文。

如果您想关注允许,您可以在此处从 GitHub 下载项目:

https://github.com/barrettbreshears/objective-c-protocol

或者,

https://github.com/barrettbreshears/swift-protocol

于 2017-04-27T13:58:01.593 回答
-6

在您的班级中创建一个 id 对象委托。创建一个 getter 和 setter,以便其他类可以将自己设置为委托。在您的班级中添加以下内容:

@interface MyClass (Private)
-(void)myDelegateMethod;
@end

然后在你想要回调到委托类的任何函数中执行以下操作:

if ( [delegate respondsToSelector:@selector(myDelegateMethod)] ) {
[delegate myDelegateMethod];
}
于 2012-08-18T17:12:11.117 回答