初探swift語言的學習—Object-C與Swift混編
swift 語言出來后,可能新的項目直接使用swift來開發(fā),但可能在過程中會遇到一些情況,某些已用OC寫好的類或封裝好的模塊,不想再在swift 中再寫一次,哪就使用混編。這個在IOS8中是允許的。
先中簡單的入手,先研究在同一個工程目錄下混合使用的情況。
為了演示。先準備兩個類
***個是swift語言寫的類,文件名為 act.swift
- import Foundation
- class Act : NSObject
- {
- func hasAct(tag:Int) -> String
- {
- switch (tag)
- {
- case 1:return "Movie"
- case 2:return "CCTV"
- case 3:return "Sport TV"
- default:return "Area TV"
- }
- }
- init()
- {
- println("act constructor is called.")
- }
- deinit
- {
- println("act destroyed is called.")
- }
- }
第二個是用OC寫的類 頭文件為OCChannel.h ,實現(xiàn)文件為OCChannel.m
頭文件
- #import <Foundation/Foundation.h>
- @interface OCChannel : NSObject
- @property (nonatomic,retain) NSString *ChannelName;
- - (NSString *)ChannelChange:(NSInteger) channels;
- @end
實現(xiàn)文件
- #import "OCChannel.h"
- #import "SwiftModule-swift.h"
- @interface OCChannel()
- {
- Act *act; //swift的類
- }
- @end
- @implementation OCChannel
- - (id)init
- {
- if (self = [super init]) {
- NSLog(@"OC Constructor is called.");
- //使用Swift類
- act = [[Act alloc]init];
- }
- return self;
- }
- - (void)dealloc
- {
- NSLog(@"OC Destroyed is called.");
- //[act release];//ARC not use
- //[super dealloc];//ARC not use
- }
- - (NSString *)ChannelChange:(NSInteger) channels
- {
- return [act hasAct:channels];
- }
- @end
這個OCChannel為中引用了swift 寫的類Act 。主要是為了演示在同一個工程項目里,swift類調(diào)用OC,同時OC類也調(diào)用Swift。從而形成一種混合編寫的模式。
下面是具體步驟:
1.新建一個Swift工程:我這里工程名為MixDemo
建好后工程:
2.就是分別引入前面的兩個類,咱先一個個來。因為建的是Swift,所以,咱先以Swift工程中引用OC文件進行一次混編
Swift中使用OC
首先Swift中不再使用頭文件和.m文件的方式了。所以也不需要使用import ""來導(dǎo)入頭文件。哪swift 如何能訪問到OC的類聲明的。
其實,swift也是需要使用頭文件進行訪問的,只不過不再需要使用顯式的方式使用import進行導(dǎo)入。有兩種方式來實現(xiàn)這個頭文件的生成。
方式一:在一個全新的Swift,利用***次新建提示的方式自動添加橋接頭文件。
點確定這后就會生成一個以<produceName-Bridging-Header.h>的頭文件。
建好后的工程:
這里有一個地方需要注意的就是在targets->build settings ->Object-C Bridging Header 設(shè)為哪個橋接的頭文件即可。
經(jīng)過上述步驟,橋接文件弄好了就可以
盡情的把想要在swift類中調(diào)用的OC頭文件放使用import "" 寫到這個橋接文件中吧。就像:
- //
- // Use this file to import your target's public headers that you would like to expose to Swift.
- //MixDemo/MixDemo-Bridging-Header.h
- #import "OCChannel.h"
同樣的,當你知道這個swift搜索頭文件的關(guān)系后,就不需要再理會這個-Bridging-Header.h的文件了。完全可以手工建一個并取自己喜歡的名字。如:
方式二:
新建一個頭文件,名為:OCContainerHeader.h
好了,以上的設(shè)置后就完全滿足了Swift使用OC寫的類了。
- mport UIKit
- class ViewController: UIViewController {
- override func viewDidLoad() {
- super.viewDidLoad()
- // Do any additional setup after loading the view, typically from a nib.
- //調(diào)用OC類
- var channel = OCChannel()
- println(channel.ChannelChange(10))
- println(channel.ChannelChange(2))
- }
- override func didReceiveMemoryWarning() {
- super.didReceiveMemoryWarning()
- // Dispose of any resources that can be recreated.
- }
- }
好了下面再來看一下OC如何調(diào)用Swift寫的類。(事實上,如果你是一比一抄我這個DEMO,哪么恭喜你,在以上你將編譯不通過。因為我的OC類中引用了swfit 寫的類,所以你要想運行,就必須把哪個Act 的類注釋了才行。)
OC如何調(diào)用Swift寫的類
OC要想使用,必須有頭文件。而swift文件卻沒有頭文件,所在咱們想必也需要產(chǎn)生一個頭文件。但對于OC調(diào)用swift 的頭文件比較特殊。因頭文件里面的機制是自動生成的,在不熟悉的,不建議手寫。
哪如何產(chǎn)生這個頭文件。(注意,系統(tǒng)設(shè)置的頭文件,在工程中是看不到的。)
產(chǎn)生步驟:
選中targets->build settings ->packing->Product Module Name 中設(shè)置模塊名,這個名稱很重要 swift 的頭文件就是根據(jù)這個來命名的。
這樣,工程中如查Swift要使用OC,則把需要使用的OC類的頭文件,全寫在MixDemo-Bridging-Header.h里。同樣如果OC中所使用的swift類,只需要Clean一把,再編就可以了,但不要忘了導(dǎo)入SwiftModule-swift.h哦(名稱自取,但-swift.h是固定的),另外還有一個需要讀者注意的。
注:
凡是用Swift寫的類,如果不繼成自NSObject或NSObject 的派生類,哪么編譯后將不會生成對應(yīng)的轉(zhuǎn)換類。從而使得OC 中找不到相應(yīng)的聲明。
如我的例子中 class Act 這樣不會被編譯到SwiftModule-swift.h中,但寫為 class Act : NSObject,就可以編譯出相應(yīng)的聲明。另外可以使用@objc加以聲明,但這個還是一樣,類***繼承NSObject下來。就像下面:
- import Foundation
- @objc(Act)
- class Act
- {
- func hasAct(tag:Int) -> String
- {
- switch (tag)
- {
- case 1:return "Movie"
- case 2:return "CCTV"
- case 3:return "Sport TV"
- default:return "Area TV"
- }
- }
- @objc(init)//原本以為加上這個alloc就可以找到,但不行的。。。
- init()
- {
- println("act constructor is called.")
- }
- deinit
- {
- println("act destroyed is called.")
- }
- }
但是在使用時你就會發(fā)現(xiàn)
act = [[Act alloc]init]; //報錯,找不到alloc,因此建議大家還是繼承NSObject.