本文介绍: swiftocswiftoc区别Swift比Objective-C优势swift独有Swift调用OCOC调用SwiftSwift 选择器selectorswiftoc区别1,最明显的区别:OC一个类由.h和.m两个文件组成,而swift只有.swift一个文件,所以整体的文件数量比OC有一定减少。2,不像C语言和OC语言一样都必须有一个函数main()作为程序的入口,swift程序从第一句开始向下顺序执行,一直到最后。(swift全局范围内的首句可执行代码作为程序入口,swift

swift和oc区别

1,最明显的区别:OC一个类由.h和.m两个文件组成,而swift只有.swift一个文件,所以整体的文件数量比OC有一定减少。

2,不像C语言和OC语言一样都必须有一个函数main()作为程序的入口,swift程序从第一句开始向下顺序执行,一直到最后。(swift将全局范围内的首句可执行代码作为程序入口,swift也有main函数,只是不用我们自己编写。)

3,swift数据类型都会自动判断,只区分变量var常量let

4,关于BOOL类型更加严格,swift不再是OC的非0就是真,而是true才是真false才是假。

5,swift的switch语句后面可以跟各种数据类型了,如Int,字符串元组区间都行,并且里面不用break

6,swift 中可以定义继承于其它类的类,称之为基类(base calss)。

7,final关键字

使用final关键字修饰的类,不能被其他类继承

继承final修饰的类会报错:Inheritance from a final class ‘……’

Swift比Objective-C优势

1,Swift容易阅读语法和文件结构简易化。

2,Swift更易于维护,文件分离结构更清晰。

3,Swift更加安全,它是类型安全语言

  Swift 是一个类型安全(type safe)的语言。类型安全的语言可以让你清楚地知道代码处理的值的类型。如果你的代码需要一个 String ,你绝对不可能不小心传进去一个 Int 。

由于 Swift 是类型安全的,所以它会在编译你的代码时进行类型检查(type checks),并把不匹配的类型标记错误。这可以让你在开发时候尽早发现修复错误

当你要处理不同类型的值时,类型检查可以帮你避免错误。然而,这并不是说你每次声明常量变量时候都需 要显式指定类型。如果你没有显式指定类型,Swift 会使用类型推断(type inference)来选择合适的类型。有了类型推断编译器可以在编译代码时候自动推断表达式的类型。原理简单,只要检查你赋的值即可

因为有类型推断,和 C 或者 Objective-C 比起来 Swift 很少需要声明类型。常量和变量虽然需要明确类型,但 是大部分工作并不需要自己完成

4,Swift代码更少,简洁语法可以省去大量冗余代码

5,Swift速度更快,运算性能更高。

swift独有

1、范围运算符
ab 表示 [a,b] 包括ab 。 (如3…5 就是范围取3,4,5)
a…<b 表示 [a,b) 包括a,不包括b 。 (如3…5 就是范围取3,4)
常见的如for循环:for i in 0…9{}
2、独有的元组类型
元组(tuples)把多个组合一个复合值。元组内的值可以使任意类型,并不要求是相同类型。eg
var value = (Int,String) = (x:15,y:“abc”) 复制代码
3、swift中使用let定义常量,var定义变量
使用常量,更加安全,不能够修改,在需要对象进行修改时候 只能用var修饰.
4、if letguard let用法
缩减代码量,安全处理数据逻辑

Swift调用OC

由于很多常用第三方框架还是oc版本没有swift版本,但是项目可能需要调用那些框架的功能,所以swift语言的工程需要用到oc版本的三方或者公司项目需要用到swift和oc混合开发时,就涉及到了Swift调用OC或者OC调用Swift

1、手动新建一个桥接头文件文件名格式默认为:{targetName}-Bridging-Header.h然后在Build Settings设置路径,如下
在这里插入图片描述
2、或者在swift工程里新建一个oc的文件时会自动弹出弹框询问是否自动创建桥接文件,如下
在这里插入图片描述
在这里插入图片描述
想用oc哪些头文件,在桥接头文件导入头文件即可,例#import “Person.h”,则在swift工程中,Person类就暴漏给swift使用了
Person.h

#import <Foundation/Foundation.h&gt;

NS_ASSUME_NONNULL_BEGIN

int sum(int a,int b);

@interface Person : 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

NS_ASSUME_NONNULL_END

Person.m

#import "Person.h"

@implementation Person

- (instancetype)initWithAge:(NSInteger)age name:(NSString *)name{
    if (self = [super init]) {
        self.age = age;
        self.name = name;
    }
    return self;
}
+ (instancetype)personWithAge:(NSInteger)age name:(NSString *)name{
    return [[self alloc] initWithAge:age name:name];
}

+ (void)run{NSLog(@"Person + run");}
- (void)run{NSLog(@"%zd %@-run",_age,_name);}

+ (void)eat:(NSString *)food other:(NSString *)other{
    NSLog(@"Person + eat %@ %@",food,other);
}
- (void)eat:(NSString *)food other:(NSString *)other{
    NSLog(@"%zd %@ - eat %@ %@",_age,_name,food,other);
}
@end

int sum(int a,int b){return a+b;}

swift文件中Swift代码

let p = Person(age: 10, name: "jack")
p.age = 18
p.name = "Rose"
p.run() //18 Rose - run
p.eat("Apple", other: "water")//18 Rose - eat Apple water
     
Person.run() //Person + run
Person.eat("Pizza", other: "Banana")//Person + eat Pizza  Banana
        
print(sum(10, 20)) //30

OC调用Swift

1、Xcode已经默认生成一个用于OC调用Swift的头文件,文件名格式是:{targetName}-Swift.h
这里需要注意的是:工程名如果带有中划线-时,buildsettings路径变成了下划线_,import引用时,写下划线文件名即可工程名如果带有下划线_时,buildsettings的路径也是下划线,引用时会报错找不到文件。文件内部放的是swift要暴露给oc的代码,那么也不是所有的swift代码都要暴露给oc,要暴漏给oc的代码要继承NSObject

2、Swift暴露给OC的类最终继承自NSObject(原因:因为oc有runtime,runtime是要求类有isa指针isa指针肯定是继承NSObject才有的,所以最终要继承NSObject)

3、使用@objc修饰需要暴露给OC的成员

4、使用@objcMembers修饰

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

extension Car{
    @objc func test(){
        print(price,band,"test")
    }
}

OC文件:

Car *car = [[Car alloc] initWithPrice:1.55 band:@"bannana"];
[car run]; // 报错:No visible @interface for 'Car' declares the selector 'run'
[Car run]; //报错:No known class method for selector 'run'
[car test];
被@objc修饰的属性或者方法才能被调用

也可写成如下
swift文件:

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

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

OC文件:

Car *car = [[Car alloc] initWithPrice:1.55 band:@"bannana"];
[car run];
[Car run];
[car test];

5、Xcode会根据Swift代码生成对应的OC声明写入 {targetName}-Swift.h文件

6、可以通过@objc重命名Swift暴露给OC的符号名(类名属性名、函数名等)
swift文件:

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

extension Car{
    @objc(exec)
    func test(){
        print(price,band,"test")
    }
}

OC文件:

XXCar *car = [[XXCar alloc] initWithPrice:1.55 band:@"bannana"];
car.name = @"banban";
[car drive];
[car exec];
[XXCar run];

Swift 选择器selector

1、Swift中依然可以使用选择器,使用#selector(name)定义一个选择
2、必须是被@objcMembers或@objc修饰的方法才可以定义选择器。
selector选择器)是依赖于runtime的,oc里才有runtime,纯swift里是不存在runtime

@objcMembers class XXPerson: NSObject {
    func test1(v1:Int){
        print("test1")
    }
    func test2(v1:Int,v2:Int) {
        print("test2(v1:v2:)")
    }
    func test2(_ v1:Double,_ v2:Double){
        print("test2(_ :_ :)")
    }
    func run(){
        perform(#selector(test1))
        perform(#selector(test1(v1:)))
        perform(#selector(test2(v1:v2:)))
        perform(#selector(test2(_:_:)))
        perform(#selector(test2 as (Double,Double) -> Void))
    }
}

p.run()底层是怎么调用的?
oc文件:
Person.h

#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface Person : NSObject

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

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

- (void)run;
@end

Person.m

#import "Person.h"
#import "ludan-Swift.h"

@implementation Person

- (instancetype)initWithAge:(NSInteger)age name:(NSString *)name{
    if (self = [super init]) {
        self.age = age;
        self.name = name;
    }
    return self;
}
- (void)run{NSLog(@"%zd %@-run",_age,_name);}
@end

swift文件:

var p:Person = Person(age: 10, name: "jack")
p.run()

汇编来看,走runtime的机制,objc_msgSend
反过来,OC调用Swift底层又是如何调用?
swift写的类继承自NSObject类,暴漏给OC调用,同样走runtime那套机制,objc_msgSend

car.run()底层是怎么调用的?
第一种情况:

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

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

var car:Car = Car(price: 10.5, band: "Audi")
car.run()

在swift文件里边调用,没有走oc的runtime机制,如果想要走objc_msgSend,则在run方法前边加上dynamic关键字修饰

第二种情况(不继承自NSObject,并且没有@objcMembers修饰):

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

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

var car:Car = Car(price: 10.5, band: "Audi")
car.run()

纯swift类方法调用是走虚表v-Table那一套机制

原文地址:https://blog.csdn.net/AHekey/article/details/123082085

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任

如若转载,请注明出处:http://www.7code.cn/show_47886.html

如若内容造成侵权/违法违规/事实不符,请联系代码007邮箱suwngjj01@126.com进行投诉反馈,一经查实,立即删除

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注