1. 程式人生 > >iOS開發之OC與swift開發混編教程,代理的相互呼叫,block的實現。OC呼叫Swift中的代理, OC呼叫Swift中的Block 閉包,swift 3.0

iOS開發之OC與swift開發混編教程,代理的相互呼叫,block的實現。OC呼叫Swift中的代理, OC呼叫Swift中的Block 閉包,swift 3.0

最新一些學妹問起,所以抽點時間來寫的,適合入門級別的swift 與 OC 混編 的程式猿。  

本文章將從兩個方向分別介紹 OC 與 swift 混編  


1. 第一個方向從 swift工程 中引入 oc類 

    1. 1 如何在swift的類中使用oc類
    1.2  如何在swift中實現oc的代理方法
    1.3   如何在swift中實現oc的Block回撥

2. 第二個方向從OC工程中引入swift類

    2.1  如何在OC類中使用swift類
    2.2   如何在OC中實現swift的代理方法
    2.3   如何在OC中實現swift中類似Block回撥

下面是具體的實現過程:

 1.1  如何在swift的類中使用oc類? 

1.  swift工程中引入OC類。 具體實現過程。

    1.1 新建一個swift工程類。 取名 swiftOrOC

    1.2  實現的功能為 :  從swift. viewController.swift 中 push到 OC語言 secondViewController 控制器

1.2.1  新建SecondViewController 類 。

        

    1.2.2 建立橋接檔案。 (很重要)

    一定要記得點選這個按鈕。 

       1.2.3  接下來工程目錄如下:

     1.2.4 接下來就可以實現具體的跳轉功能了。 

      ViewController.swift中具體實現

import UIKit

class ViewController: UIViewController {

    @IBOutlet weak var hintLabel: UILabel!  //稍後用來顯示回撥
    
    // push 到 oc controller
    @IBAction func pushAction(_ sender: AnyObject) {
        let secondVC = SecondViewController.init()
        self.navigationController?.pushViewController(secondVC, animated: true)
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
    }

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


}

1.2 如何在swift中實現oc的代理方法

       1.2.1 首先在 SecondViewController.h 中宣告一個協議。具體程式碼

#import <UIKit/UIKit.h>

@protocol SecondDelegate <NSObject>

-(void)refreshHintLabel:(NSString *)hintString;

@end

@interface SecondViewController : UIViewController

@property (nonatomic,weak)id<SecondDelegate> secondDelegate;
@end
     1.2.2 然後在SecondViewController.m中,通過一個UITextField,讓使用者輸入內容,當用戶點選返回的時候把輸入框中的內容返回給對應的代理。具體程式碼如下
#import "SecondViewController.h"
#import "UIViewController+BackButtonHandler.h"

@interface SecondViewController ()
{
    UITextField *textField;
}
@end

@implementation SecondViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    self.title = @"oc";
    
    self.view.backgroundColor  = [UIColor whiteColor];
    
    textField = [[UITextField alloc]initWithFrame:CGRectMake(100, 100, 200, 200)];
    textField.placeholder = @"請輸入使用者名稱";
    [self.view addSubview:textField];
    [textField.layer setBorderColor:[UIColor blackColor].CGColor];
    [textField.layer setBorderWidth:1.0];

    
}

-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{
    [self.view endEditing:YES];
}
#pragma mark 返回上一頁回撥 ,將使用者輸入的使用者名稱傳回給 ViewController.swift
-(BOOL)navigationShouldPopOnBackButton{
    if ([_secondDelegate respondsToSelector:@selector(refreshHintLabel:)]) {
        [_secondDelegate refreshHintLabel: textField.text];
    }
    
    return YES;
}


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

/*
#pragma mark - Navigation

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

@end
 1.2.3 接下來就非常簡單了,讓ViewController.swift只需要成為SecondViewController的代理,然後遵循她的協議,就可以了。 具體程式碼如下。

       1.2.3.1 遵循協議

  

     1.2.3.2 成為代理,並實現協議方法,更改controller.swift中hintLabel的text。

    // push 到 oc controller
    @IBAction func pushAction(_ sender: AnyObject) {
        let secondVC = SecondViewController.init()
        secondVC.secondDelegate = self;
        self.navigationController?.pushViewController(secondVC, animated: true)
    }
    
    // SecondViewControll的代理方法
    func refreshHintLabel(_ hintString: String!) {
        hintLabel.text = "secondView textView.text = " + hintString;
    }
    

 1.3   如何在swift中實現oc的Block回撥

1.3.1 具體過程與1.2小節一樣。 直接上程式碼。

        1.3.2 宣告block;

typedef void(^RefreshHintLabelBlock)(NSString *hintString);

@interface SecondViewController : UIViewController
@property (nonatomic, copy) RefreshHintLabelBlock hintBlock;
@end

        1.3.3 block的回撥。 SecondViewController.m中

#pragma mark 返回上一頁回撥 ,將使用者輸入的使用者名稱傳回給 ViewController.swift
-(BOOL)navigationShouldPopOnBackButton{    
    if (_hintBlock) {
        _hintBlock(textField.text);
    }
    return YES;
}

        1.3.4 在swift類中呼叫 oc的block.

    // push 到 oc controller
    @IBAction func pushAction(_ sender: AnyObject) {
        let secondVC = SecondViewController.init()
//        secondVC.secondDelegate = self;
        secondVC.hintBlock = {(t:String?)in
            self.hintLabel.text = "secondView textView.text = " + t!
        }
        self.navigationController?.pushViewController(secondVC, animated: true)
    }


2.  OC工程中引入swift類。 具體實現過程。

    耽誤了不少時間, 今天才開始寫oc工程中引入swift類。

    demo地址: 

     2.1  如何在OC類中使用swift類

       2.1.1   新建一個基於OC語言的工程 ,取名 OcOrSwiftTwo        2.1. 2  實現的功能為 : 從oc類 viewcontroller中, push 至 swift語言 SecondViewController  ,然後SecondViewController可以通過代理或者swift閉包把值傳回viewcontroller.         2.1.3   當前檔案目錄看下圖:  (第四個箭頭: 橋接檔案)     2.2   如何在OC中實現swift的代理與閉包Block方法     2.2.1 如何在oc中引入swift類。#import "工程名-swift.h"
#import "OcOrSwiftTwo-swift.h"
   2.2.2 在secondViewController.swift 中實現代理與閉包,程式碼如下:     注意: @objc(代理名)  才能在外部可見這個代理  
import UIKit
import Foundation

// 必須加上@objc 代理才能在oc類中可見。
@objc(EditTextFieldDelegate)
protocol EditTextFieldDelegate:NSObjectProtocol {
    func editTextField(_ str: String) -> Void
}

@objc(SecondViewController)
class SecondViewController: UIViewController {

    var editorDelegate:EditTextFieldDelegate?
    var textField:UITextField?
    var addButton:UIButton?
    var pushButton:UIButton?
    
    typealias editorBlock = (_ t:String) -> Void
    var myEidtorBlock:editorBlock?
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.view.backgroundColor = UIColor.white
        textField = UITextField.init(frame: CGRect.init(x: 50, y: 60, width: 200, height: 50))
        textField?.placeholder = "輸入返回首頁的內容"
        self.view.addSubview(textField!)
        
        addButton = UIButton.init(type: .custom)
        addButton?.setTitleColor(UIColor.black, for: .normal)
        addButton?.setTitle("pop", for: .normal)
        addButton?.frame = CGRect.init(x: 50, y: 150, width: 200, height: 50)
        addButton?.layer.borderColor = UIColor.black.cgColor
        addButton?.layer.borderWidth = 1.0
        addButton?.addTarget(self, action: #selector(popAction), for: .touchUpInside)
        self.view.addSubview(addButton!)
        
        
        
        pushButton = UIButton.init(type: .custom)
        pushButton?.setTitleColor(UIColor.black, for: .normal)
        pushButton?.setTitle("push", for: .normal)
        pushButton?.frame = CGRect.init(x: 50, y: 250, width: 200, height: 50)
        pushButton?.layer.borderColor = UIColor.black.cgColor
        pushButton?.layer.borderWidth = 1.0
        pushButton?.addTarget(self, action: #selector(pushAction), for: .touchUpInside)
        self.view.addSubview(pushButton!)
        
    }
    
    func popAction() -> Void {
        
        if editorDelegate != nil {
            editorDelegate?.editTextField((textField?.text)!)
        }
        
        if ((self.myEidtorBlock) != nil){
            self.myEidtorBlock!((textField?.text!)!)
        }
        
        self.navigationController?.popViewController(animated: true)
    }
    
    
    func pushAction() -> Void {
        let three = ThreeViewController.init()
        self.navigationController?.pushViewController(three, animated: true)
        
    }     
    2.2.3   在oc類中viewcontroller.m 檔案中實現SecondviewController.swift的相關代理與閉包(block). 程式碼如下:    
#import "ViewController.h"
#import "OcOrSwiftTwo-swift.h"

@interface ViewController ()<EditTextFieldDelegate>
@property (nonatomic, strong) UITextField *showTextField;
@property (nonatomic, strong) UIButton *pushButton;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    _showTextField = [[UITextField alloc]initWithFrame:CGRectMake(50, 100 , 200, 50)];
    _showTextField.placeholder = @"swift傳回的文字內容";
    _showTextField.adjustsFontSizeToFitWidth = YES;
    _showTextField.enabled = NO;
    [self.view addSubview:_showTextField];
    
    _pushButton = [UIButton buttonWithType:UIButtonTypeCustom];
    [_pushButton.layer setBorderColor:[UIColor blackColor].CGColor];
    [_pushButton.layer setBorderWidth:1.0];
    [_pushButton setFrame:CGRectMake(50, 200, 200, 50)];
    [_pushButton setTitleColor:[UIColor blackColor] forState:UIControlStateNormal];
    [_pushButton setTitle:@"push" forState:UIControlStateNormal];
    [_pushButton addTarget:self action:@selector(pushAction) forControlEvents:UIControlEventTouchUpInside];
    
    [self.view addSubview:_pushButton];
}




-(void)pushAction{
    SecondViewController *second = [[SecondViewController alloc]init];
    // second.editorDelegate = self;
    
    /*
      swift中的閉包回滴
     */
    second.myEidtorBlock = ^(NSString *str) {
        _showTextField.text = [NSString stringWithFormat:@"second傳回資訊: %@",str];
    };
    [self.navigationController pushViewController:second animated:YES];
}

#pragma mark swift中的代理
-(void)editTextField:(NSString *)str{
    _showTextField.text = [NSString stringWithFormat:@"second傳回資訊: %@",str];
}

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