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…