The Swift Programming Language (Swift 3.1)
- Swift中文件權(quán)限
fileprivate :如名字一樣,只有這個(gè)文件才能訪問(wèn)
private: 只能在作用域訪問(wèn)
interal: 默認(rèn)焕济,在整個(gè)模塊可以訪問(wèn).
public: 在同一個(gè)模塊里面可以繼承或者重寫,在模塊外可以訪問(wèn),但不可以重寫和繼承
open:在所有模塊都可以訪問(wèn)脂凶,重寫和繼承
權(quán)限由大到小排序:
open > public > interal > fileprivate > private
- 關(guān)鍵字
final
:
- 可以通過(guò)把方法永品,屬性或下標(biāo)標(biāo)記為`final`來(lái)防止它們被重寫虱歪,只需要在聲明關(guān)鍵字前加上`final`修飾符即可(例如:`final var`时迫,`final func`娇昙,`final class func`,以及`final subscript`)
- 可以通過(guò)在關(guān)鍵字`class`前添加`final`修飾符(`final class`)來(lái)將整個(gè)類標(biāo)記為 `final` 的剥哑。這樣的類是不可被繼承的硅则,試圖繼承這樣的類會(huì)導(dǎo)致編譯報(bào)錯(cuò)。
staic
: 在方法的func
關(guān)鍵字之前加上關(guān)鍵字static
株婴,來(lái)指定類型方法怎虫。類還可以用關(guān)鍵字class
來(lái)允許子類重寫父類的方法實(shí)現(xiàn)。
- Swift調(diào)用OC代碼
1.在Swift項(xiàng)目中創(chuàng)建OC文件時(shí)困介,Xcode會(huì)提示是否需要?jiǎng)?chuàng)建橋接文件大审,點(diǎn)擊創(chuàng)建橋接文件,會(huì)生成“工程名-Bridging-Header.h”文(也可手動(dòng)創(chuàng)建Header File座哩,命名為XXX-Bridging-Header.h徒扶,xxx為工程名稱)
2.配置.h文件位置:TARGETS->Build Settings->Swift Compiler->Objective-C Bridging Header,設(shè)置路徑如工程名為為Demo根穷,則此處可配置為:Demo/Demo-Bridging-Header.h姜骡。(前提Demo-Bridging-Header.h在Demo工程根目錄下)
3.在XXX-Bridging-Header.h文件中導(dǎo)入OC頭文件。如:#import "AFNetworking.h"
- OC調(diào)用Swift代碼
1.在OC項(xiàng)目中創(chuàng)建Swift文件時(shí)缠诅,Xcode會(huì)提示是否需要?jiǎng)?chuàng)建橋接文件溶浴,點(diǎn)擊創(chuàng)建橋接文件,會(huì)生成“工程名-Bridging-Header.h”文(也可手動(dòng)創(chuàng)建)
2.配置:TARGETS ->Build Settings -> Packaging ,設(shè)置Defines Module為YES管引,Product Module Name為工程名稱(默認(rèn)為工程的名字)
3.在OC需要用到Swift的文件中導(dǎo)入文件 "Product Module Name-Swift.h"士败, Product Module Name 默認(rèn)是工程的名字,直接導(dǎo)入#import "工程名-Swift.h"
(注意:導(dǎo)入的是XXX.Swift.h褥伴,而不是系統(tǒng)提示的XXX-Bridging-Header.h)
- 聲明特性
- 系統(tǒng)版本判斷
if #available(iOS 9.0, *) {
if let options = options as? [UIApplicationOpenURLOptionsKey : Any] {
if let sourceAppKey = options[.sourceApplication] {
sourceApplicationKey = (sourceAppKey as? String)!
}
}
} else {
// Fallback on earlier versions
if let options = options as? String {
if options.characters.count > 0 {
sourceApplicationKey = options
}
}
}
- 忽略函數(shù)返回值
@discardableResult
func test() -> Bool {
return false
}
- 某個(gè)聲明已經(jīng)被重命名
@available(*, unavailable, renamed:"MyRenamedProtocol")
typealias MyProtocol = MyRenamedProtocol
- 平臺(tái)可用性
@available(iOS 10.0, macOS 10.12, *)
class MyClass {
}
@available(iOS, introduced: 2.0, deprecated: 10.0, message: "Please use openURL:options:completionHandler: instead")
open func openURL(_ url: URL) -> Bool {}
- 使用OC方法調(diào)用
以下方法為Swift中定義的方法谅将,若想使用OC方法的命名方式定義,則使用@objc(參數(shù)個(gè)數(shù)需一直)重慢,如下:
@objc(beginLogPage:)
public class func beginLogPage(identifier: String) {
}
- 閉包弱引用
Unowned 還是 Weak饥臂?生命周期和性能對(duì)比
- unowned
- 原始實(shí)例永遠(yuǎn)不會(huì)為 nil,閉包可以直接使用它似踱,并且直接定義為顯式解包可選值隅熙。當(dāng)原始實(shí)例被析構(gòu)后,在閉包中使用這個(gè)捕獲值將導(dǎo)致崩潰核芽。
- 閉包和捕獲對(duì)象的生命周期相同囚戚,所以對(duì)象可以被訪問(wèn),也就意味著閉包也可以被訪問(wèn)轧简。外部對(duì)象和閉包有相同的生命周期驰坊,如 `[unowned self]`
- weak:
- 如果捕獲原始實(shí)例在使用過(guò)程中可能為 nil ,必須將引用聲明為 weak哮独, 并且在使用之前驗(yàn)證這個(gè)引用的有效性拳芙。
- 閉包的生命周期和捕獲對(duì)象的生命周期相互獨(dú)立察藐,當(dāng)對(duì)象不能再使用時(shí),閉包依然能夠被引用舟扎。在使用它之前驗(yàn)證一下它是否為 nil(請(qǐng)不要對(duì)它進(jìn)行強(qiáng)制解包).如:
[weak delegate = self.delegate!]
class aClass{
var value = 1
}
var c1 = aClass()
var c2 = aClass()
var fSpec = { [unowned c1, weak c2] in
c1.value += 1
if let c2 = c2 {
c2.value += 1
}
}
fSpec()
print(c1.value,c2.value) //Prints 2 and 2
- 判斷字符串是否包含另一字符串
if (strA.components(separatedBy: "strB").count)! > 1 {
println("包含")
} else {
println("不包含")
}
>= iOS iOS 8 NSString方法containsString
let str: String = "123test4"
if (str as NSString).contains("test") {
print("包含")
}
if str.contains("test") {
print("包含")
}
- 方法中修改可變字典分飞、數(shù)組等
var pageInfoDic = [String: AnyObject]()
setDic(origin: &pageInfoDic, value: pageInfo.pageIdentifier, key: "PID")
class func setDic(origin dic: inout [String: AnyObject], value: Any?, key: String) {
guard let value = value else {
return
}
if let value = value as? String {
if value == "" {
return
}
}
dic[key] = value as AnyObject?
}
- 解檔枚舉類型
public enum UserSex: Int {
case EGSexFemale = 0
case EGSexMale
case EGSexUnknown
}
public class EGUserInfo: NSObject,NSCoding {
public var userSex: UserSex = .EGSexUnknown
}
// MARK:- 歸檔及解檔
public func encode(with aCoder: NSCoder) {
aCoder.encode(userSex.rawValue, forKey: "userSex")
}
required public init?(coder aDecoder: NSCoder) {
super.init()
userSex = UserSex(rawValue: aDecoder.decodeInteger(forKey: "userSex"))!
}
- 擴(kuò)展通知,方便調(diào)用
方法1:
// 添加通知
NotificationCenter.default.addObserver(self, selector: #selector(enterForeground(notify:)), name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)
// 發(fā)送通知
NotificationCenter.default.post(name: NSNotification.Name("foreground"), object: nil)
方法2:
import Foundation
class TestDemo: NSObject {
func testDemo() {
// 添加通知
NotificationCenter.default.addObserver(self, selector: .foregroundNotify, name: NSNotification.Name.UIApplicationWillEnterForeground, object: nil)
}
// MARK: - 通知執(zhí)行方法
func enterForeground(notify: Notification) -> Void {
print("1111")
}
// MARK: - 析構(gòu)函數(shù)
deinit {
NotificationCenter.default.removeObserver(self)
}
}
// MARK: - Selector 擴(kuò)展
fileprivate extension Selector {
static let foregroundNotify = #selector(TestDemo.enterForeground(notify:))
}
- GCD
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0/*延遲時(shí)長(zhǎng)浆竭,單位秒*/) {
print("延遲1s執(zhí)行")
}
// 異步線程
DispatchQueue.global().async {
// 主線程
DispatchQueue.main.async {
}
}
- 只讀屬性
// 懶加載
lazy var names: NSArray = {
let names = NSArray()
print("只在首次訪問(wèn)輸出")
return names
}()
var appVersion: String {
if let version = Bundle.main.infoDictionary?["CFBundleShortVersionString"] {
return version as! String
}
return ""
}
- 可選類型類型轉(zhuǎn)換
var optionStr: String?
optionStr = "123"
// 1.拆包判斷
if let str = optionStr as? String {
print("string")
} else {
print("not string")
}
// 2.map
if let string = optionStr.map({ $0 as String }) {
print("map, string")
} else {
print("map, not string")
}
// 3.flatMap
if let string = optionStr.flatMap({ $0 as? String }) {
print("flatMap, string")
} else {
print("flatMap, not string")
}
// 類型嵌套及解包
class func savePolicy(info: AnyObject) {
if let policyInfo = info as? NSDictionary,
let policyDic = policyInfo["policy"] as? NSDictionary,
let failDic = policyDic["fail"] as? NSDictionary
{
}
}
- 處理不等長(zhǎng)的數(shù)組
let array2 = ["張三","李四","王五","趙六"]
let array1 = [0,1,2,3,4]
for (index, name) in zip(array1, array2) {
print(name)
print(array2[index])
}
for (model, viewController) in zip(models, viewControllers) {
viewController.model = model
}
- extension使用
extension UIView {
func with(backgroundColor: UIColor) -> Self {
self.backgroundColor = backgroundColor
return self
}
func with(cornerRadius: CGFloat) -> Self {
self.layer.cornerRadius = 3
return self
}
}
// 使用
override func viewDidLoad() {
super.viewDidLoad()
let view = UIView(frame: CGRect(x: 30, y: 30, width: 100, height: 100))
.with(backgroundColor: .blue)
.with(cornerRadius: 3)
self.view.addSubview(view)
}
- 代碼注釋
在OC中使用以下方式可對(duì)方法進(jìn)行分割分類
#pragma mark - 表示方法分割線
但在Swift中需使用以下方法
// MARK: - 表示方法分割線
其他方法
// FIXME: - 在注釋中用 FIXME 標(biāo)記某代碼是錯(cuò)誤的浸须,而且不能工作,需要及時(shí)糾正的情況邦泄。
// TODO: - 表示需要實(shí)現(xiàn)删窒,但目前還未實(shí)現(xiàn)的功能。
當(dāng)然FIXME和TODO若查找太麻煩顺囊,可以讓其在編譯時(shí)報(bào)警告肌索,提醒開發(fā)者,可能有問(wèn)題的地方特碳,方法如下:
工程 -> TARGETS -> Build Phases -> + -> New Run Script Phase诚亚,添加相應(yīng)腳本,內(nèi)容如下:
image.png
Swift腳本:
TAGS="TODO:|FIXME:"
echo "searching ${SRCROOT} for ${TAGS}"
find "${SRCROOT}" \( -name "*.swift" \) -print0 | xargs -0 egrep --with-filename --line-number --only-matching "($TAGS).*\$" | perl -p -e "s/($TAGS)/ warning: \$1/"
OC腳本:
KEYWORDS="TODO:|FIXME:|\?\?\?:|\!\!\!:"
find "${SRCROOT}" \( -name "*.h" -or -name "*.m" \) -print0 | xargs -0 egrep --with-filename --line-number --only-matching "($KEYWORDS).*\$" | perl -p -e "s/($KEYWORDS)/ warning: \$1/"
重新運(yùn)行工程后午乓,便會(huì)看到相應(yīng)的警告提示站宗,如下圖所示:
image.png
- Swift中數(shù)組中刪除子數(shù)組
在OC中NSMutableArray可以使用removeObjectsInArray:方法刪除子數(shù)組,但在Swift中沒(méi)有此方法益愈,只能將數(shù)組中需要剔除的對(duì)象挨個(gè)刪除
參考How to remove an array of objects from a Swift 2 Array - removeObjectsInArray
// Swift 2
var wordArray = ["Apple", "Carrot", "Peanut Butter"]
wordArray.append("Hummus")
wordArray.insert("Greek Salad", atIndex: 0)
// Find the objects to remove
var wordsToDelete: [String] = [String]()
for word in wordArray {
if word.lowercaseString.characters.contains("p") {
wordsToDelete.append(word)
}
}
// Find the index and remove each object
for word in wordsToDelete {
if let index = wordArray.indexOf(word) {
wordArray.removeAtIndex(index)
}
}
- 打印對(duì)象地址
在debug區(qū)域輸入:
fr v -R 對(duì)象名稱
結(jié)果如下:
(lldb) fr v -R a
(Swift.Array<Swift.Int>) a = {
_buffer = {
_storage = {
rawValue = 0x0000600000079500 {
Swift._ContiguousArrayStorageBase = {
Swift._SwiftNativeNSArrayWithContiguousStorage = {
Swift._SwiftNativeNSArray = {}
}
countAndCapacity = {
_storage = {
count = {
_value = 3
}
_capacityAndFlags = {
_value = 6
}
}
}
}
}
}
}
}
- Range使用
swift中Range<String.Index>非常麻煩梢灭,可以將String轉(zhuǎn)為NSString結(jié)合NSRange使用
let levels = "ABCDE"
let nsRange = NSMakeRange(1, 4)
let newString = (levels as NSString).replacingCharacters(in: nsRange, with: "AAAA")
print(newString)
- 數(shù)組遍歷
let arr: NSArray = [1, 2, 3, 4, 5]
for (index, num) in arr.enumerated() {
result += num as! Int
if index == 2 {
break
}
}
print(result)