从OC到Swift

一、标记
二、系统版本检测
三、iOS程序的入口


四、Swift调用OC
五、OC调用Swift


一、标记


  • // MARK: -:类似于OC的#pragma mark -
  • #warning("这是一个警告哦"):用于添加一个警告
  • // TODO: - 记得把这搞一下哦:用于标记未完成的任务
  • // FIXME: - 记得把这修复一下哦:用于标记待修复的任务


二、系统版本检测


if #available(iOS 10, macOS 10.12, *) {
    // iOS平台,大于等于10的系统版本才执行
    // macOS平台,大于等于10.12的系统版本才执行
    // 其它平台(如watchOS、tvOS),所有的系统版本都可以执行
}


三、iOS程序的入口


OC:main.m --> main函数 --> UIApplicationMain函数,设置AppDelegate为App的代理。

Swift:AppDelegate里顶部默认有一个@UIApplicationMain,这表示编译器会在自动生成的入口代码——main函数代码——里把AppDelegate设置为App的代理。


四、Swift调用OC


声明在前面:

  • Swift的代码在Swift里调用,是走Swift的方法调用流程;OC的代码在OC里调用,是走OC的方法调用流程——即消息机制
  • 但无论是Swift调用OC,还是OC调用Swift,都是走OC的方法调用流程
文件目录

假设我们有一个用OC写的Person类。

// INEPerson.h
#import <Foundation/Foundation.h>

@interface INEPerson : NSObject

@property (nonatomic, assign) NSInteger age;
@property (nonatomic, copy) NSString *name;

- (instancetype)initWithAge:(NSInteger)age name:(NSString *)name;
+ (instancetype)personWithAge:(NSInteger)age name:(NSString *)name;

- (void)run;
+ (void)run;

- (void)eat:(NSString *)food other:(NSString *)other;
+ (void)eat:(NSString *)food other:(NSString *)other;

@end


// INEPerson.m
#import "INEPerson.h"

@implementation INEPerson

- (instancetype)initWithAge:(NSInteger)age name:(NSString *)name {

    if (self = [super init]) {
        self.age = age;
        self.name = name;
    }

    return self;
}

- (instancetype)initWithAge1:(NSInteger)age name1:(NSString *)name {

    if (self = [super init]) {
        self.age = age;
        self.name = name;
    }

    return self;
}

+ (instancetype)personWithAge:(NSInteger)age name:(NSString *)name {
    
    return [[self alloc] initWithAge1:age name1:name];
}

- (void)run {
    
    NSLog(@"%s, %d, %@", __func__, self.age, self.name);
}

+ (void)run {
    
    NSLog(@"%s", __func__);
}

- (void)eat:(NSString *)food other:(NSString *)other {
    
    NSLog(@"%s, %d, %@, %@, %@", __func__, self.age, self.name, food, other);
}

+ (void)eat:(NSString *)food other:(NSString *)other {
    
    NSLog(@"%s, %@, %@", __func__, food, other);
}

@end

如果我们想在Swift的代码里调用这个类,就得首先创建一个Swift和OC的桥接头文件,文件名的格式为:{targetName}-Bridging-Header.h;然后配置一下这个桥接头文件。

接下来我们就可以在这个桥接头文件里导入Swift想要调用的OC类了。

// SwiftTest-Bridging-Header.h
#import "INEPerson.h"

现在我们去main.swift里调用一下OC的代码。

// main.swift
/*
 会优先调用-initWithAge:name:
 如果没有-initWithAge:name:,才会去调用+personWithAge:name
 */
var person = INEPerson(age: 11, name: "张三")
person?.age = 12
person?.name = "李四"
person?.run() // -[INEPerson run], 12, 李四
person?.eat("Apple", other: "Banana") // -[INEPerson eat:other:], 12, 李四, Apple, Banana

INEPerson.run() // +[INEPerson run]
INEPerson.eat("Beef", other: "Turkey") // +[INEPerson eat:other:], Beef, Turkey


五、OC调用Swift


文件目录

假设我们有一个用Swift写的Car类。

// main.swift
class Car {
    var price: Double
    var band: String
    
    init(price: Double, band: String) {
        self.price = price
        self.band = band
    }
    
    func run() {
        print("run", self.price, self.band)
    }
    
    static func run() {
        print("Car run")
    }
}

extension Car {
    func test() {
        print("test", self.price, self.band)
    }
}


// Swift调用OC的代码
testSwift()

如果我们想在OC的代码里调用这个类,也得首先创建一个OC和Swift的桥接头文件,文件名的格式为:{targetName}-Swift.h,只不过系统早就自动帮我们创建好了,但是我们在文件目录里看不到它;然后配置一下这个桥接头文件,只不过系统也早就自动帮我们配置好了。我们什么都不需要干喽,用的时候导入一下这个桥接头文件就可以了(你可以点进去看看,这个桥接头文件里其实会生成一份Swift代码对应的OC代码)。

我们需要做的仅仅是让用Swift写的那个类继承自NSObject,并用@objcMembers关键字表明要把它暴露给OC使用。

@objcMembers class Car: NSObject {
    var price: Double
    var band: String
    
    init(price: Double, band: String) {
        self.price = price
        self.band = band
    }
    
    func run() {
        print("run", self.price, self.band)
    }
    
    static func run() {
        print("Car run")
    }
}

extension Car {
    func test() {
        print("test", self.price, self.band)
    }
}

现在我们去Person里调用一下Swift的代码。

// INEPerson.h
#import <Foundation/Foundation.h>

void testSwift(); // 一个C函数

@interface INEPerson : NSObject

@end


// INEPerson.m
#import "INEPerson.h"
#import "SwiftTest-Swift.h"

void testSwift() {
    
    Car *car = [[Car alloc] initWithPrice:15 band:@"雪佛兰"];
    car.price = 30;
    car.band = @"奔驰";
    [car run]; // run 30.0 奔驰
    [car test]; // test 30.0 奔驰
    
    [Car run]; // Car run
}

@implementation INEPerson

@end

推荐阅读更多精彩内容