如何在iOS应用程序中进行自定义委派

时间:2012-08-18 17:06:50

标签: iphone

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

3 个答案:

答案 0 :(得分: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];

并在代表

  • 像往常一样在.h文件中包含<YourDelegate>
  • 在.m中,将您的自定义委托的类的委托属性分配给self

答案 1 :(得分:1)

创建自定义代理和协议iOS |斯威夫特&amp;目标C

协议

协议是一个方法列表,用于指定代理将实现的接口。我们可以使用两种代理:Option和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。

<强>目标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()类。

<强>目标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时,它通知视图控制器,重新启动计时器并打印“嘿,我的委托在控制台中工作”。

如果您对代码有任何疑问或发现本教程有帮助,请在下面的评论中告诉我们!我很感激反馈。另外别忘了在twitter上关注我。我一直在寻找iOS开发人员发推文。

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

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

,或者

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

答案 2 :(得分:-5)

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

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

然后在你想要回调给委托的类的任何函数中做这样的事情:

if ( [delegate respondsToSelector:@selector(myDelegateMethod)] ) {
[delegate myDelegateMethod];
}