天天看點

swift調用oc初始化類方法init方法和對象方法init的差別等問題

今天用swift調用oc的一個工具類,在oc中可以輕松運作的轉換成swift出現了問題

首先,oc中的類方法playerView因為會被系統自動去掉前面的TDW然後取後面的變成初始化init(),是以系統提示把類方法直接改成init()

swift調用oc初始化類方法init方法和對象方法init的差別等問題

然後我按照系統提示直接修改成了這樣的格式

結果運作以後并沒有進入到類方法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.回到故事的開頭 類名去掉字首的類方法調用

于是改了代碼調用對象方法- (instancetype)init到了這裡

打了斷點可以看到跳入這裡

swift調用oc初始化類方法init方法和對象方法init的差別等問題

2.init類方法調用:

按照類方法的調用格式 類名.方法名() 調用類方法 init

3.init對象方法調用:

錯誤的格式

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

var playerView = TDWPlayerView.self.init()!
//這個.self是先取出類類型TDWPlayerView.Type,然後在調用init,因為傳回的是可選類型,是以強制解包,為了下面調用友善,可以少打一個?
           

也可以用最簡單的寫法

可以進入到對象方法中

swift調用oc初始化類方法init方法和對象方法init的差別等問題

4.調用 調用類重名 類方法

系統自動提示,這個已經改成對象方法init()

swift調用oc初始化類方法init方法和對象方法init的差別等問題

系統自動改成對象方法init

運作結果也是進入對象init

swift調用oc初始化類方法init方法和對象方法init的差別等問題

5.調用不是系統占用名字的類方法可以正常調用

運作結果是正常運作到類方法中

swift調用oc初始化類方法init方法和對象方法init的差別等問題

最後的總結

如果使用swift調用oc代碼,如果oc之前的自定義初始化方法是類方法init ()去掉字首的類名(),類名(),那麼你有2種方法正常運作:

  1. 把自定義的oc初始化内容自己改成對象方法,或者把類方法名字改成系統沒占用的名字,例如+ (instancetype)shared .
  2. 或者 把自定義初始化内容寫到 對象方法中,例如 - (instancetype)init 或 - (instancetype)任何名字