開篇
在簡單的學(xué)習(xí)了swift語法之后虏缸,開始在項(xiàng)目里使用良姆。很多東西都是別人鋪好路,自己只是套用寫UI而已。這里先簡單過渡一下OC-Swift啼器,后續(xù)再深入研究Swift相關(guān)知識(shí)旬渠。
Swift與OC如何互相調(diào)用
大部分項(xiàng)目應(yīng)該都是要從OC過渡到Swift,這就避免不了混編端壳,這里涉及到兩個(gè)橋接頭文件:
1. Swift調(diào)用OC {targetName}-Bridging-Header.h
作用:Swift可調(diào)用OC告丢,在此文件中import OC的頭文件
在OC工程中創(chuàng)建swift文件時(shí)會(huì)有此提示,點(diǎn)擊create Xcode會(huì)幫我們生產(chǎn)此文件更哄。
并且在
Targets-->Build Settings-->Swift Compiler - General-->Objective-C Bridging Header
有配置路徑芋齿。如果工程里沒有此文件,我們可以手動(dòng)創(chuàng)建成翩,并且在這里配置一下觅捆,不過注意的是文件名字必須為上述格式{targetName}-Bridging-Header.h
2. OC調(diào)用Swift 一般為{targetName}-swift.h
在上面圖中我們看到Objective-C Generated Interface Header Name
這里也有一個(gè)配置的文件路徑菲宴,這里就是讓OC可與調(diào)用Swift置鼻。需要調(diào)用swift的地方,import這個(gè)文件就可以说莫。
名字為什們說一般為{targetName}-swift.h
呢术羔?當(dāng)targetName中存在-
這種情況赢赊,需要變_
。 例如targetNameOC-Swift
级历,這個(gè)頭文件的名字應(yīng)該是OC_Swift-Swift.h
释移。這個(gè)文件內(nèi)是swift編譯生成的對(duì)應(yīng)OC代碼。
這個(gè)文件在工程內(nèi)不能直接看到寥殖,編譯后玩讳,可以通過Command+單擊該文件名,就會(huì)看到具體生成的代碼嚼贡。
需要注意的是:
- 在OC里如果想要調(diào)用Swift熏纯,需要在被訪問的類,屬性粤策,方法前面加上@objc樟澜,并且如果是類,需要繼承NSObject叮盘,否則編譯也會(huì)報(bào)錯(cuò)秩贰。
@objc class TestSwiftClass: NSObject { }
- 這就又有問題了,如果一個(gè)類特別復(fù)雜都需要暴露給OC熊户,那不是得寫好多@objc萍膛?這時(shí)候可以使用@objcMembers, 這樣類、類中的所有屬性嚷堡、方法都暴露給OC可以直接調(diào)用蝗罗。
@objcMembers class Car: NSObject { }
- 我們還可以給swift屬性艇棕、方法重新定義供OC使用的名字
@objc(realName)
var name: String;
@objc(ocRun)
func run() {
}
以上整體下來示例:
//swift中寫法
@objcMembers class TestSwiftClass: NSObject {
@objc(realName)
var name: String;
var age: Int;
init(name:String, age:Int) {
self.name = name
self.age = age
}
@objc(ocRun)
func run() {
}
}
//OC中調(diào)用
- (void)viewDidLoad {
[super viewDidLoad];
TestSwiftClass *obj = [[TestSwiftClass alloc]initWithName:@"zhangsan" age:12];
obj.age = 11;
obj.realName = @"ZhangSan";
[obj ocRun];
}
- 我們上面會(huì)發(fā)現(xiàn)swif中定義的init方法
init(name:String, age:Int)
,而OC里面調(diào)用還是我們熟悉的樣子TestSwiftClass *obj = [[TestSwiftClass alloc]initWithName:@"zhangsan" age:12];
而且OC里面的方法- (instancetype)initWithTitle:(NSString *)title;
到Swift中調(diào)用的時(shí)候是let obj = TestOCClass(title: "title")
這里是xcode幫我做了優(yōu)化串塑,生成對(duì)應(yīng)風(fēng)格的代碼沼琉。
這里有個(gè)坑,就是你可能會(huì)發(fā)現(xiàn)在swift中無法調(diào)用一些OC的單例創(chuàng)建方法,比如 + (instancetype)manager, 或者+(instancetype)shareManager桩匪。后來發(fā)現(xiàn)需要定義一些標(biāo)準(zhǔn)名字比如default singleton shared 打瘪。不過這個(gè)問題應(yīng)該在只存在某幾個(gè)版本的Xcode中,目前發(fā)現(xiàn)Xcode11.3沒有這個(gè)問題
以上大概就已經(jīng)做好混編的基礎(chǔ)了傻昙。
Selector的使用
在OC里面我們經(jīng)常使用@selector(name)
闺骚,在swift里面只是把@替換#,例:#selector(name)
妆档。
- 注意的是僻爽,必須是被@objcMembers或@objc修飾的方法才可以定義選擇器。
為什么呢贾惦?我們可以想一下@selector(name)是依賴OC的runtime胸梆,純swift是沒有runtime的,所以既然要使用方法選擇器须板,說明需要用到runtime碰镜,所以需要通過關(guān)鍵字橋接到OC。當(dāng)然在swift里面也可以調(diào)用perform(#selector(name))
String的區(qū)別
我們發(fā)現(xiàn)swift中的String在OC中會(huì)自動(dòng)轉(zhuǎn)換為NSString习瑰。但是Swift中的String的用法確與OC相差很大绪颖。在系統(tǒng)學(xué)習(xí)之前,我兩個(gè)月都沒用明白(但是不能承認(rèn)自己笨甜奄。嗯菠发!咳)。
關(guān)于字符串拼接之類的就不多說了贺嫂,主要說一下關(guān)于String的Index。
String的下標(biāo)(Index)并不是int類型雁乡,而是String.Index第喳,Index是個(gè)結(jié)構(gòu)體
雖然他不是整形,但是他一樣代表著位置踱稍。關(guān)于String類型的一些方法曲饱,.startIndex/.endIndex!,例:name.startIndex/name.endIndex
代表是起始位置(第一個(gè)字符的位置)/最后位置(最后一個(gè)字符的下一位)
關(guān)于String的一些插入刪除方法:
//插入
var str = "a-b"
// 插入單個(gè)字符珠月,最后一個(gè)位置插入‘-’,結(jié)果:a-b-
str.insert("-", at: str.endIndex)
// 插入字符串使用contentsOf:末尾插入c-d,結(jié)果:a-b-c-d
str.insert(contentsOf: "c-d", at: str.endIndex)
// after:str.startIndex扩淀,在第一個(gè)字符的后一位,結(jié)果:a666-b-c-d
str.insert(contentsOf: "666", at: str.index(after: str.startIndex))
// before:str.endIndex啤挎,在末尾的前一位驻谆,也就是最后一個(gè)字符的位置插入卵凑,從插入位置起,原字符都順位后移胜臊,結(jié)果:a666-b-c-888d
str.insert(contentsOf: "888", at: str.index(before: str.endIndex))
// offsetBy:可以指定偏移量勺卢,從開始向后偏移3,也就是第三個(gè)6的位置象对,插入后黑忱,原字符順位后移,結(jié)果 a66hello6-b-c-888d
str.insert(contentsOf: "hello", at: str.index(str.startIndex, offsetBy: 3))
//刪除
//刪除第一個(gè)'-' 結(jié)果:a66hello6b-c-888d
str.remove(at: str.firstIndex(of: "-")!)
//刪除所有勒魔,符合閉包條件的所有值甫煞。結(jié)果ahellob-c-888d
str.removeAll { $0 == "6" }
還有其他的關(guān)于range的方法,就不在這羅列了冠绢,明白了上面這些關(guān)于String.Index的使用抚吠,其他的基本一樣了。
Substring
String可以通過下標(biāo)唐全、 prefix埃跷、 suffix等截取子串,但是子串類型不是String邮利,而是Substring弥雹。String本身就是個(gè)結(jié)構(gòu)體,不能被繼承延届。Substring也就不是什么子類之類的剪勿。他一樣也是個(gè)結(jié)構(gòu)體。
- Substring 是字符串的一部分方庭,和父字符串共享同一塊內(nèi)存空間厕吉,并且記錄了自己的開始和結(jié)束位置。
- String 和 Substring 都聲明實(shí)現(xiàn)了 StringProtocol械念。StringProtocol 包含了一個(gè)字符串的基本屬性和功能头朱。
- Substring發(fā)生修改 或者 轉(zhuǎn)為String時(shí),會(huì)分配新的內(nèi)存存儲(chǔ)字符串?dāng)?shù)據(jù)
具體細(xì)節(jié)龄减,大家自行Google吧项钮。