oc swift 转_oc 混编swift ,oc 中不能找到swift 方法 - CSDN
  • 这篇文章主要给大家介绍了关于Objective-C和Swift的转换速查手册的相关资料,文中通过示例代码介绍的非常详细,非常推荐给大家参考学习使用,盛情邀请读者进入小编交流群:624212887,一起交流学习 前言 如果你正要...

    这篇文章主要给大家介绍了关于Objective-C和Swift的转换速查手册的相关资料,文中通过示例代码介绍的非常详细,非常推荐给大家参考学习使用,盛情邀请读者进入小编交流群:624212887,一起交流学习

    前言

    如果你正要从Objective-C过渡到Swift,或反过来,一个在两种语言间显示等效代码的小手册会很有帮助。本文内容就是这些:苹果开发者的红宝书,包含变量,集合,函数,类等等。

    下面例子中,上面是Objective-C代码,下面是等效的Swift代码。必要的地方我会给一些备注来帮助你理解。

    变量与常量

    创建一个变量

    //Objective-C
    NSInteger score = 556;
    //
    NSString *name = @"Taylor";
    //
    BOOL loggedIn = NO;
    
    //Swift
    var score = 556
    //
    var name = "Taylor"
    //
    var loggedIn = false
    

    创建一个常量

    //Objective-C
    const NSInteger score = 556;
    //
    NSString * const name = @"Taylor";
    //
    const BOOL firstRun = YES;
    //Objective-C中常量用的很少
    
    //Swift
    let score = 556
    //
    let name = "Taylor"
    //
    let firstRun = true
    //Swift中常量很常见
    

    创建一个变量数组

    创建一个常量数组

    //Objective-C
    NSArray *grades = @[@90, @85, @97];
    //
    NSArray *names = @[@"Taylor", @"Adele", @"Justin"];
    
    //Swift
    let grades = [90, 85, 97]
    //
    let names = ["Taylor", "Adele", "Justin"]
    

    向数组中添加一个值类型

    //Objective-C
    NSMutableArray *array = [NSMutableArray new];
    //
    [array addObject:[NSValue valueWithRect:CGRectMake(0, 0, 32, 64)]];
    //在添加到集合前,值类型有对应的引用类型
    
    //Swift
    var array = [CGRect]()
    //
    array.append(CGRect(x: 0, y: 0, width: 32, height: 64))
    

    创建一个字典

    //Objective-C
    NSDictionary *houseNumbers = @{ @"Paul": @7, @"Jess": @56, @"Peter": @332 };
    
    //Swift
    let houseNumbers = ["Paul": 7, "Jess": 56, "Peter": 332]
    

    定义一个枚举

    //Objective-C
    typedef NS_ENUM(NSInteger, ShapeType) {
     kCircle,
     kRectangle,
     kHexagon
    };
    
    //Swift
    enum ShapeType: Int {
     case circle
     case rectangle
     case hexagon
    }
    

    附加一串字符

    //Objective-C
    NSString *first = @"Hello, ";
    NSString *second = [first stringByAppendingString:@" world!"];
    
    //Swift
    let first = "Hello, "
    let second = first + "world!"
    

    增加数字

    //Objective-C
    NSInteger rating = 4;
    rating++;
    rating += 3;
    
    //Swift
    var rating = 4
    rating += 1
    rating += 3
    

    插入字符串

    //Objective-C
    NSString *account = @"twostraws";
    NSString *str = [NSString stringWithFormat:@"Follow me on Twitter: %@", account];
    
    //Swift
    let account = "twostraws"
    let str = "Follow me on Twitter: \(account)"
    

    打印调试信息

    //Objective-C
    NSString *username = @"twostraws";
    NSLog(@"Username is %@", username);
    
    //Swift
    let username = "twostraws"
    print("Username is \(username)")
    

    控制流

    检查状态

    //Objective-C
    NSInteger result = 86;
    if (result >= 85) {
     NSLog(@"You passed the test!");
    } else {
     NSLog(@"Please try again.");
    }
    
    //Swift
    let result = 86
     
    if result >= 85 {
     print("You passed the test!")
    } else {
     print("Please try again.")
    }
    

    循环一定次数

    //Objective-C
    for (NSInteger i = 0; i < 100; ++i) {
     NSLog(@"This will be printed 100 times.");
    }
    
    //Swift
    for _ in 0 ..< 100 {
     print("This will be printed 100 times.")
    }
    

    在数组中循环

    //Objective-C
    NSArray *companies = @[@"Apple", @"Facebook", @"Twitter"];
     
    for (NSString *name in companies) {
     NSLog(@"%@ is a well-known tech company.", name);
    }
    
    //Swift
    let companies = ["Apple", "Facebook", "Twitter"]
     
    for name in companies {
     print("\(name) is a well-known tech company.")
    }
    

    数值切换

    //Objective-C
    NSInteger rating = 8;
     
    switch (rating) {
     case 0 ... 3:
     NSLog(@"Awful");
     break;
     case 4 ... 7:
     NSLog(@"OK");
     break;
     case 8 ... 10:
     NSLog(@"Good");
     break;
     default:
     NSLog(@"Invalid rating.");
    }
    //很多人不知道Objective-C有范围支持,所以你也许看到二选一的语法
    
    //Swift
    let rating = 8
     
    switch rating {
    case 0...3:
     print("Awful")
    case 4...7:
     print("OK")
    case 8...10:
     print("Good")
    default:
     print("Invalid rating.")
    }
    //Swift不会fall through案例,除非你使用fallthrough关键字
    

    函数

    不接收参数也没有返回的函数

    //Objective-C
    - (void)printGreeting {
     NSLog(@"Hello!");
    }
     
    [self printGreeting];
    
    //Swift
    func printGreeting() {
     print("Hello!")
    }
     
    printGreeting()
    

    不接收参数,返回一个字符串的函数

    //Objective-C
    - (NSString*)printGreeting {
     return @"Hello!";
    }
     
    NSString *result = [self printGreeting];
    
    //Swift
    func printGreeting() -> String {
     return "Hello!"
    }
     
    let result = printGreeting()
    

    接收一个字符串,返回一个字符串的函数

    //Objective-C
    - (NSString*)printGreetingFor:(NSString*)user {
     return [NSString stringWithFormat:@"Hello, %@!", user];
    }
     
    NSString *result = [self printGreetingFor:@"Paul"];
    //第一个参数的名称需要为方法名的一部分
    
    //Swift
    func printGreeting(for user: String) -> String {
     return "Hello, \(user)!"
    }
    
    let result = printGreeting(for: "Paul")
    

    接收一个字符串和一个整数,返回一个字符串的函数

    //Objective-C
    - (NSString*)printGreetingFor:(NSString*)user withAge:(NSInteger)age {
     if (age >= 18) {
      return [NSString stringWithFormat:@"Hello, %@! You're an adult.", user];
     } else {
      return [NSString stringWithFormat:@"Hello, %@! You're a child.", user];
     }
    }
     
    NSString *result = [self printGreetingFor:@"Paul" withAge:38];
    
    //Swift
    func printGreeting(for user: String, age: Int) -> String {
     if age >= 18 {
      return "Hello, \(user) You're an adult."
     } else {
      return "Hello, \(user)! You're a child."
     }
    }
     
    let result = printGreeting(for: "Paul", age: 38)
    

    从函数返回多个值

    //Objective-C
    - (NSDictionary*)loadAddress {
     return @{
      @"house": @"65, Park Street",
      @"city": @"Bristol",
      @"country": @"UK"
     };
    }
     
    NSDictionary*address = [self loadAddress];
    NSString *house = address[@"house"];
    NSString *city = address[@"city"];
    NSString *country = address[@"country"];
    //Objective-C不支持元祖(tuple),所以用字典或数组替代
    
    //Swift
    func loadAddress() -> (house: String, city: String, country: String) {
     return ("65, Park Street", "Bristol", "UK")
    }
     
    let (city, street, country) = loadAddress()
    

    不接收参数没有返回的闭环

    //Objective-C
    void (^printUniversalGreeting)(void) = ^{
     NSLog(@"Bah-weep-graaaaagnah wheep nini bong");
    };
     
    printUniversalGreeting();
    
    //Swift
    let universalGreeting = {
     print("Bah-weep-graaaaagnah wheep nini bong")
    }
     
    universalGreeting()
    

    不接收参数返回一个字符串的闭环

    /Objective-C
    NSString* (^getUniversalGreeting)(void) = ^{
     return @"Bah-weep-graaaaagnah wheep nini bong";
    };
     
    NSString *greeting = getUniversalGreeting();
    NSLog(@"%@", greeting);
    
    //Swift
    let getUniversalGreeting = {
     return "Bah-weep-graaaaagnah wheep nini bong"
    }
     
    let greeting = getUniversalGreeting()
    print(greeting)
    

    接收一个字符串参数,返回一个字符串的闭环

    //Objective-C
    NSString* (^getGreeting)(NSString *) = ^(NSString *name) {
     return [NSString stringWithFormat:@"Live long and prosper, %@.", name];
    };
     
    NSString *greeting = getGreeting(@"Paul");
    NSLog(@"%@", greeting);
    
    //Swift
    let getGreeting = { (name: String) in
     return "Live long and prosper, \(name)."
    }
     
    let greeting = getGreeting("Paul")
    print(greeting)
    

    创建空类

    //Objective-C
    @interface MyClass : NSObject
    @end
     
    @implementation MyClass
    @end
    
    //Swift
    class MyClass: NSObject {
    }
    //推荐使用结构代替类,这样也许不需要从NSObject继承了
    

    创建有2个属性的类

    //Objective-C
    @interface User : NSObject
    @property (nonatomic, copy) NSString *name;
    @property (nonatomic, assign) NSInteger age;
    @end
     
    @implementation User
     
    @end
    
    //Swift
    class User {
     var name: String
     var age: Int
      
     init(name: String, age: Int) {
      self.name = name
      self.age = age
     }
    }
    //Swift要求进行初始化,给这些属性默认值
    

    创建有一个私有属性的类

    //Objective-C
    //在头文件中
    @interface User : NSObject
    @property (nonatomic, copy) NSString *name;
    @end
     
    //在执行文件中
    @interface User()
    @property (nonatomic, assign) NSInteger age;
    @end
     
    @implementation User
     
    @end
    //Objective-C实际上并不支持私有属性,通常都用这种变通方式
    
    //Swift
    class User {
     var name: String
     private var age: Int
      
     init(name: String, age: Int) {
      self.name = name
      self.age = age
     }
    }
    

    创建有一个实例方法的类

    //Objective-C
    @interface Civilization : NSObject
    - (NSInteger)getMeaningOfLife;
    @end
     
    @implementation Civilization
    - (NSInteger)getMeaningOfLife {
     return 42;
    }
    @end
    
    //Swift
    class Civilization {
     func getMeaningOfLife() -> Int {
      return 42
     }
    }
    

    创建有一个静态方法的类

    //Objective-C
    @interface Civilization : NSObject
    + (NSInteger)getMeaningOfLife;
    @end
     
    @implementation Civilization
    + (NSInteger)getMeaningOfLife {
     return 42;
    }
    @end
    //差别很小,用+而不是-
    
    //Swift
    class Civilization {
     class func getMeaningOfLife() -> Int {
      return 42
     }
    }
    //Swift也支持静态方法——它不会在子类中被覆盖
    

    用一种新方法扩展一个类型

    //Objective-C
    @interface NSString (Trimming)
    - (NSString*)trimmed;
    @end
     
    @implementation NSString (Trimming)
     
    - (NSString*)trimmed {
     return [self stringByTrimmingCharactersInSet:[NSCharacterSet whitespaceCharacterSet]];
    }
     
    @end
    
    //Swift
    extension String {
     func trimmed() -> String {
      return trimmingCharacters(in: .whitespacesAndNewlines)
     }
    }
    

    检查一个对象的类

    //Objective-C
    if ([object isKindOfClass:[YourClass class]]) {
     NSLog(@"This is a YourClass.");
    }
    
    //Swift
    if object is YourClass {
     print("This is a YourClass.")
    }
    

    类型转换

    //Objective-C
    Dog *poodle = (Dog*)animalObject;
    
    //Swift
    let poodle = animalObject as? Dog
    //
    let poodle = animalObject as! Dog
    //如果不是一个dog,前者会把poodle设为nil,后者则会崩溃
    

    GCD
    在不同线程运行代码

    //Objective-C
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
     NSLog(@"Running in the background...");
      
     dispatch_async(dispatch_get_main_queue(), ^{
      NSLog(@"Running back on the main thread");
     });
    });
    
    //Swift
    DispatchQueue.global().async {
     print("Running in the background...")
      
     DispatchQueue.main.async {
      print("Running on the main thread")
     }
    }
    

    以上就是这篇文章的全部内容了,希望本文的内容对大家具有一定的参考学习价值,如果有疑问大家可以进入小编交流群:624212887,一起交流学习,谢谢大家的支持

    展开全文
  • oc代码直接转swift代码

    2020-07-29 14:20:42
    oc代码直接转swift代码,非常好用,绝对福利~更多精彩
  • OC转Swift工具

    2016-05-18 14:34:17
    http://www.ucai.cn/index.php?app=tools&mod=Code&act=oc2swift
    http://www.ucai.cn/index.php?app=tools&mod=Code&act=oc2swift
    
    展开全文
  • OC转Swift指南

    2020-03-10 00:01:09
    作者丨zhangferry来源丨iOS成长之路运行环境:Xcode 11.1 Swift5.0最近参与的一个项目需要从Objective-C(以下简称OCSwift,期间遇到了一些...

    作者丨zhangferry

    来源丨iOS成长之路

    运行环境:Xcode 11.1 Swift5.0

    最近参与的一个项目需要从Objective-C(以下简称OC)转到Swift,期间遇到了一些坑,于是有了这篇总结性的文档。如果你也有将OC项目Swift化的需求,可以作为参考。

    OC转Swift有一个大前提就是你要对Swift有一定的了解,熟悉Swift语法,最好是完整看过一遍官方的Language Guide。

    转换的过程分自动化和手动转译,鉴于自动化工具的识别率不能让人满意,大部分情况都是需要手动转换的。

    自动化工具

    有一个比较好的自动化工具Swiftify,可以将OC文件甚至OC工程整个转成Swift,号称准确率能达到90%。我试用了一些免费版中的功能,但感觉效果并不理想,因为没有使用过付费版,所以也不好评价它就是不好。

    Swiftify还有一个Xcode的插件Swiftify for Xcode,可以实现对选中代码和单文件的转化。这个插件还挺不错,对纯系统代码转化还算精确,但部分代码还存在一些识别问题,需要手动再修改。

    手动Swift化

    桥接文件

    如果你是在项目中首次使用Swift代码,在添加Swift文件时,Xcode会提示你添加一个 .h的桥接文件。如果不小心点了不添加还可以手动导入,就是自己手动生成一个 .h文件,然后在 BuildSettings>SwiftCompiler-General>Objective-CBridgingHeader中填入该 .h文件的路径。

    这个桥接文件的作用就是供Swift代码引用OC代码,或者OC的三方库。

    #import "Utility.h"
    #import <Masonry/Masonry.h>
    

    BridgingHeader的下面还有一个配置项是 Objective-CGeneratedInterfaceHeaderName,对应的值是 ProjectName-Swift.h。这是由Xcode自动生成的一个隐藏头文件,每次Build的过程会将Swift代码中声明为外接调用的部分转成OC代码,OC部分的文件会类似 pch一样全局引用这个头文件。因为是Build过程中生成的,所以只有 .m文件中可以直接引用,对于在 .h文件中的引用下文有介绍。

    Appdelegate(程序入口)

    Swift中没有 main.m文件,取而代之的是 @UIApplicationMain命令,该命令等效于原有的执行 main.m。所以我们可以把 main.m文件进行移除。

    系统API

    对于 UIKit框架中的大部分代码转换可以直接查看系统API文档进行转换,这里就不过多介绍。

    property(属性)

    Swift没有 property,也没有 copynonatomic等属性修饰词,只有表示属性是否可变的 letvar

    注意点一OC中一个类分 .h.m两个文件,分别表示用于暴露给外接的方法,变量和仅供内部使用的方法变量。迁移到Swift时,应该将 .m中的property标为 private,即外接无法直接访问,对于 .h中的property不做处理,取默认的 internal,即同模块可访问。

    对于函数的迁移也是相同的。

    注意点二有一种特殊情况是在OC项目中,某些属性在内部( .m)可变,外部( .h)只读。这种情况可以这么处理:

    private(set) var value: String
    

    就是只对 valueset方法就行 private标记。

    注意点三Swift中针对空类型有个专门的符号 ?,对应OC中的 nil。OC中没有这个符号,但是可以通过在 nullablenonnull表示该种属性,方法参数或者返回值是否可以空。

    如果OC中没有声明一个属性是否可以为空,那就去默认值 nonnull

    如果我们想让一个类的所有属性,函数返回值都是 nonnull,除了手动一个个添加之外还有一个宏命令。

    NS_ASSUME_NONNULL_BEGIN
    /* code */
    NS_ASSUME_NONNULL_END
    

    enum(枚举)

    OC代码:

    typedef NS_ENUM(NSInteger, PlayerState) {
    PlayerStateNone= 0,
    PlayerStatePlaying,
    PlayerStatePause,
    PlayerStateBuffer,
    PlayerStateFailed,
    };
    typedef NS_OPTIONS(NSUInteger, XXViewAnimationOptions) {
    XXViewAnimationOptionNone= 1<<  0,
    XXViewAnimationOptionSelcted1= 1<<  1,
    XXViewAnimationOptionSelcted2= 1<<  2,
    }
    

    Swift代码

    enumPlayerState: Int{
    case none = 0
    case playing
    case pause
    case buffer
    case failed
    }
    structViewAnimationOptions: OptionSet{
    let rawValue: UInt
    staticletNone= ViewAnimationOptions(rawValue: 1<<0)
    staticletSelected1= ViewAnimationOptions(rawValue: 1<<0)
    staticletSelected2= ViewAnimationOptions(rawValue: 1<< 2)
    //...
    }
    

    Swift没有 NS_OPTIONS的概念,取而代之的是为了满足 OptionSet协议的 struct类型。

    懒加载

    OC代码:

    - (MTObject*)object{
    if(!_object) {
            _object = [MTObjectnew];
    }
    return _object;
    }
    

    Swift代码:

    lazy varobject: MTObject= {
    letobject= MTObject()
    return imagobjecteView
    }()
    

    闭包

    OC代码:

    typedefvoid(^DownloadStateBlock)(BOOL isComplete);
    

    Swift代码:

    typealias DownloadStateBlock= ((_ isComplete: Bool) -> Void)
    

    单例

    OC代码:

    + (XXManager*)shareInstance {
    staticdispatch_once_t onceToken;
        dispatch_once(&onceToken, ^{
            instance = [[self alloc] init];
    });
    return instance;
    }
    

    Swift对单例的实现比较简单,有两种方式:

    第一种

    swiftletshared=XXManager()// 声明在全局命名区(global namespace)ClassXXManager{}

    你可能会疑惑,为什么没有 dispatch_once,如何保证多线程下创建的唯一性?其实是这样的,Swift中全局变量是懒加载,在AppDelegate中被初始化,之后所有的调用都会使用该实例。而且全局变量的初始化是默认使用 dispatch_once的,这保证了全局变量的构造器(initializer)只会被调用一次,保证了 shard原子性

    第二种

    ClassXXManager{
    staticlet shared = XXManager()
    privateoverride init() {
    // do something
    }
    }
    

    Swift 2 开始增加了 static关键字,用于限定变量的作用域。如果不使用 static,那么每一个 shared都会对应一个实例。而使用 static之后, shared成为全局变量,就成了跟上面第一种方式原理一致。可以注意到,由于构造器使用了 private 关键字,所以也保证了单例的原子性。

    初始化方法和析构函数

    对于初始化方法OC先调用父类的初始化方法,然后初始自己的成员变量。Swift先初始化自己的成员变量,然后在调用父类的初始化方法。

    OC代码:

    // 初始化方法
    @interfaceMainView: UIView
    @property(nonatomic, strong) NSString*title;
    - (instancetype)initWithFrame:(CGRect)frame title:(NSString*)title NS_DESIGNATED_INITIALIZER;
    @end
    @implementationMainView
    - (instancetype)initWithFrame:(CGRect)frame title:(NSString*)title {
    if(self= [super initWithFrame:frame]) {
    self.title = title;
    }
    returnself;
    }
    @end
    // 析构函数
    - (void)dealloc {
    //dealloc
    }
    

    Swift代码:

    classMainViewSwift: UIView{
    let title: String
        init(frame: CGRect, title: String) {
    self.title = title
    super.init(frame: frame)
    }
        required init?(coder: NSCoder) {
            fatalError("init(coder:) has not been implemented")
    }
            deinit {
    //deinit
    }
    }
    

    函数调用

    OC代码:

    // 实例函数(共有方法)
    - (void)configModelWith:(XXModel*)model {}
    // 实例函数(私有方法)
    - (void)calculateProgress {}
    // 类函数
    + (void)configModelWith:(XXModel*)model {}
    

    Swift代码

    // 实例函数(共有方法)
    func configModel(with model: XXModel) {}
    // 实例函数(私有方法)
    private func calculateProgress() {}
    // 类函数(不可以被子类重写)
    static func configModel(with model: XXModel) {}
    // 类函数(可以被子类重写)
    class func configModel(with model: XXModel) {}
    // 类函数(不可以被子类重写)
    classfinal func configModel(with model: XXModel) {}
    

    OC可以通过是否将方法声明在 .h文件表明该方法是否为私有方法。Swift中没有了 .h文件,对于方法的权限控制是通过权限关键词进行的,各关键词权限大小为:private<fileprivate<internal<public<open

    其中 internal为默认权限,可以在同一 module下访问。

    NSNotification(通知)

    OC代码:

    // add observer
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(method) name:@"NotificationName"object:nil];
    // post
    [NSNotificationCenter.defaultCenter postNotificationName:@"NotificationName"object:nil];
    

    Swift代码:

    // add observer
    NotificationCenter.default.addObserver(self, selector: #selector(method), name: NSNotification.Name(rawValue: "NotificationName"), object: nil)
    // post
    NotificationCenter.default.post(name: NSNotification.Name(rawValue: "NotificationName"), object: self)
    

    可以注意到,Swift中通知中心 NotificationCenter不带 NS前缀,通知名由字符串变成了 NSNotification.Name的结构体。

    改成结构体的目的就是为了便于管理字符串,原本的字符串类型变成了指定的 NSNotification.Name类型。上面的Swift代码可以修改为:

    extension NSNotification.Name{
    staticletNotificationName= NSNotification.Name("NotificationName")
    }
    // add observer
    NotificationCenter.default.addObserver(self, selector: #selector(method), name: .NotificationName, object: nil)
    // post
    NotificationCenter.default.post(name: .NotificationName, object: self)
    

    protocol(协议/代理)

    OC代码:

    @protocolXXManagerDelegate<NSObject>
    - (void)downloadFileFailed:(NSError*)error;
    @optional
    - (void)downloadFileComplete;
    @end
    @interfaceXXManager: NSObject
    @property(nonatomic, weak) id<XXManagerDelegate> delegate;
    @end
    

    Swift中对 protocol的使用拓宽了许多,不光是 class对象, structenum也都可以实现协议。需要注意的是 structenum为指引用类型,不能使用 weak修饰。只有指定当前代理只支持类对象,才能使用 weak。将上面的代码转成对应的Swift代码,就是:

    @objc protocol XXManagerDelegate{
        func downloadFailFailed(error: Error)
    @objc optional func downloadFileComplete() // 可选协议的实现
    }
    classXXManager: NSObject{
        weak vardelegate: XXManagerDelegate?
    }
    

    @objc是表明当前代码是针对 NSObject对象,也就是 class对象,就可以正常使用weak了。

    如果不是针对NSObject对象的delegate,仅仅是普通的class对象可以这样设置代理:

    protocol XXManagerDelegate: class{
        func downloadFailFailed(error: Error)
    }
    classXXManager{
        weak vardelegate: XXManagerDelegate?
    }
    

    值得注意的是,仅 @objc标记的 protocol可以使用 @optional

    Swift和OC混编注意事项

    函数名的变化

    如果你在一个Swift类里定义了一个delegate方法:

    @objc protocol MarkButtonDelegate{
        func clickBtn(title: String)
    }
    

    如果你要在OC中实现这个协议,这时候方法名就变成了:

    - (void)clickBtnWithTitle:(NSString*)title {
    // code
    }
    

    这主要是因为Swift有指定参数标签,OC却没有,所以在由Swift方法名生成OC方法名时编译器会自动加一些修饰词,已使函数作为一个句子可以"通顺"。

    在OC的头文件里调用Swift类

    如果要在OC的头文件里引用Swift类,因为Swift没有头文件,而为了让在头文件能够识别该Swift类,需要通过 @class的方法引入。

    @classSwiftClass;
    @interfaceXXOCClass: NSObject
    @property(nonatomic, strong) SwiftClass*object;
    @end
    

    对OC类在Swift调用下重命名

    因为Swift对不同的module都有命名空间,所以Swift类都不需要添加前缀。如果有一个带前缀的OC公共组件,在Swift环境下调用时不得不指定前缀是一件很不优雅的事情,所以苹果添加了一个宏命令 NS_SWIFT_NAME,允许在OC类在Swift环境下的重命名:

    NS_SWIFT_NAME(LoginManager)
    @interfaceXXLoginManager: NSObject
    @end
    

    这样我们就将 XXLoginManager在Swift环境下的类名改为了 LoginManager

    引用类型和值类型

    • struct 和 enum 是值类型,类 class 是引用类型。

    • String, Array和 Dictionary都是结构体,因此赋值直接是拷贝,而 NSStringNSArray 和 NSDictionary则是类,所以是使用引用的方式。

    • struct 比 class 更“轻量级”, struct 分配在栈中, class 分配在堆中。

    id类型和AnyObject

    OC中 id类型被Swift调用时会自动转成 AnyObject,他们很相似,但却其实概念并不一致。Swift中还有一个概念是 Any,他们三者的区别是:

    • id 是一种通用的对象类型,它可以指向属于任何类的对象,在OC中即是可以代表所有继承于 NSObject的对象。

    • AnyObject可以代表任何 class类型的实例。

    • Any可以代表任何类型,甚至包括 func类型。

    从范围大小比较就是:id<AnyObject<Any

    其他语法区别及注意事项(待补充)

    1、Swift语句中不需要加分号 ;

    2、关于Bool类型更加严格,Swift不再是OC中的非0就是真,真假只对应 truefalse

    3、Swift类内一般不需要写 self,但是闭包内是需要写的。

    4、Swift是强类型语言,必须要指定明确的类型。在Swift中 IntFloat是不能直接做运算的,必须要将他们转成同一类型才可以运算。

    5、Swift抛弃了传统的 ++--运算,抛弃了传统的C语言式的 for循环写法,而改为 for-in

    6、Swift的 switch操作,不需要在每个case语句结束的时候都添加 break

    7、Swift对 enum的使用做了很大的扩展,可以支持任意类型,而OC枚举仅支持 Int类型,如果要写兼容代码,要选择Int型枚举。

    8、Swift代码要想被OC调用,需要在属性和方法名前面加上 @objc

    9、Swift独有的特性,如泛型, struct,非Int型的 enum等被包含才函数参数中,即使添加 @objc也不会被编译器通过。

    10、Swift支持重载,OC不支持。

    11、带默认值的Swift函数再被OC调用时会自动展开。

    语法检查

    对于OC转Swift之后的语法变化还有很多细节值得注意,特别是对于初次使用Swift这门语言的同学,很容易遗漏或者待着OC的思想去写代码。这里推荐一个语法检查的框架SwiftLint,可以自动化的检查我们的代码是否符合Swift规范。

    可以通过 cocoapods进行引入,配置好之后,每次 Build的过程,Lint脚本都会执行一遍Swift代码的语法检查操作,Lint还会将代码规范进行分级,严重的代码错误会直接报错,导致程序无法启动,不太严重的会显示代码警告(⚠️)。

    如果你感觉SwiftLint有点过于严格了,还可以通过修改 .swiftlint.yml文件,自定义属于自己的语法规范。

    近期精彩内容推荐:  

     有个程序媛上司是什么体验

     一个天才程序员的黑帮大佬人生

     200行Python代码做一个换脸程序

     在 IntelliJ IDEA 中使用 Git,太方便了!

    在看点这里好文分享给更多人↓↓

    展开全文
  • SwiftOC转换

    2015-09-16 20:36:13
    1、获取对象类型 OC: NSDate*date = [NSDatedate];NSLog(@"%@",NSStringFromClass([date class])); Swift: let date = NSDate() let name = date.dynamicType 共有: let name:
    1、获取对象类型
    OC:

    NSDate* date = [NSDatedate];

    NSLog(@"%@",NSStringFromClass([date class]));


    Swift

    letdate =NSDate()

    letname = date.dynamicType


    共有:

    let name:AnyClass! = object_getClass(date)


    2、函数入参中对象转化
    OC转Swift,对象变为可选类型
    Swift转OC,不用改变

    3、枚举
    1)Swift按位操作使用OptionSetType
    struct MyOptions : OptionSetType {
        let rawValue: Int
    
        static let None         = MyOptions(rawValue: 0)
        static let FirstOption  = MyOptions(rawValue: 1 << 0)
        static let SecondOption = MyOptions(rawValue: 1 << 1)
        static let ThirdOption  = MyOptions(rawValue: 1 << 2)
    }
    

    Now we can use set-based semantics with MyOptions:

    let singleOption = MyOptions.FirstOption
    let multipleOptions: MyOptions = [.FirstOption, .SecondOption]
    if multipleOptions.contains(.SecondOption) {
       
    print("multipleOptions has SecondOption")
    }
    let allOptions = MyOptions(rawValue: 7)
    if allOptions.contains(.ThirdOption) {
       
    print("allOptions has ThirdOption")
    }

    2)OC调用Swift,只需增加前缀@objc
    @objc enum Bear: Int {
        case Black, Grizzly, Polar
    }
    

    Shamelessly taken from the Swift Blog


    In Objective-C this would look like

    Bear type = BearBlack;
    switch (type) {
       
    case BearBlack:
       
    case BearGrizzly:
       
    case BearPolar:
           
    [self runLikeHell];
    }

    3)Swift调用OC直接使用rawValue
    展开全文
  • OCSwift之间的互调很简单,iOS8以后官方给出了这两种语言之间的桥接方案,简单说就是在Swift工程中,通过提示创建的Bridging头文件可以将OC文件和Swift文件衔接在一起,从而可以在OC文件中引用Swift类,或者在...

    OC和Swift之间的互调很简单,iOS8以后官方给出了这两种语言之间的桥接方案,简单说就是在Swift工程中,通过提示创建的Bridging头文件可以将OC文件和Swift文件衔接在一起,从而可以在OC文件中引用Swift类,或者在Swift文件中引用OC的类。应用较多的主要是在Swift中调用OC类,使得在最新的swift工程中仍然能够兼容使用以前的OC类库等。

    这里通过一个简单的例子展示在Swift工程中OC和Swift之间的互调:

    首先建立一个Swift工程,这里创建了一个Single View Application,工程名为SwiftBridge,并分别新建了一个新的名为SwiftClass的swift类文件和一个名为OCClass的OC类文件,创建第一个OC文件后会提示创建一个Bridging头文件,创建后就可以对两者进行桥接:

    这里我们在ViewController.swift中调用OCClass类,同时在OCClass类中调用SwiftClass.swift。其中在swift中引用OC类时要在Bridging头文件中引入OC类的头文件(swift文件中没有头文件及其引用),而在OC中引用swift类时直接引入“SwiftBridge-swift.h”即可,不需要在Bridging头文件设置,其中“SwiftBridge”为工程名,该文件是隐藏的,对工程中所有swift类文件进行了向OC语言的翻译,从而在OC文件中可以像调用其他OC文件一样调用工程中的swift类文件。

    1. 在SwiftClass.swift中定义一个实例方法和一个类方法:
    import UIKit
    
    class SwiftClass: NSObject {
        func SwiftInstanceMethod() -> Void {
            print("swift instance method!");
        }
        class func SwiftClassMethod() -> Void {
            print("swift class method!");
        }
    }
    1. 在OCClass类中调用SwiftClass:
    /* OCClass.h */
    #import <Foundation/Foundation.h>
    
    @interface OCClass : NSObject
    - (void)OCInstanceMethod;
    + (void)OCClassMethod;
    @end
    
    /* OCClass.m */
    #import "OCClass.h"
    #import "SwiftBridge-swift.h" /* 引入swift类头文件 */
    
    @implementation OCClass
    - (void)OCInstanceMethod {
        /* 调用swift实例方法 */
        SwiftClass *swiftc = [[SwiftClass alloc] init];
        [swiftc SwiftInstanceMethod];
        NSLog(@"oc instance method!");
    }
    + (void)OCClassMethod {
        /* 调用swift类方法 */
        [SwiftClass SwiftClassMethod];
        NSLog(@"oc class method!");
    }
    @end
    1. 在Bridging头文件引入OC类头文件供swift调用:
    /* SwiftBridge-swift.h */
    #import "OCClass.h"
    1. 在ViewController.swift中调用OCClass类:
    /* ViewController.swift */
    import UIKit
    class ViewController: UIViewController {
        override func viewDidLoad() {
            super.viewDidLoad()
    
            let occ = OCClass()
            occ.ocInstanceMethod()
            OCClass.ocClassMethod()
        }
    }

    打印结果:

    swift instance method!
    2017-04-12 12:40:39.657 SwiftBridge[3773:5420107] oc instance method!
    swift class method!
    2017-04-12 12:40:39.657 SwiftBridge[3773:5420107] oc class method!

    另外类似的也可以实现swift和C语言之间的互调。

    展开全文
  • OC Swift 混编

    2017-08-30 13:29:01
    首先承认我落后了,到今天才开始在项目里用swift,而且还不是全部的用,只是ocswift混编,因为实在是进入项目的时候框架已经用oc搭好了啊啊啊啊啊。只能退而求其次,混编了,大致根据百度到的方法试了一下,不是很...
  • OCswift区别

    2019-04-03 10:07:42
    swift 是在oc上提出来的 swift中有oc中没有的类 比如 元组 有泛型 3.因为swift 定义的常亮和变量是没有值的,所以引入了可选的概念,这时候 如果swift没有值的话 就用optional 4.在swift 中,let 声明的常量的值不...
  • 最新一些学妹问起,所以抽点时间来写的,适合入门级别的swiftOC 混编 的程序猿。 本文章将从两个方向分别介绍 OCswift 混编 1. 第一个方向从 swift工程 中引入 oc类   1. 1 如何在swift的类中使用...
  • oc调用swift

    2015-11-14 18:05:06
    如果你想在Objective-C工程中,嵌入Swift文件,实现OC调用Swift,那么这篇文章就能帮助你,由于本人最近在开发Swift项目,所以实现过OC调用Swift,在这过程中遇到过一些瓶颈,特此,将此文奉上,供大家参考。...
  • [Swift]1.在OC项目里的OC代码调用Swift方法,Swift代码里调用OC代码。2.在Swift项目里的Swift代码里调用OC代码,OC代码调用Swift方法。
  • OC项目转Swift指南

    2020-07-11 15:07:53
    OC转Swift有一个大前提就是你要对Swift有一定的了解,熟悉Swift语法,最好是完整看过一遍官方的Language Guide。 转换的过程分自动化和手动转译,鉴于自动化工具的识别率不能让人满意,大部分情况都是需要手动转换的...
  • OCSwift是苹果爸爸的原生语言,Swift代替OC的成本太高,需要过度和时间,但是现在的Swift的成长很快,在这个矛盾的时间,我们必须混编了。 1、创建一个新的工程 ,工程的名字叫OCAndSwiftDemo。 2、配置工程...
  • SwiftOC代码转换实例

    2019-07-22 11:35:57
    1. Objectice-C code: 1 NSShadow *shadow = [NSShadow new]; 2 ... 3 [shadow setShadowColor:[UIColor colorWithRed:1.0 green:1.0 blue:1.0 alpha:1.0]];... 5 [shadow setShadowOffset:CGSizeMake(0, ...
  • oc自动转换成swift网址

    2015-11-12 17:54:03
    https://objectivec2swift.com/#/converter/code
  • OC调用SwiftOC调用Swift方法比较简单。但是需要注意以下几点: 1.需要在当前OC类里导入xxx-Swift.h头文件,其中xxx为项目名称(与你的项目配置相关,具体配置方式见上一篇文章) 2.OC类里仅可以调用public的Swift...
  • OCSwift混合使用

    2017-07-11 09:13:02
    随着swift趋向于稳定,越来越多的公司启动的新项目也想使用swift过把瘾,使用swift的好处与弊端不再赘述。目前版本是swift3.0,而且Xcode9beta版中已经更新到swift4.0。使用swift开发是大趋势,这里从以下几个方面看...
  • OC代码转Swift代码

    2015-07-02 19:57:18
    初始化函数对于oc中的[[XX alloc]init] swift不需要alloc 也不需要init。直接调用以类名为函数名的工厂方法进行初始化。 声明的变量可以不显式声明类型//objective-c UITableView *myTableView = [[UITableView ...
  • swift可以算是OC更上层的语言,我这里说的坑都是关于Swift转OC的,很奇葩吧,还有把Swift项目转成OC的,一句话公司需求,怼得程序员无言以对。(废话不多说了,后面全是骂项目经理和产品的。。...
  • OCSwift混编

    2018-07-19 11:31:59
    首先要说明的是,混编时,比如工程原先用oc,你突然创建了一个swift文件,那么xcode会弹出一个是否创建侨界文件的提示,点击是...1.OC里调用swift: xcode会隐形生成类似类似 “工程名-Swift.h”的文件,直接#imp...
1 2 3 4 5 ... 20
收藏数 20,083
精华内容 8,033
关键字:

oc swift 转