Swift面試題

問題一:

下面代碼中變量 tutorial1.difficulty 和 tutorial2.difficulty 的值分別是什么? 如果 Tutorial 是一個類,會有什么不同嗎梳玫?為什么?

struct Tutorial {
  var difficulty: Int = 1
}

var tutorial1 = Tutorial()
var tutorial2 = tutorial1
tutorial2.difficulty = 2

回答:

tutorial1.difficulty 等于 1, tutorial2.difficulty 等于 2.
swift中的結(jié)構(gòu)體是值類型误算。是按值類型而不是引用類型復(fù)制值的喉脖。

創(chuàng)建了一個tutorial1的副本,并將其分配給tutorial2:

var tutorial2 = tutorial1
“ tutorial1 ”中未反映對“ tutorial12”的更改

如果 Tutorial 是一個類,那么 tutorial1 和 tutorial2 都等于 2.
swift中的類是引用類型酱虎。當(dāng)你更改Tutorial1的屬性時寨蹋,你將看到它反映在Tutorial2中松蒜,反之亦然缀雳。

問題二:

你用var聲明了view1僚纷,用let聲明了view2。有什么區(qū)別恢暖,最后一行會編譯通過嗎运褪?

import UIKit

var view1 = UIView()
view1.alpha = 0.5

let view2 = UIView()
view2.alpha = 0.5 // 此行是否編譯惊楼?

回答:

是的,最后一行可以編譯吐句。view1 是一個變量胁后,可以給它重新分配一個 UIView 類型的新實例。使用let嗦枢,只能分配一次值攀芯,因此不會編譯以下代碼:

view2 = view1 // Error: view2 is immutable

UIView是一個具有引用語義的類,因此你可以改變view2的屬性-這意味著最后一行將編譯:

let view2 = UIView()
view2.alpha = 0.5 // Yes!

問題三:

這段復(fù)雜的代碼按字母順序?qū)γQ數(shù)組進(jìn)行排序文虏。盡可能簡化閉包侣诺。

var animals = ["fish", "cat", "chicken", "dog"]
animals.sort { (one: String, two: String) -> Bool in
    return one < two
}
print(animals)

回答:

類型推斷系統(tǒng)會自動判斷閉包中參數(shù)的類型和返回類型,就可以去掉類型:

animals.sort { (one, two) -> Bool in
     return one < two
}

可以用$I符號替換參數(shù)名:

animals.sort { return $0 < $1 }

在單語句閉包中氧秘,可以省略返回關(guān)鍵字年鸳。最后一條語句的值將成為閉包的返回值:

animals.sort { $0 < $1 }

后,由于Swift知道數(shù)組的元素符合equatable丸相,因此可以簡單地編寫:

animals.sort(by: <)

問題四:

此代碼創(chuàng)建兩個類:Address 和 Person 搔确。然后它創(chuàng)建兩個 Person 實例來表示Ray和Brian。

class Address {
  var fullAddress: String
  var city: String
  
  init(fullAddress: String, city: String) {
    self.fullAddress = fullAddress
    self.city = city
  }
}

class Person {
  var name: String
  var address: Address

  init(name: String, address: Address) {
    self.name = name
    self.address = address
  }
}

var headquarters = Address(fullAddress: "123 Tutorial Street", city: "Appletown")
var ray = Person(name: "Ray", address: headquarters)
var brian = Person(name: "Brian", address: headquarters)

假設(shè)布 Brian 搬到街對面的新大樓灭忠,更新他的地址:

brian.address.fullAddress = "148 Tutorial Street"

它編譯,運(yùn)行時不會出錯膳算。如果你現(xiàn)在查一下 Ray 的地址,他也搬到了新大樓弛作。

print (ray.address.fullAddress)

這是怎么回事涕蜂?你如何解決這個問題?

回答:

Address 是一個類映琳,是引用類型机隙,不管是通過Ray還是Brian訪問蜘拉,都是相同的實例。更改 headquarters 地址將同時更改兩個人的地址有鹿。你能想象如果 Brian 收到Ray的郵件會發(fā)生什么情況嗎旭旭,反之亦然?

解決方案是創(chuàng)建一個新 Address 對象來分配給Brian印颤,或者將 Address 聲明為結(jié)構(gòu)體您机。

口述問題

什么是可選的,可選可以解決哪些問題年局?

使用可選類型(optionals)來處理值可能缺失的情況际看。在objective-c中,只有在使用nil特殊值的引用類型中才可以表示值缺失矢否。值類型(如int或float)不具有此功能仲闽。
Swift將缺乏值概念擴(kuò)展到引用類型和值類型〗├剩可選變量可以包含值或零赖欣,表示是否缺少值。

總結(jié)結(jié)構(gòu)體和類之間的主要區(qū)別验庙。

差異總結(jié)為:

類支持繼承顶吮;結(jié)構(gòu)不支持。
類是引用類型粪薛;結(jié)構(gòu)體是值類型悴了。
什么是通用類型,它們解決了什么問題违寿?

在swift中湃交,可以在函數(shù)和數(shù)據(jù)類型中使用泛型,例如在類藤巢、結(jié)構(gòu)體或枚舉中搞莺。
泛型解決了代碼重復(fù)的問題。當(dāng)有一個方法接受一種類型的參數(shù)時掂咒,通常會復(fù)制它以適應(yīng)不同類型的參數(shù)才沧。
例如,在下面的代碼中绍刮,第二個函數(shù)是第一個函數(shù)的“克隆”糜工,但它接受字符串而不是整數(shù)。

func areIntEqual(_ x: Int, _ y: Int) -> Bool {
  return x == y
}

func areStringsEqual(_ x: String, _ y: String) -> Bool {
  return x == y
}

areStringsEqual("ray", "ray") // true
areIntEqual(1, 1) // true

通過采用泛型录淡,可以將這兩個函數(shù)合并為一個函數(shù),同時保持類型安全油坝。下面是通用實現(xiàn):

func areTheyEqual<T: Equatable>(_ x: T, _ y: T) -> Bool {
  return x == y
}

areTheyEqual("ray", "ray")
areTheyEqual(1, 1)

由于在本例中測試的是相等性嫉戚,所以將參數(shù)限制為遵守 Equatable 協(xié)議的任何類型刨裆。此代碼實現(xiàn)了預(yù)期的結(jié)果,并防止傳遞不同類型的參數(shù)彬檀。

在某些情況下帆啃,你無法避免使用隱式展開的選項。什么時候窍帝?為什么努潘?

使用隱式展開選項的最常見原因是:

如果在實例化時無法初始化非本質(zhì)的屬性。
一個典型的例子是Interface Builder出口坤学,它總是在它的所有者之后初始化疯坤。在這種特定情況下 - 假設(shè)它在Interface Builder中正確配置 - 你在使用它之前保證outlet是非零的。
解決強(qiáng)引用循環(huán)問題深浮,即兩個實例相互引用并且需要對另一個實例的非空引用压怠。在這種情況下,將一側(cè)標(biāo)記為無主引用飞苇,而另一側(cè)使用隱式解包可選菌瘫。
打開可選項的各種方法有哪些?他們?nèi)绾卧u價安全性布卡?

var x : String? = "Test"

提示:有七種方法雨让。

強(qiáng)行打開 - 不安全。

let a: String = x!

隱式解包變量聲明 - 在許多情況下不安全忿等。

var a = x!

可選綁定 - 安全栖忠。

if let a = x {
  print("x was successfully unwrapped and is = \(a)")
}

可選鏈接 - 安全。

let a = x?.count

無合并操作員 - 安全这弧。

let a = x ?? ""

警衛(wèi)聲明 - 安全娃闲。

guard let a = x else {
  return
}

可選模式 - 安全。

if case let a? = x {
  print(a)
}

中級面試題

問題一:

nil 和 .none有什么區(qū)別?

沒有區(qū)別匾浪,因為Optional.none(簡稱.none)和nil是等價的皇帮。
實際上,下面的等式輸出為真:

nil == .none
使用nil更常見蛋辈,推薦使用属拾。

這是 thermometer 作為類和結(jié)構(gòu)的模型。編譯器在最后一行報錯冷溶。為什么編譯失斀グ住?

public class ThermometerClass {
  private(set) var temperature: Double = 0.0
  public func registerTemperature(_ temperature: Double) {
    self.temperature = temperature
  }
}

let thermometerClass = ThermometerClass()
thermometerClass.registerTemperature(56.0)

public struct ThermometerStruct {
  private(set) var temperature: Double = 0.0
  public mutating func registerTemperature(_ temperature: Double) {
    self.temperature = temperature
  }
}

let thermometerStruct = ThermometerStruct()
thermometerStruct.registerTemperature(56.0)

使用可變函數(shù)正確聲明ThermometerStruct以更改其內(nèi)部變量temperature逞频。編譯器報錯是因為你在通過 let 創(chuàng)建的實例上調(diào)用了registerTemperature纯衍,因為它是不可變的。將let改為var通過編譯苗胀。
對于結(jié)構(gòu)體襟诸,必須將內(nèi)部狀態(tài)更改為mutating的方法標(biāo)記瓦堵,但不能從不可變變量中調(diào)用它們。

這段代碼會打印什么歌亲?為什么菇用?

var thing = "cars"

let closure = { [thing] in
  print("I love \(thing)")
}

thing = "airplanes"

closure()

它會打印:I love cars陷揪。聲明閉包時惋鸥,捕獲列表會創(chuàng)建一個 thing 副本。這意味著即使為 thing 分配新值悍缠,捕獲的值也不會改變卦绣。

如果省略閉包中的捕獲列表,則編譯器使用引用而不是副本扮休。因此迎卤,當(dāng)調(diào)用閉包時,它會反映對變量的任何更改玷坠∥仙Γ可以在以下代碼中看到:

var thing = "cars"

let closure = {    
  print("I love \(thing)")
}

thing = "airplanes"

closure() // Prints: "I love airplanes"

問題四

這是一個全局函數(shù),用于計算數(shù)組中唯一值的數(shù)量:

func countUniques<T: Comparable>(_ array: Array<T>) -> Int {
  let sorted = array.sorted()
  let initial: (T?, Int) = (.none, 0)
  let reduced = sorted.reduce(initial) {
    ($1, $0.0 == $1 ? $0.1 : $0.1 + 1)
  }
  return reduced.1
}

它使用sorted方法八堡,因此它將T限制為符合Comparable協(xié)議的類型樟凄。
你這樣調(diào)用它:

countUniques([1, 2, 3, 3]) // result is 3

問題: 將此函數(shù)重寫為Array上的擴(kuò)展方法,以便你可以編寫如下內(nèi)容:

[1, 2, 3, 3].countUniques() // should print 3
你可以將全局countUniques(_ :)重寫為Array擴(kuò)展:

extension Array where Element: Comparable {
  func countUniques() -> Int {
    let sortedValues = sorted()
    let initial: (Element?, Int) = (.none, 0)
    let reduced = sortedValues.reduce(initial) { 
      ($1, $0.0 == $1 ? $0.1 : $0.1 + 1) 
    }
    return reduced.1
  }
}

請注意兄渺,僅當(dāng)泛型 Element 符合Comparable時缝龄,新方法才可用。

問題五

這是 divide 對象的兩個可選 Double 類型變量的方法挂谍。在執(zhí)行實際解析之前叔壤,有三個先決條件需要驗證:

變量 dividend 必須包含非空的值
變量 divisor 必須包含非空的值
變量 divisor 不能等于零

func divide(_ dividend: Double?, by divisor: Double?) -> Double? {
  if dividend == nil {
    return nil
  }
  if divisor == nil {
    return nil
  }
  if divisor == 0 {
    return nil
  }
  return dividend! / divisor!
}

使用guard語句并且不使用強(qiáng)制解包來改進(jìn)此功能。

func divide(_ dividend: Double?, by divisor: Double?) -> Double? {
    guard let dividend = dividend, let divisor = divisor, divisor != 0  else {
       return nil
    }
       return dividend / divisor
    }

問題六

使用 if let 重寫第五題

func divide(_ dividend: Double?, by divisor: Double?) -> Double? {
   if let dividend = dividend, let divisor = divisor, divisor != 0 {
      return dividend / divisor
   } else {
     return nil
   }
}

中級口述問題

第一題

在Objective-C中口叙,聲明一個這樣的常量:

const int number = 0;

Swift對應(yīng)的寫法:

let number = 0

const是在編譯時使用值或表達(dá)式初始化的變量炼绘,必須在編譯時解析。
使用let創(chuàng)建的不可變是在運(yùn)行時確定的常量妄田。你可以使用靜態(tài)或動態(tài)表達(dá)式對其進(jìn)行初始化俺亮。這允許聲明如下:

let higherNumber = number + 5

請注意,只能分配一次值疟呐。

第二題

聲明一個 static 修飾的屬性或函數(shù)脚曾,請在值類型上使用static修飾符。這是一個結(jié)構(gòu)的例子:你用 static 修飾值類型启具。這是一個結(jié)構(gòu)體的例子:

struct Sun {
  static func illuminate() {}
}

對于類本讥,可以使用static或class修飾符。他們實現(xiàn)了相同的目標(biāo),但方式不同囤踩。你能解釋一下它們有何不同旨椒?

static 使屬性或方法為靜態(tài)并不可重寫。使用class可以重寫屬性或方法堵漱。
應(yīng)用于類時,static將成為class final的別名涣仿。
例如勤庐,在此代碼中,當(dāng)你嘗試重寫 illuminate() 時好港,編譯器會抱錯:

class Star {
  class func spin() {}
  static func illuminate() {}
}
class Sun : Star {
  override class func spin() {
    super.spin()
  }
  // error: class method overrides a 'final' class method
  override static func illuminate() { 
    super.illuminate()
  }
}

問題三

你可以在 extension 里添加存儲屬性嗎愉镰?為什么行或不行呢?

不钧汹,這是不可能的丈探。你可以使用擴(kuò)展來向現(xiàn)有類型添加新行為,但不能更改類型本身或其接口拔莱。如果添加存儲的屬性碗降,則需要額外的內(nèi)存來存儲新值。擴(kuò)展程序無法管理此類任務(wù)塘秦。

問題四

Swift中的協(xié)議是什么讼渊?

協(xié)議是一種定義方法,屬性和其他要求藍(lán)圖的類型尊剔。然后爪幻,類,結(jié)構(gòu)或枚舉可以遵守協(xié)議來實現(xiàn)這些要求须误。
遵守協(xié)議需要實現(xiàn)該協(xié)議的要求挨稿。該協(xié)議本身不實現(xiàn)任何功能,而是定義功能京痢∧谈剩可以擴(kuò)展協(xié)議以提供某些要求的默認(rèn)實現(xiàn)或符合類型可以利用的其他功能。

高級書面問題

第一題

思考以下 thermometer 模型結(jié)構(gòu)體:

public struct Thermometer {
  public var temperature: Double
  public init(temperature: Double) {
    self.temperature = temperature
  }
}

可以使用以下代碼創(chuàng)建實例:

var t: Thermometer = Thermometer(temperature:56.8)

但以這種方式初始化它會更好:

var thermometer: Thermometer = 56.8

你可以嗎? 要怎么做?

Swift定義了一些協(xié)議历造,使你可以使用賦值運(yùn)算符初始化具有文字值的類型甩十。

采用相應(yīng)的協(xié)議并提供公共初始化器允許特定類型的文字初始化。在 Thermometer 的情況下吭产,實現(xiàn)ExpressibleByFloatLiteral如下:

extension Thermometer: ExpressibleByFloatLiteral {
  public init(floatLiteral value: FloatLiteralType) {
    self.init(temperature: value)
  }
}

現(xiàn)在侣监,可以使用float創(chuàng)建實例。

var thermometer: Thermometer = 56.8

轉(zhuǎn)自:http://www.reibang.com/p/744e5c3af37e

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末臣淤,一起剝皮案震驚了整個濱河市橄霉,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌邑蒋,老刑警劉巖姓蜂,帶你破解...
    沈念sama閱讀 206,126評論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件按厘,死亡現(xiàn)場離奇詭異,居然都是意外死亡钱慢,警方通過查閱死者的電腦和手機(jī)逮京,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,254評論 2 382
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來束莫,“玉大人懒棉,你說我怎么就攤上這事±缆蹋” “怎么了策严?”我有些...
    開封第一講書人閱讀 152,445評論 0 341
  • 文/不壞的土叔 我叫張陵,是天一觀的道長饿敲。 經(jīng)常有香客問我妻导,道長,這世上最難降的妖魔是什么怀各? 我笑而不...
    開封第一講書人閱讀 55,185評論 1 278
  • 正文 為了忘掉前任倔韭,我火速辦了婚禮,結(jié)果婚禮上渠啤,老公的妹妹穿的比我還像新娘狐肢。我一直安慰自己,他們只是感情好沥曹,可當(dāng)我...
    茶點故事閱讀 64,178評論 5 371
  • 文/花漫 我一把揭開白布份名。 她就那樣靜靜地躺著,像睡著了一般妓美。 火紅的嫁衣襯著肌膚如雪僵腺。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 48,970評論 1 284
  • 那天壶栋,我揣著相機(jī)與錄音辰如,去河邊找鬼。 笑死贵试,一個胖子當(dāng)著我的面吹牛琉兜,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播毙玻,決...
    沈念sama閱讀 38,276評論 3 399
  • 文/蒼蘭香墨 我猛地睜開眼豌蟋,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了桑滩?” 一聲冷哼從身側(cè)響起梧疲,我...
    開封第一講書人閱讀 36,927評論 0 259
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后幌氮,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體缭受,經(jīng)...
    沈念sama閱讀 43,400評論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 35,883評論 2 323
  • 正文 我和宋清朗相戀三年该互,在試婚紗的時候發(fā)現(xiàn)自己被綠了米者。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 37,997評論 1 333
  • 序言:一個原本活蹦亂跳的男人離奇死亡宇智,死狀恐怖塘雳,靈堂內(nèi)的尸體忽然破棺而出,到底是詐尸還是另有隱情普筹,我是刑警寧澤,帶...
    沈念sama閱讀 33,646評論 4 322
  • 正文 年R本政府宣布隘马,位于F島的核電站太防,受9級特大地震影響,放射性物質(zhì)發(fā)生泄漏酸员。R本人自食惡果不足惜蜒车,卻給世界環(huán)境...
    茶點故事閱讀 39,213評論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望幔嗦。 院中可真熱鬧酿愧,春花似錦、人聲如沸邀泉。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,204評論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽汇恤。三九已至庞钢,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間因谎,已是汗流浹背基括。 一陣腳步聲響...
    開封第一講書人閱讀 31,423評論 1 260
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留财岔,地道東北人风皿。 一個月前我還...
    沈念sama閱讀 45,423評論 2 352
  • 正文 我出身青樓,卻偏偏與公主長得像匠璧,于是被迫代替她去往敵國和親桐款。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 42,722評論 2 345

推薦閱讀更多精彩內(nèi)容