最近公司項目不怎麼忙, 閒暇時間把iOS 在面試中可能會遇到的問題整理了一番, 一部分題目是本身面試遇到的,一部分題目則是網上收錄的, 方便本身鞏固複習, 也分享給你們! 知識點比較多,比較雜,這裏作了分類,下面是分類連接地址;git
面試知識點整理 - 目錄:面試
iOS | 面試知識整理 - OC基礎 (一)
iOS | 面試知識整理 - OC基礎 (二)
iOS | 面試知識整理 - OC基礎 (三)
iOS | 面試知識整理 - UI 相 關 (四)
iOS | 面試知識整理 - 內存管理 (五)
iOS | 面試知識整理 - 多 線 程 (六)
iOS | 面試知識整理 - 網絡相關 (七)
iOS | 面試知識整理 - 數據持久化 (八)
iOS | 面試知識整理 - Swift 基礎 (九)編程
Swift
是蘋果在2014年6月WWDC發佈的全新編程語言,借鑑了JS,Python,C#,Ruby
等語言特性,看上去偏腳本化,Swift 仍支持 cocoa touch
框架swift
他的優勢:api
Swift 調用 OC代碼
須要建立一個 Target-BriBridging-Header.h
的橋文件,在喬文件導入須要調用的OC代碼頭文件便可數組
OC 調用 Swift代碼
直接導入 Target-Swift.h
文件便可, Swift若是須要被OC調用,須要使用@objc 對方法或者屬性進行修飾安全
在 Swift 中,class 是引用類型(指針類型), struct 是值類型bash
值類型微信
引用類型網絡
class 有如下功能,struct 是沒有的:
struct 優點:
var name: String? // 默認爲 nil
var age: Int? // 默認爲nil
print(name, age) // 打印 nil, nil
複製代碼
// 實現一個方法,能夠交換實現任意類型
func swap<T>(a: inout T, b: inout T) {
(a, b) = (b, a)
}
複製代碼
Swift 中有個5個級別的訪問控制權限,從高到低依次是 open, public, internal, fileprivate, private
它們遵循的基本規則: 高級別的變量不容許被定義爲低級別變量的成員變量,好比一個 private 的 class 內部容許包含 public的 String值,反之低級變量能夠定義在高級別變量中;
Swift 的內存管理機制同OC一致,都是ARC管理機制; Strong,和 Weak用法同OC同樣
Unowned(無主引用), 不會產生強引用,實例銷燬後仍然存儲着實例的內存地址(相似於OC中的unsafe_unretained), 試圖在實例銷燬後訪問無主引用,會產生運行時錯誤(野指針)
值類型(好比:struct),在複製時,複製對象與原對象實際上在內存中指向同一個對象,當且僅當修改複製的對象時,纔會在內存中建立一個新的對象,
屬性觀察是指在當前類型內對特性屬性進行監測,並做出響應,屬性觀察是 swift 中的特性,具備2種, willset
和 didset
var title: String {
willSet {
print("willSet", newValue)
}
didSet {
print("didSet", oldValue, title)
}
}
複製代碼
@objc
,而後在方法前面添加 optional
關鍵字,改方式其實是將協議轉爲了OC的方式@objc protocol someProtocol {
@objc optional func test()
}
複製代碼
protocol someProtocol {
func test()
}
extension someProtocol{
func test() {
print("test")
}
}
複製代碼
swift 的初始化方法,更加嚴格和準確, swift初始化方法須要保證全部的非optional
的成員變量都完成初始化, 同時 swfit 新增了convenience和 required
兩個修飾初始化器的關鍵字
自省在OC中就是判斷某一對象是否屬於某一個類的操做,有如下2中方式
[obj iskinOfClass:[SomeClass class]]
[obj isMemberOfClass:[SomeClass class]]
複製代碼
在 Swift 中因爲不少 class 並不是繼承自 NSObject, 故而 Swift 使用 is
來判斷是否屬於某一類型, is
不只能夠做用於class
, 仍是做用於enum
和struct
關聯值--有時會將枚舉的成員值跟其餘類型的變量關聯存儲在一塊兒,會很是有用
// 關聯值
enum Date {
case digit(year: Int, month: Int, day: Int)
case string(String)
}
複製代碼
原始值--枚舉成員可使用相同類型的默認值預先關聯,這個默認值叫作:原始值
// 原始值
enum Grade: String {
case perfect = "A"
case great = "B"
case good = "C"
case bad = "D"
}
複製代碼
{
(參數列表) -> 返回值類型 in 函數體代碼
}
複製代碼
// fn 就是一個尾隨閉包參數
func exec(v1: Int, v2: Int, fn: (Int, Int) -> Int) {
print(fn(v1, v2))
}
// 調用
exec(v1: 10, v2: 20) {
$0 + $1
}
複製代碼
當閉包做爲一個實際參數傳遞給一個函數或者變量的時候,咱們就說這個閉包逃逸了,能夠在形式參數前寫 @escaping
來明確閉包是容許逃逸的。
// 定義一個數組用於存儲閉包類型
var completionHandlers: [() -> Void] = []
// 在方法中將閉包當作實際參數,存儲到外部變量中
func someFunctionWithEscapingClosure(completionHandler: @escaping () -> Void) {
completionHandlers.append(completionHandler)
}
複製代碼
若是你不標記函數的形式參數爲 @escaping ,你就會遇到編譯時錯誤。
自動閉包是一種自動建立的用來把做爲實際參數傳遞給函數的表達式打包的閉包。它不接受任何實際參數,而且當它被調用時,它會返回內部打包的表達式的值。這個語法的好處在於經過寫普通表達式代替顯式閉包而使你省略包圍函數形式參數的括號。
func getFirstPositive(_ v1: Int, _ v2: @autoclosure () -> Int) -> Int? {
return v1 > 0 ? v1 : v2()
}
getFirstPositive(10, 20)
複製代碼
若是你想要自動閉包容許逃逸,就同時使用 @autoclosure 和 @escaping 標誌。
Swift中跟實例對象相關的屬性能夠分爲2大類
存儲屬性(Stored Property)
計算屬性(Computed Property)
struct Circle {
// 存儲屬性
var radius: Double
// 計算屬性
var diameter: Double {
set {
radius = newValue / 2
}
get {
return radius * 2
}
}
}
複製代碼
使用lazy能夠定義一個延遲存儲屬性,在第一次用到屬性的時候纔會進行初始化(相似OC中的懶加載)
class PhotoView {
// 延遲存儲屬性
lazy var image: Image = {
let url = "https://...x.png"
let data = Data(url: url)
return Image(data: data)
}()
}
複製代碼
能夠爲非lazy的var存儲屬性設置屬性觀察器,經過關鍵字willSet
和didSet
來監聽屬性變化
struct Circle {
var radius: Double {
willSet {
print("willSet", newValue)
}
didSet {
print("didSet", oldValue, radius)
}
}
init() {
self.radius = 1.0
print("Circle init!")
}
}
複製代碼
嚴格來講,屬性能夠分爲
實例屬性(Instance Property): 只能經過實例對象去訪問
類型屬性(Type Property):只能經過類型去訪問
能夠經過static定義類型屬性 p若是是類,也能夠用關鍵字class
struct Car {
static var count: Int = 0
init() {
Car.count += 1
}
}
複製代碼
不一樣於存儲實例屬性,你必須給存儲類型屬性設定初始值
存儲類型屬性默認就是lazy,會在第一次使用的時候才初始化
枚舉類型也能夠定義類型屬性(存儲類型屬性、計算類型屬性)
能夠經過類型屬性+let+private
來寫單例; 代碼以下以下:
public class FileManager {
public static let shared = {
// ....
// ....
return FileManager()
}()
private init() { }
}
複製代碼
使用以下:
class Point {
var x = 0.0, y = 0.0
subscript(index: Int) -> Double {
set {
if index == 0 {
x = newValue
} else if index == 1 {
y = newValue }
}
get {
if index == 0 {
return x
} else if index == 1 {
return y
}
return 0
}
}
}
var p = Point()
// 下標賦值
p[0] = 11.1
p[1] = 22.2
// 下標訪問
print(p.x) // 11.1
print(p.y) // 22.2
複製代碼
指定初始化器(designated initializer)
、便捷初始化器(convenience initializer)
// 指定初始化器
init(parameters) {
statements
}
// 便捷初始化器
convenience init(parameters) {
statements
}
複製代碼
規則:
初始化器的相互調用規則
可選鏈是一個調用和查詢可選屬性、方法和下標的過程,它可能爲 nil 。若是可選項包含值,屬性、方法或者下標的調用成功;若是可選項是 nil ,屬性、方法或者下標的調用會返回 nil 。多個查詢能夠連接在一塊兒,若是鏈中任何一個節點是 nil ,那麼整個鏈就會得體地失敗。
類、結構體、枚舉能夠爲現有的運算符提供自定義的實現,這個操做叫作:運算符重載
struct Point {
var x: Int
var y: Int
// 重載運算符
static func + (p1: Point, p2: Point) -> Point {
return Point(x: p1.x + p2.x, y: p1.y + p2.y)
}
}
var p1 = Point(x: 10, y: 10)
var p2 = Point(x: 20, y: 20)
var p3 = p1 + p2複製代碼
其實呢做爲一個開發者,有一個學習的氛圍跟一個交流圈子特別重要,這是個人微信 你們有興趣能夠添加 邀請小夥伴們進入微信羣裏一塊兒 交流(想要加羣的能夠直接點擊此處進交流羣 來一塊兒交)