GitHub Repo:coderZsq.target.swift
Follow: coderZsq · GitHub
Resume: coderzsq.github.io/coderZsq.we…前端
從去年開始, 我就一直有嘗試的面試些大公司
, 由於對於一個半路出家
(非計算機專業), 靠着MJ視頻
入門的iOS菜雞玩家
, 通過了3年
的摸爬滾打, 終於也漸漸的能夠作一些簡單的前端
, 後端
, 移動端
的交互, 但想要繼續深刻就感受瓶頸
愈加的明顯, 基礎的薄弱
致使很難上升, 因此可以進入一家大型成熟
互聯網公司就成爲了我最近的目標, 緣由很簡單, 這是最爲有效
的學習成長的方式.webpack
去年7月
, 第一次面試大公司: 餓了麼
, 收到大公司的召喚很是的興奮, 以爲本身翻身的機會終於要來了, 興沖沖的跑去面試, 覺得會和通常初級iOS
面試的題目相同, 沒有作任何的準備, 其實也不知道準備什麼, 記得那時候聊的是:git
如何避免卡頓掉幀
, 異步渲染
.性能優化
, Vsync
, CPU / GPU
緩存策略
.lild重簽名
, Mach-O
.DOM
重繪.負載均衡
的處理.還有一些極端的狀況, 因爲時間久遠已經記不太清了, 反正此次面試給個人感受就是, 靠... 我簡直就是個垃圾啊~ 當時記得內推個人架構師建議我紮實一下iOS的基本功
, 而後就推薦了基本書: 計算機網絡
, 操做系統原理
, HTTP權威指南
, TCP/IP權威指南
, 深刻解析Max OS X & iOS 操做系統
... 這些書, 除了HTTP權威指南
我咬着牙看完了, 其餘的對於我來講簡直就是天書, 根本消化不良啊.github
去年12月
, 第二次面試大公司: 京東
, 因爲有了上一次的經驗, 我變得很是的淡定, 知道本身確定會被大公司所淘汰, 和優等專業生
有着不可逾越
的天塹
, 比較吃驚的是, 進入京東的大樓須要用身份證
換取臨時門禁
... 那時候的面試題就比餓了麼的柔和的多了, 雖然當時仍是回答不出.web
isa
, 消息轉發
, 弱引用表
.mode
, timer
.__block
, __forwording
.assign
, weak
, copy
.assoc
, load
如今想一想, 這TM纔是面試iOS
啊, 只惋惜, 那時候並不具有這些知識, 惋惜了了. 以後我就對C++
, ASM
, Linux
, 這三方面進行了學習, 也學習了些MACH-O
, 逆向
的相關的知識, 以備後面的面試機會.面試
第三次就是這週三
面試第二梯隊
了, 我準備了全部我可以準備的面試題內容, 底層原理
, 逆向安全
, 多線程與鎖
, 內存佈局
, UI性能優化
等, 果不其然, 足足1個小時
的電話面試, 我輕鬆經過, 問的就是些我準備好的底層知識
, 讓我以爲機會終於來了, 但是.... 當我現場面試後... 題目所有是上機題...算法
Promise
的自實現.UIControl
實現UIButton
....果真,網絡
, UI
, 算法
... 好吧, 第一次作上機題, 瞬間就蒙了... 而後就是面試官在旁邊不停的笑... 不停的笑... 多是他對我友好的一種方式吧... 最後的面試結論是, 個人知識面
仍是比較廣
的, 作過的東西
也是挺多
的, 可是在知識深度
方面仍是比較欠缺.swift
後來得知, 他們招聘的是技術專家
的職級, 以爲個人技術水平達不到要求, 不能給與錄取, 固然被拒我是當場就知道了, 也以爲美團
和餓了麼
的兩次面試經歷都和個人水平相差甚遠... 但是, 我只是想進入大公司學習, 就必定要成爲專家
才行麼? 如今初中高級
, 資深
都不須要了, 直接專家麼..., 個人獵頭朋友和我說, 3-1
的級別就是對標阿里P6/P7
, 我選擇去死啊.....後端
有了此次的面試經驗後, 個人策略也發生了改變, 再也不追求大公司的光環了, 作人開心一點
很差麼, 非要像機器同樣思考
? 活的像個算法
同樣是否是感受缺乏了些重要的東西? 和朋友們吹吹牛逼
的日子不快活麼, 偏要用功學習? 這裏想到了最近聽到的兩句話, 最好的產品體驗就是要讓用戶不用思考
, 認知即痛苦, 無知即極樂
, 人真是矛盾, 價值觀的一念之差, 差之毫釐失之千里啊....設計模式
這道題目上機的時候很是的蒙, 由於冪是double
, 徹底不知道如何下手, 面試官就下降難度使用整型.
func _pow_1(_ base: Int, _ exponent: Int) -> Int {
if exponent < 0 {
return 0
}
if exponent == 0 {
return 0
}
if exponent == 1 {
return base
}
var result = base
for _ in 1..<exponent {
result *= base
}
return result
}
複製代碼
而後, 第一次作算法題的我, 只能想到經過最爲粗糙的辦法解答, 就是一個循環, 我也知道這不是面試官所期許的答案, 但這有什麼辦法呢...
func _pow_2(_ base: Double, _ exponent: Int) -> Double {
if exponent < 0 {
return 0
}
if exponent == 0 {
return 0
}
var ans:Double = 1, last_pow = base, exp = exponent
while exp > 0 {
if (exp & 1) != 0 {
ans = ans * last_pow
}
exp = exp >> 1
last_pow = last_pow * last_pow
}
return ans
}
複製代碼
這個是我在網上翻閱資料後的另外一種看似比較好的解答方式.
func _pow_3(_ base: Double, _ exponent: Int) -> Double {
var isNegative = false
var exp = exponent
if exp < 0 {
isNegative = true
exp = -exp
}
let result = _pow_2(base, exp)
return isNegative ? 1 / result : result
}
複製代碼
這個僅僅是加了一個負值判斷.... 可是冪是double
的仍然是毫無頭緒, 須要請大佬和大神不吝賜教
.
這是一道LeetCode的原題, 可是我至今尚未刷過算法題庫... 也是生平第一次面試的時候遇到算法題. 題目的意思是找到兩個排序數組的中位數.
func findMedianSortedArrays_1(_ array1: [Int], _ array2: [Int]) -> Double {
var array = [Int]()
array.append(contentsOf: array1)
array.append(contentsOf: array2)
quickSort(list: &array)
let b = array.count % 2
let c = array.count
var result = 0.0;
if b == 1 {
result = Double(array[c / 2])
} else {
let n1 = array[c / 2 - 1]
let n2 = array[c / 2]
result = Double((n1 + n2)) / 2.0
}
return result
}
複製代碼
第一次作算法題, 只能無視算法複雜度, 可以完成就算是不錯了, 要什麼自行車...
func findMedianSortedArrays_2(_ array1: [Int], _ array2: [Int]) -> Double {
let c1 = array1.count, c2 = array2.count
var a1 = array1, a2 = array2
if c1 <= 0 && c2 <= 0 {
return 0.0
}
func findKth(_ nums1: inout [Int], i: Int, _ nums2: inout [Int], j: Int, k: Int) -> Double {
if nums1.count - i > nums2.count - j {
return findKth(&nums2, i: j, &nums1, j: i, k: k)
}
if nums1.count == i {
return Double(nums2[j + k - 1])
}
if k == 1 {
return Double(min(nums1[i], nums2[j]))
}
let pa = min(i + k / 2, nums1.count), pb = j + k - pa + i
if nums1[pa - 1] < nums2[pb - 1] {
return findKth(&nums1, i: pa, &nums2, j: j, k: k - pa + i)
} else if nums1[pa - 1] > nums2[pb - 1] {
return findKth(&nums1, i: i, &nums2, j: pb, k: k - pb + j)
} else {
return Double(nums1[pa - 1])
}
}
let total = c1 + c2
if total % 2 == 1 {
return findKth(&a1, i: 0, &a2, j: 0, k: total / 2 + 1)
} else {
return (findKth(&a1, i: 0, &a2, j: 0, k: total / 2) + findKth(&a1, i: 0, &a2, j: 0, k: total / 2 + 1)) / 2.0
}
}
複製代碼
這個是我在網上查資料的時候的答案... 還沒理清是個什麼思路, 反正面試官提示分而治之, 掐頭去尾... 也不知道是否是最優算法.
func findMedianSortedArrays_3(_ array1: [Int], _ array2: [Int]) -> Double {
let total = array1.count + array2.count
let index = total / 2
let count = array1.count < array2.count ? array2.count : array1.count
var array = [Int]()
var i = 0, j = 0;
for _ in 0...count {
if array.count >= index + 1 {
break
}
if array1[i] < array2[j] {
array.append(array1[i])
i += 1
} else {
array.append(array2[j])
j += 1
}
}
return total % 2 == 1 ? Double(array[index]) : Double(array[index] + array[index - 1]) * 0.5
}
複製代碼
這個是請教霜神(@halfrost-一縷殤流化隱半邊冰霜)後給的思路, 的確很好實現. 但霜神謙虛的說不是最優解....
var array1 = randomList(1000001)
var array2 = randomList(1000000)
quickSort(list: &array1)
quickSort(list: &array2)
print(findMedianSortedArrays_1(array1, array2))
print(findMedianSortedArrays_2(array1, array2))
print(findMedianSortedArrays_3(array1, array2))
複製代碼
--- scope of: findMedianSortedArrays ---
500045.0
500045.0
500045.0
複製代碼
var array1 = randomList(1000001)
var array2 = randomList(1000000)
quickSort(list: &array1)
quickSort(list: &array2)
print(findMedianSortedArrays_1(array1, array2))
print(findMedianSortedArrays_2(array1, array2))
print(findMedianSortedArrays_3(array1, array2))
複製代碼
--- scope of: findMedianSortedArrays ---
499665.5
499665.5
499665.5
複製代碼
--- scope of: findMedianSortedArrays_1 ---
timing: 2.50845623016357
--- scope of: findMedianSortedArrays_2 ---
timing: 1.28746032714844e-05
--- scope of: findMedianSortedArrays_3 ---
timing: 0.0358490943908691
複製代碼
能夠看出網上查資料的答案是三種解法裏性能最高的算法, 霜神的思路和網上的答案差了三個數量級, 而我寫的差了五個數量級.... 果真我寫的果真是最爲垃圾的算法....
@discardableResult func findMedianSortedArrays_4(_ array1: [Int], _ array2: [Int]) -> Double {
if array1.count == 0 {
if array2.count % 2 == 1 {
return Double(array2[array2.count / 2])
} else {
return Double(array2[array2.count / 2] + array2[array2.count / 2 - 1]) * 0.5
}
} else if array2.count == 0 {
if array1.count % 2 == 1 {
return Double(array1[array1.count / 2])
} else {
return Double(array1[array1.count / 2] + array1[array1.count / 2 - 1]) * 0.5
}
}
let total = array1.count + array2.count
let count = array1.count < array2.count ? array1.count : array2.count
let odd = total % 2 == 1
var i = 0, j = 0, f = 1, m1 = 0.0, m2 = 0.0, result = 0.0;
for _ in 0...count {
if odd { array1[i] < array2[j] ? (i += 1) : (j += 1) }
if f >= total / 2 {
if odd {
result = array1[i] < array2[j] ? Double(array1[i]) : Double(array2[j])
} else {
if array1[i] < array2[j] {
m1 = Double(array1[i])
if (i + 1) < array1.count && array1[i + 1] < array2[j] {
m2 = Double(array1[i + 1])
} else {
m2 = Double(array2[j])
}
} else {
m1 = Double(array2[j])
if (j + 1) < array2.count && array2[j + 1] < array1[i] {
m2 = Double(array2[j + 1])
} else {
m2 = Double(array1[i])
}
}
result = (m1 + m2) * 0.5
}
break
}
if !odd { array1[i] < array2[j] ? (i += 1) : (j += 1) }
f += 1
}
return result
}
複製代碼
--- scope of: findMedianSortedArrays_3 ---
timing: 0.0358932018280029
--- scope of: findMedianSortedArrays_4 ---
timing: 0.0241639614105225
複製代碼
沿着霜神的思路和麪試官給的提示, 給出了上面的算法, 可是解法3
的數量級是相同的
protocol ButtonInterface {
func setTitle(_ title: String);
func setTitleColor(_ titleColor: UIColor);
func setTitleEdgeInsets(_ edgeInsets: UIEdgeInsets);
func setImage(_ image: UIImage);
func setBackgroundImage(_ image: UIImage);
func setImageEdgeInsets(_ edgeInsets: UIEdgeInsets);
}
class Button: UIControl, ButtonInterface {
}
複製代碼
以上就是面試時候的原題, 一開始根本不知道是要讓我作些什麼, 說是隻要讓我把上面的方法所有實現就行了, 就像實現一個本身的UIButton... 一開始, 我覺得是要我用CALayer
來實現, 嚇的我瑟瑟發抖... 還好不是... 而後, 我就按照本身平時自定義控件的寫法, 寫了一個UIImageView
, 一個UILabel
, 而後佈局賦值... 就看到面試官對着我笑着說, 你覺得這道題這麼簡單麼... 這麼簡單麼...
而後說, 你知道UIButton setTitle
的時候纔會建立UILabel
, setImage
的時候纔會建立UIImageView
, 你爲何吧frame
給寫死... 不知道UIView
有sizeToFit
麼, 你怎麼不實現sizeThatFits
, 你是徹底不會用吧... 你知道UIButton
用AutoLayout
佈局的時候只要設置origin
座標, 寬高就能夠自適應了, 你自定義的時候怎麼不實現呢? setBackgroundImage
和setImageEdgeInsets
你就不要作了吧, 反正你也不會...
我想說的是,誰沒事放着UIButton
不用, 用UIContorl
這種東西... 就爲了一個target-action
的設計模式麼... 我每次在想思路的時候一直打斷我, 可能這是面試官的一種策略吧... 算了不吐槽了, 仍是盡力實現吧.
import UIKit
protocol ButtonInterface {
func setTitle(_ title: String);
func setTitleColor(_ titleColor: UIColor);
func setTitleEdgeInsets(_ edgeInsets: UIEdgeInsets);
func setImage(_ image: UIImage);
func setBackgroundImage(_ image: UIImage);
func setImageEdgeInsets(_ edgeInsets: UIEdgeInsets);
}
class Button: UIControl, ButtonInterface {
lazy var titleLabel: UILabel = UILabel()
lazy var imageView: UIImageView = UIImageView()
lazy var backgroundImageView: UIImageView = UIImageView()
var titleLabelIsCreated = false
var imageViewIsCreated = false
var backgroundImageViewCreated = false
internal func setTitle(_ text: String) {
if !titleLabelIsCreated {
addSubview(titleLabel)
titleLabelIsCreated = true
}
titleLabel.text = text
}
internal func setTitleColor(_ textColor: UIColor) {
if !titleLabelIsCreated {
return
}
titleLabel.textColor = textColor
}
internal func setTitleEdgeInsets(_ edgeInsets: UIEdgeInsets) {
if !titleLabelIsCreated {
return
}
}
internal func setImage(_ image: UIImage) {
if !imageViewIsCreated {
addSubview(imageView)
imageViewIsCreated = true
}
imageView.image = image
}
internal func setBackgroundImage(_ image: UIImage) {
if !backgroundImageViewCreated {
addSubview(backgroundImageView)
insertSubview(backgroundImageView, at: 0)
backgroundImageViewCreated = true
}
backgroundImageView.image = image
}
internal func setImageEdgeInsets(_ edgeInsets: UIEdgeInsets) {
if !imageViewIsCreated {
return
}
}
override func sizeThatFits(_ size: CGSize) -> CGSize {
if titleLabelIsCreated && !imageViewIsCreated && !backgroundImageViewCreated {
let text: NSString? = titleLabel.text as NSString?
let titleLabelW: CGFloat = text?.boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: bounds.height), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.width ?? 0.0
let titleLabelH: CGFloat = text?.boundingRect(with: CGSize(width: titleLabelW, height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.height ?? 0.0
return CGSize(width: titleLabelW, height: titleLabelH + 10)
} else if !titleLabelIsCreated && imageViewIsCreated {
return imageView.image?.size ?? CGSize.zero
} else if titleLabelIsCreated && imageViewIsCreated {
let text: NSString? = titleLabel.text as NSString?
let titleLabelW: CGFloat = text?.boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: bounds.height), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.width ?? 0.0
let titleLabelH: CGFloat = text?.boundingRect(with: CGSize(width: titleLabelW, height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.height ?? 0.0
let imageViewW: CGFloat = imageView.image?.size.width ?? 0.0
let imageViewH: CGFloat = imageView.image?.size.height ?? 0.0
return CGSize(width: titleLabelW + imageViewW, height: imageViewH > titleLabelH ? imageViewH : titleLabelH)
} else {
return backgroundImageView.image?.size ?? CGSize.zero
}
}
override func layoutSubviews() {
super.layoutSubviews()
if titleLabelIsCreated && !imageViewIsCreated {
titleLabel.frame = bounds
titleLabel.textAlignment = .center
} else if !titleLabelIsCreated && imageViewIsCreated {
let y: CGFloat = 0;
let width: CGFloat = imageView.image?.size.width ?? 0;
let x: CGFloat = (bounds.width - width) * 0.5;
let height: CGFloat = bounds.height;
imageView.frame = CGRect(x: x, y: y, width: width, height: height)
} else if titleLabelIsCreated && imageViewIsCreated {
let imageViewY: CGFloat = 0;
let imageViewW: CGFloat = imageView.image?.size.width ?? 0;
let imageViewH: CGFloat = bounds.height;
let text: NSString? = titleLabel.text as NSString?
let titleLabelW: CGFloat = text?.boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: bounds.height), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.width ?? 0.0
let titleLabelH: CGFloat = text?.boundingRect(with: CGSize(width: titleLabelW, height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.height ?? 0.0
let imageViewX: CGFloat = (bounds.width - imageViewW - titleLabelW) * 0.5;
let titleLabelX: CGFloat = imageViewX + imageViewW
let titleLabelY = (bounds.height - titleLabelH) * 0.5
titleLabel.frame = CGRect(x: titleLabelX, y: titleLabelY, width: titleLabelW, height: titleLabelH)
imageView.frame = CGRect(x: imageViewX, y: imageViewY, width: imageViewW, height: imageViewH)
}
if backgroundImageViewCreated {
backgroundImageView.frame = bounds
}
}
}
複製代碼
雖然實現了部分的功能, 可是AutoLayout
和EdgeInsets
的功能仍是沒有思路, 還請各位大佬解惑.
咱們用本身自實現的Button
和UIButton
進行對比.
class ViewController: UIViewController {
override func loadView() {
super.loadView();
let uibutton = UIButton()
uibutton.layer.borderWidth = 1
uibutton.layer.borderColor = UIColor.black.cgColor
uibutton.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 40)
uibutton.setTitle("github.com/coderZsq", for: .normal)
uibutton.setTitleColor(.red, for: .normal)
uibutton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
uibutton.setImage(UIImage(named: "avatar"), for: .normal)
uibutton.setBackgroundImage(UIImage(named: "avatar"), for: .normal)
uibutton.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10)
view.addSubview(uibutton)
uibutton.sizeToFit()
let button = Button()
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
button.frame = CGRect(x: 0, y: 350, width: view.bounds.width, height: 40)
button.setTitle("github.com/coderZsq")
button.setTitleColor(.red)
button.setTitleEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
button.setImage(UIImage(named: "avatar") ?? UIImage());
button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
button.setImageEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
view.addSubview(button)
button.sizeToFit()
}
}
複製代碼
let uibutton = UIButton()
uibutton.layer.borderWidth = 1
uibutton.layer.borderColor = UIColor.black.cgColor
uibutton.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 40)
// uibutton.setTitle("github.com/coderZsq", for: .normal)
// uibutton.setTitleColor(.red, for: .normal)
// uibutton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
// uibutton.setImage(UIImage(named: "avatar"), for: .normal)
// uibutton.setBackgroundImage(UIImage(named: "avatar"), for: .normal)
// uibutton.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10)
view.addSubview(uibutton)
// uibutton.sizeToFit()
let button = Button()
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
button.frame = CGRect(x: 0, y: 350, width: view.bounds.width, height: 40)
// button.setTitle("github.com/coderZsq")
// button.setTitleColor(.red)
// button.setTitleEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
// button.setImage(UIImage(named: "avatar") ?? UIImage());
// button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
// button.setImageEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
view.addSubview(button)
// button.sizeToFit()
複製代碼
let uibutton = UIButton()
uibutton.layer.borderWidth = 1
uibutton.layer.borderColor = UIColor.black.cgColor
uibutton.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 40)
uibutton.setTitle("github.com/coderZsq", for: .normal)
uibutton.setTitleColor(.red, for: .normal)
// uibutton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
// uibutton.setImage(UIImage(named: "avatar"), for: .normal)
// uibutton.setBackgroundImage(UIImage(named: "avatar"), for: .normal)
// uibutton.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10)
view.addSubview(uibutton)
// uibutton.sizeToFit()
let button = Button()
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
button.frame = CGRect(x: 0, y: 350, width: view.bounds.width, height: 40)
button.setTitle("github.com/coderZsq")
button.setTitleColor(.red)
// button.setTitleEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
// button.setImage(UIImage(named: "avatar") ?? UIImage());
// button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
// button.setImageEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
view.addSubview(button)
// button.sizeToFit()
}
複製代碼
let uibutton = UIButton()
uibutton.layer.borderWidth = 1
uibutton.layer.borderColor = UIColor.black.cgColor
uibutton.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 40)
uibutton.setTitle("github.com/coderZsq", for: .normal)
uibutton.setTitleColor(.red, for: .normal)
// uibutton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
// uibutton.setImage(UIImage(named: "avatar"), for: .normal)
// uibutton.setBackgroundImage(UIImage(named: "avatar"), for: .normal)
// uibutton.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10)
view.addSubview(uibutton)
uibutton.sizeToFit()
let button = Button()
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
button.frame = CGRect(x: 0, y: 350, width: view.bounds.width, height: 40)
button.setTitle("github.com/coderZsq")
button.setTitleColor(.red)
// button.setTitleEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
// button.setImage(UIImage(named: "avatar") ?? UIImage());
// button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
// button.setImageEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
view.addSubview(button)
button.sizeToFit()
複製代碼
let uibutton = UIButton()
uibutton.layer.borderWidth = 1
uibutton.layer.borderColor = UIColor.black.cgColor
uibutton.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 40)
// uibutton.setTitle("github.com/coderZsq", for: .normal)
// uibutton.setTitleColor(.red, for: .normal)
// uibutton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
uibutton.setImage(UIImage(named: "avatar"), for: .normal)
// uibutton.setBackgroundImage(UIImage(named: "avatar"), for: .normal)
// uibutton.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10)
view.addSubview(uibutton)
// uibutton.sizeToFit()
let button = Button()
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
button.frame = CGRect(x: 0, y: 350, width: view.bounds.width, height: 40)
// button.setTitle("github.com/coderZsq")
// button.setTitleColor(.red)
// button.setTitleEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
button.setImage(UIImage(named: "avatar") ?? UIImage());
// button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
// button.setImageEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
view.addSubview(button)
// button.sizeToFit()
複製代碼
let uibutton = UIButton()
uibutton.layer.borderWidth = 1
uibutton.layer.borderColor = UIColor.black.cgColor
uibutton.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 40)
// uibutton.setTitle("github.com/coderZsq", for: .normal)
// uibutton.setTitleColor(.red, for: .normal)
// uibutton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
uibutton.setImage(UIImage(named: "avatar"), for: .normal)
// uibutton.setBackgroundImage(UIImage(named: "avatar"), for: .normal)
// uibutton.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10)
view.addSubview(uibutton)
uibutton.sizeToFit()
let button = Button()
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
button.frame = CGRect(x: 0, y: 350, width: view.bounds.width, height: 40)
// button.setTitle("github.com/coderZsq")
// button.setTitleColor(.red)
// button.setTitleEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
button.setImage(UIImage(named: "avatar") ?? UIImage());
// button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
// button.setImageEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
view.addSubview(button)
button.sizeToFit()
複製代碼
let uibutton = UIButton()
uibutton.layer.borderWidth = 1
uibutton.layer.borderColor = UIColor.black.cgColor
uibutton.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 40)
// uibutton.setTitle("github.com/coderZsq", for: .normal)
// uibutton.setTitleColor(.red, for: .normal)
// uibutton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
// uibutton.setImage(UIImage(named: "avatar"), for: .normal)
uibutton.setBackgroundImage(UIImage(named: "avatar"), for: .normal)
// uibutton.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10)
view.addSubview(uibutton)
// uibutton.sizeToFit()
let button = Button()
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
button.frame = CGRect(x: 0, y: 350, width: view.bounds.width, height: 40)
// button.setTitle("github.com/coderZsq")
// button.setTitleColor(.red)
// button.setTitleEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
// button.setImage(UIImage(named: "avatar") ?? UIImage());
button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
// button.setImageEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
view.addSubview(button)
// button.sizeToFit()
複製代碼
這裏, 咱們看到和系統的實現不同, 由於我直接在渲染(display
)設置了bitmap
, 而不是像系統添加了一個新的view
. 這樣的性能消耗會少些... (以修改 爲了下面的問題)
let uibutton = UIButton()
uibutton.layer.borderWidth = 1
uibutton.layer.borderColor = UIColor.black.cgColor
uibutton.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 40)
// uibutton.setTitle("github.com/coderZsq", for: .normal)
// uibutton.setTitleColor(.red, for: .normal)
// uibutton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
// uibutton.setImage(UIImage(named: "avatar"), for: .normal)
uibutton.setBackgroundImage(UIImage(named: "avatar"), for: .normal)
// uibutton.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10)
view.addSubview(uibutton)
uibutton.sizeToFit()
let button = Button()
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
button.frame = CGRect(x: 0, y: 350, width: view.bounds.width, height: 40)
// button.setTitle("github.com/coderZsq")
// button.setTitleColor(.red)
// button.setTitleEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
// button.setImage(UIImage(named: "avatar") ?? UIImage());
button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
// button.setImageEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
view.addSubview(button)
button.sizeToFit()
複製代碼
let uibutton = UIButton()
uibutton.layer.borderWidth = 1
uibutton.layer.borderColor = UIColor.black.cgColor
uibutton.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 40)
uibutton.setTitle("github.com/coderZsq", for: .normal)
uibutton.setTitleColor(.red, for: .normal)
// uibutton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
uibutton.setImage(UIImage(named: "avatar"), for: .normal)
// uibutton.setBackgroundImage(UIImage(named: "avatar"), for: .normal)
// uibutton.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10)
view.addSubview(uibutton)
// uibutton.sizeToFit()
let button = Button()
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
button.frame = CGRect(x: 0, y: 350, width: view.bounds.width, height: 40)
button.setTitle("github.com/coderZsq")
button.setTitleColor(.red)
// button.setTitleEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
button.setImage(UIImage(named: "avatar") ?? UIImage());
// button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
// button.setImageEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
view.addSubview(button)
// button.sizeToFit()
複製代碼
let uibutton = UIButton()
uibutton.layer.borderWidth = 1
uibutton.layer.borderColor = UIColor.black.cgColor
uibutton.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 40)
uibutton.setTitle("github.com/coderZsq", for: .normal)
uibutton.setTitleColor(.red, for: .normal)
// uibutton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
uibutton.setImage(UIImage(named: "avatar"), for: .normal)
// uibutton.setBackgroundImage(UIImage(named: "avatar"), for: .normal)
// uibutton.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10)
view.addSubview(uibutton)
uibutton.sizeToFit()
let button = Button()
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
button.frame = CGRect(x: 0, y: 350, width: view.bounds.width, height: 40)
button.setTitle("github.com/coderZsq")
button.setTitleColor(.red)
// button.setTitleEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
button.setImage(UIImage(named: "avatar") ?? UIImage());
// button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
// button.setImageEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
view.addSubview(button)
button.sizeToFit()
複製代碼
let uibutton = UIButton()
uibutton.layer.borderWidth = 1
uibutton.layer.borderColor = UIColor.black.cgColor
uibutton.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 40)
uibutton.setTitle("github.com/coderZsq", for: .normal)
uibutton.setTitleColor(.red, for: .normal)
// uibutton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
// uibutton.setImage(UIImage(named: "avatar"), for: .normal)
uibutton.setBackgroundImage(UIImage(named: "avatar"), for: .normal)
// uibutton.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10)
view.addSubview(uibutton)
// uibutton.sizeToFit()
let button = Button()
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
button.frame = CGRect(x: 0, y: 350, width: view.bounds.width, height: 40)
button.setTitle("github.com/coderZsq")
button.setTitleColor(.red)
// button.setTitleEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
// button.setImage(UIImage(named: "avatar") ?? UIImage());
button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
// button.setImageEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
view.addSubview(button)
// button.sizeToFit()
複製代碼
let uibutton = UIButton()
uibutton.layer.borderWidth = 1
uibutton.layer.borderColor = UIColor.black.cgColor
uibutton.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 40)
uibutton.setTitle("github.com/coderZsq", for: .normal)
uibutton.setTitleColor(.red, for: .normal)
// uibutton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
// uibutton.setImage(UIImage(named: "avatar"), for: .normal)
uibutton.setBackgroundImage(UIImage(named: "avatar"), for: .normal)
// uibutton.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10)
view.addSubview(uibutton)
uibutton.sizeToFit()
let button = Button()
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
button.frame = CGRect(x: 0, y: 350, width: view.bounds.width, height: 40)
button.setTitle("github.com/coderZsq")
button.setTitleColor(.red)
// button.setTitleEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
// button.setImage(UIImage(named: "avatar") ?? UIImage());
button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
// button.setImageEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
view.addSubview(button)
button.sizeToFit()
複製代碼
let uibutton = UIButton()
uibutton.layer.borderWidth = 1
uibutton.layer.borderColor = UIColor.black.cgColor
uibutton.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 40)
uibutton.setTitle("github.com/coderZsq", for: .normal)
uibutton.setTitleColor(.red, for: .normal)
// uibutton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
uibutton.setImage(UIImage(named: "avatar"), for: .normal)
uibutton.setBackgroundImage(UIImage(named: "avatar"), for: .normal)
// uibutton.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10)
view.addSubview(uibutton)
// uibutton.sizeToFit()
let button = Button()
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
button.frame = CGRect(x: 0, y: 350, width: view.bounds.width, height: 40)
button.setTitle("github.com/coderZsq")
button.setTitleColor(.red)
// button.setTitleEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
button.setImage(UIImage(named: "avatar") ?? UIImage());
button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
// button.setImageEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
view.addSubview(button)
// button.sizeToFit()
複製代碼
let uibutton = UIButton()
uibutton.layer.borderWidth = 1
uibutton.layer.borderColor = UIColor.black.cgColor
uibutton.frame = CGRect(x: 0, y: 100, width: view.bounds.width, height: 40)
uibutton.setTitle("github.com/coderZsq", for: .normal)
uibutton.setTitleColor(.red, for: .normal)
// uibutton.titleEdgeInsets = UIEdgeInsetsMake(0, 0, 0, 0)
uibutton.setImage(UIImage(named: "avatar"), for: .normal)
uibutton.setBackgroundImage(UIImage(named: "avatar"), for: .normal)
// uibutton.imageEdgeInsets = UIEdgeInsetsMake(-10, -10, -10, -10)
view.addSubview(uibutton)
uibutton.sizeToFit()
let button = Button()
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.black.cgColor
button.frame = CGRect(x: 0, y: 350, width: view.bounds.width, height: 40)
button.setTitle("github.com/coderZsq")
button.setTitleColor(.red)
// button.setTitleEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
button.setImage(UIImage(named: "avatar") ?? UIImage());
button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
// button.setImageEdgeInsets(UIEdgeInsetsMake(0, 0, 0, 0))
view.addSubview(button)
button.sizeToFit()
複製代碼
這道題尚未實現的就是AutoLayout
和EdgeInsets
, 還有就是在sizeToFit
算的最佳尺寸和系統的最佳尺寸有細微出入, 還有就是UIImageView
和UILabel
的前後加載的問題.
lazy var titleLabel: UILabel = {
let titleLabel = UILabel()
titleLabel.font = UIFont.systemFont(ofSize: 18)
titleLabel.textAlignment = .center
return titleLabel
}()
複製代碼
對於在sizeToFit算的最佳尺寸和系統的最佳尺寸有細微出入
這個問題是UILabel
的默認系統字體大小是17
, 而UIButton
中的titleLabel
的字體大小是18
.
internal func setImage(_ image: UIImage) {
if !imageViewIsCreated {
addSubview(imageView)
if titleLabelIsCreated {
insertSubview(imageView, belowSubview: titleLabel)
}
imageViewIsCreated = true
}
imageView.image = image
}
複製代碼
對於UIImageView和UILabel的前後加載的問題
, 須要在setImage
時判斷titleLabel
是否存在便可
現已達到徹底相同, 接下來就是要解決AutoLayout
和EdgeInsets
的問題.
經過 nib 進行建立.. 謝謝@夢痕_Lee
提供的思路.
1.判斷是不是從nib中建立
var createdFromNib = false
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
createdFromNib = true
}
複製代碼
2.重寫系統實現函數intrinsicContentSize
並返回最佳尺寸
override var intrinsicContentSize: CGSize {
return bestSize()
}
func bestSize() -> CGSize {
if titleLabelIsCreated && !imageViewIsCreated && !backgroundImageViewCreated {
let text: NSString? = titleLabel.text as NSString?
let titleLabelW: CGFloat = text?.boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: bounds.height), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.width ?? 0.0
let titleLabelH: CGFloat = text?.boundingRect(with: CGSize(width: titleLabelW, height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.height ?? 0.0
return CGSize(width: titleLabelW, height: titleLabelH + 10)
} else if !titleLabelIsCreated && imageViewIsCreated {
return imageView.image?.size ?? CGSize.zero
} else if titleLabelIsCreated && imageViewIsCreated {
let text: NSString? = titleLabel.text as NSString?
let titleLabelW: CGFloat = text?.boundingRect(with: CGSize(width: CGFloat(MAXFLOAT), height: bounds.height), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.width ?? 0.0
let titleLabelH: CGFloat = text?.boundingRect(with: CGSize(width: titleLabelW, height: CGFloat(MAXFLOAT)), options: NSStringDrawingOptions.usesLineFragmentOrigin, attributes: [NSAttributedStringKey.font : titleLabel.font], context: nil).size.height ?? 0.0
let imageViewW: CGFloat = imageView.image?.size.width ?? 0.0
let imageViewH: CGFloat = imageView.image?.size.height ?? 0.0
return CGSize(width: titleLabelW + imageViewW, height: imageViewH > titleLabelH ? imageViewH : titleLabelH)
} else {
return backgroundImageView.image?.size ?? CGSize.zero
}
}
複製代碼
3.佈局時判斷便可
override func layoutSubviews() {
super.layoutSubviews()
if createdFromNib {
frame.size = intrinsicContentSize
}
...
}
複製代碼
4.測試一下, 不加sizetofit
nib_button.layer.borderWidth = 1
nib_button.layer.borderColor = UIColor.black.cgColor
nib_button.setTitle("github.com/coderZsq")
nib_button.setTitleColor(.red)
// nib_button.setTitleEdgeInsets(.zero)
nib_button.setImage(UIImage(named: "avatar") ?? UIImage())
// nib_button.setBackgroundImage(UIImage(named: "avatar") ?? UIImage())
nib_button.setImageEdgeInsets(.zero)
複製代碼
同樣的完美, 攻克了AutoLayout
, 接下來就是EdgeInsets
啦~~~
一直理解錯了, intrinsicContentSize
這個方法是在添加約束後生效, 不論是nib
仍是手動約束
, 都會生效.
因此update2
中只需實現第二步便可, 並不須要其餘的判斷.
這道題真是戳中個人軟肋, 網絡與多線程是我最爲薄弱的地方, 如今對線程的理解應該已經不錯了, 可是網絡仍是有所欠缺的, 因此, 我會在從此學習Linux
和精讀AFNetWorking
&& SDWebImage
後, 本身寫一個網絡架構來進行自我提高.
對於兩道算法題, 我沒有什麼太多想講的, 技不如人吧
, 但是算法題這種東西在iOS
上用處其實不是很大, 我就不信那些沒有刷過算法題的同窗, 面對一道從沒有見過的算法題可以一會兒從容
的寫出最優解
的. 還有就是UI
的那道題目, 坑吧, 誰會去放着好好的現成的不用, 去噁心本身, 還必定要同樣... 我都問過面試官好幾遍, 到底想要作什麼功能... 回答只有, 我不在意你怎麼寫, 只要和系統的同樣就行了.... 產品附體了麼....
好吧... 技不如人, 被掛了也是理所固然... 不會找什麼藉口... 聽美團的朋友說, 如今只招技術專家, 其餘低職級的名額緊縮都不招了... 誒... 隨緣吧...
最後 本文中全部的源碼均可以在github上找到:
GitHub Repo:coderZsq.target.swift
Follow: coderZsq · GitHub
Resume: coderzsq.github.io/coderZsq.we…
掘金技術徵文連接👉 juejin.im/post/5aaf2a…