swift调用oc初始化类方法init方法和对象方法init的区别等问题

今天用swift调用oc的一个工具类,在oc中可以轻松运行的转换成swift出现了问题

首先,oc中的类方法playerView因为会被系统自动去掉前面的TDW然后取后面的变成初始化init(),所以系统提示把类方法直接改成init()
《swift调用oc初始化类方法init方法和对象方法init的区别等问题》
然后我按照系统提示直接修改成了这样的格式

 var playerView = TDWPlayerView()

结果运行以后并没有进入到类方法playerView中,也没有进入类方法+ (instancetype)init中,而是进入了对象方法- (instancetype)init中,而这个工具类,并没有重写对象方法- (instancetype)init,所以就没有进行自定义的初始化

于是我针对swift调用oc类的初始化进行了详细分类说明

首先看下oc类TDWPlayerView定义了4个类方法和1个对象方法init

用oc写的类TDWPlayerView,在oc中调用调用类初始化方法和对象方法,可以很轻松的调用
TDWPlayerView.h中定义了 4个类方法和 1个 对象方法

//TDWPlayerView.h中定义了 4个类方法和 1个 对象方法
@interface TDWPlayerView : UIView

+ (instancetype)TDWPlayerView;
+ (instancetype)init;
- (instancetype)init;
+ (instancetype)playerView;
+ (instancetype)shared;

@property (weak, nonatomic) id<TDWPlayerViewDelegate> delegate;
@property (nonatomic, strong) AVPlayerItem *playerItem;

@end

TDWPlayerView.m中的文件

@implementation TDWPlayerView
- (instancetype)init{ 
    NSLog(@"init对象方法");
       TDWPlayerView * view =  [[[NSBundle mainBundle] loadNibNamed:@"TDWPlayerView" owner:nil options:nil] firstObject];
       return view;
}
+ (instancetype)init
{ 
    NSLog(@"类方法init");
    TDWPlayerView * view =  [[[NSBundle mainBundle] loadNibNamed:@"TDWPlayerView" owner:nil options:nil] firstObject];
    return view;
}

+(instancetype)TDWPlayerView{ 
     NSLog(@"类方法TDWPlayerView");
    TDWPlayerView * view =  [[[NSBundle mainBundle] loadNibNamed:@"TDWPlayerView" owner:nil options:nil] firstObject];
    return view;
}


+ (instancetype)playerView
{ 
    NSLog(@"类方法playerView");
    TDWPlayerView * view =  [[[NSBundle mainBundle] loadNibNamed:@"TDWPlayerView" owner:nil options:nil] firstObject];
    return view;
}


+ (instancetype)shared
{ 
    NSLog(@"类方法shared");
    TDWPlayerView * view =  [[[NSBundle mainBundle] loadNibNamed:@"TDWPlayerView" owner:nil options:nil] firstObject];
    return view;
}
@end

在oc的类中调用,刚才写的oc方法,oc调用oc没有任何问题

- (void)viewDidLoad { 
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    self.playerView = [[TDWPlayerView alloc]init];//对象方法
    self.playerView = [TDWPlayerView TDWPlayerView]; //类方法
    self.playerView = [TDWPlayerView init]; //类方法
    self.playerView = [TDWPlayerView shared]; //类方法
    self.playerView = [TDWPlayerView playerView]; //类方法
}

打印结果是正确的,
2020-09-22 18:04:39.739433+0800 AVPlayer播放器封装oc[32441:300040] init对象方法
2020-09-22 18:04:39.847482+0800 AVPlayer播放器封装oc[32441:300040] 类方法init
2020-09-22 18:04:39.850247+0800 AVPlayer播放器封装oc[32441:300040] 类方法shared
2020-09-22 18:04:39.852846+0800 AVPlayer播放器封装oc[32441:300040] 类方法playerView

现在看重头戏,容易出问题的swift调用oc类

1.回到故事的开头 类名去掉前缀的类方法调用

var playerView = TDWPlayerView.playerView() //系统报错'playerView()' has been replaced by 'init()'


于是改了代码调用对象方法- (instancetype)init到了这里

var playerView = TDWPlayerView() // 执行后进入- (instancetype)init

打了断点可以看到跳入这里
《swift调用oc初始化类方法init方法和对象方法init的区别等问题》

2.init类方法调用:

按照类方法的调用格式 类名.方法名() 调用类方法 init

var playerView = TDWPlayerView.init()//结果依然进入对象方法

3.init对象方法调用:

错误的格式

var playerView = TDWPlayerView().init()//系统报错,因为这种格式是调用普通的对象方法的,调用类方法的init要换成下面这种格式 

正确的类名.方法名的格式

var playerView = TDWPlayerView.self.init()!
//这个.self是先取出类类型TDWPlayerView.Type,然后在调用init,因为返回的是可选类型,所以强制解包,为了下面调用方便,可以少打一个?

也可以用最简单的写法

var playerView = TDWPlayerView()

可以进入到对象方法中
《swift调用oc初始化类方法init方法和对象方法init的区别等问题》

4.调用 调用类重名 类方法

var playerView = TDWPlayerView.TDWPlayerView()//报错'TDWPlayerView()' has been replaced by 'init()'

系统自动提示,这个已经改成对象方法init()
《swift调用oc初始化类方法init方法和对象方法init的区别等问题》
系统自动改成对象方法init

var playerView = TDWPlayerView()

运行结果也是进入对象init
《swift调用oc初始化类方法init方法和对象方法init的区别等问题》

5.调用不是系统占用名字的类方法可以正常调用

var playerView =  TDWPlayerView.shared()

运行结果是正常运行到类方法中
《swift调用oc初始化类方法init方法和对象方法init的区别等问题》

最后的总结

如果使用swift调用oc代码,如果oc之前的自定义初始化方法是类方法init ()去掉前缀的类名(),类名(),那么你有2种方法正常运行:

  1. 把自定义的oc初始化内容自己改成对象方法,或者把类方法名字改成系统没占用的名字,例如+ (instancetype)shared .
  2. 或者 把自定义初始化内容写到 对象方法中,例如 – (instancetype)init 或 – (instancetype)任何名字
    原文作者:小手琴师
    原文地址: https://blog.csdn.net/boildoctor/article/details/108737694
    本文转自网络文章,转载此文章仅为分享知识,如有侵权,请联系博主进行删除。
点赞