Daily nonsense Since last year, I have been trying to interview with some big companies, because as a beginner iOS player (not a computer major) who got started with MJ videos, after three years of hard work, I can finally do some simple front-end, back-end, and mobile interactions. But if I want to go deeper, I feel that the bottleneck is becoming more and more obvious. The weak foundation makes it difficult to move up, so being able to enter a large and mature Internet company has become my recent goal. The reason is simple, this is the most effective way to learn and grow. Last July, I had my first interview with a big company: Ele.me. I was very excited to receive the call from a big company. I felt that my chance to turn things around was finally coming. I ran to the interview excitedly, thinking that the questions would be the same as those for general junior iOS interviews. I didn’t make any preparations. In fact, I didn’t know what to prepare. I remember what we talked about at that time: - UI: How to avoid frame drops and asynchronous rendering.
- Performance: Performance optimization, Vsync, CPU / GPU
- Network aspect: How to implement request caching strategy.
- Security: lild re-signature, Mach-O.
- Front-end: How to avoid DOM redrawing.
- Backend: How to handle load balancing.
There are some extreme cases, which I can't remember clearly because it was so long ago. Anyway, the feeling I got from this interview was, damn... I am just a piece of crap~ I remember that the architect who recommended me suggested that I solidify the basic skills of iOS, and then recommended basic books: Computer Networks, Operating System Principles, HTTP Authoritative Guide, TCP/IP Authoritative Guide, In-depth Analysis of Max OS X & iOS Operating System... Of these books, except for HTTP Authoritative Guide, which I gritted my teeth to finish, the others were simply incomprehensible to me, and I couldn't digest them at all. Last December, I had my second interview with a big company: JD.com. With the experience from the last time, I became very calm. I knew I would definitely be eliminated by the big company and there was an insurmountable gap between me and the top students. What surprised me was that I needed to use my ID card to exchange for a temporary access card to enter JD.com's building... The interview questions at that time were much softer than those of Ele.me, although I still couldn't answer them at that time. - Runtime: isa, message forwarding, weak reference table.
- Runloop:mode,timer.
- Block:__block,__forwording.
- Property: assign, weak, copy.
- Category:assoc,load
Now that I think about it, this is the interview for iOS. Unfortunately, I didn't have the knowledge at that time. What a pity. After that, I studied C++, ASM, and Linux. I also learned some knowledge about MACH-O and reverse engineering to prepare for future interview opportunities. The third interview was with Meituan this Wednesday. I prepared all the interview questions I could, including underlying principles, reverse security, multithreading and locks, memory layout, UI performance optimization, etc. Sure enough, I passed the one-hour phone interview easily. The questions were all about the underlying knowledge I had prepared, which made me feel that the opportunity had finally come. However.... when I had the on-site interview... all the questions were computer-based questions... - Design a network framework, how to design different data parsing (header, body), and be able to customize it, how to handle the reconnection mechanism, how to handle the status code error forwarding mechanism, how to avoid callback hell, and realize the self-implementation of Promise.
- Implement UIButton based on UIControl....
- Find the median of two sorted arrays...
- Self-implementation of the pow(double, double) function....
Sure enough, network, UI, algorithm... Well, the first time I did a computer test, I was instantly confused... Then the interviewer kept laughing beside me... kept laughing... Maybe it was his way of being friendly to me... The final conclusion of the interview was that my knowledge is still relatively broad, and I have done a lot of things, but I am still lacking in depth of knowledge. Later I learned that they were recruiting for the position of technical experts, and felt that my technical level did not meet the requirements, so they could not accept me. Of course, I knew I was rejected on the spot, and I also felt that the two interviews with Meituan and Ele.me were far from my level... But, I just want to enter a big company to learn, do I have to become an expert? Now junior, intermediate, senior, and experienced are not needed, just experts..., my headhunter friend told me that the 3-1 level is equivalent to Alibaba P6/P7, I chose to die... After this interview experience, my strategy has also changed. I no longer pursue the halo of a big company. Isn't it good to be a happy person? Do you have to think like a machine? Don't you feel that something important is missing if you live like an algorithm? Isn't it happy to brag with friends? Why do you have to study hard? Here I think of two sentences I heard recently: the best product experience is to let users not think, cognition is pain, ignorance is bliss, people are really contradictory, a slight difference in values can lead to a huge loss... Meituan interview question 1: self-implementation of pow(double, double) I was very confused when I took this question on the computer because the power is double and I had no idea how to start. The interviewer made it easier and used integers. Solution 1 - 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..
Then, it was my first time to solve an algorithm problem, and I could only think of the crudest way to solve it, which was a loop. I also knew that this was not the answer the interviewer expected, but what else could I do... Solution 2 - 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
- }
This is another solution that I found to be better after reading some information online. Solution 3 - 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
- }
This just adds a negative value check.... But I still have no idea about the power of double. I need some advice from the masters. Meituan interview question 2 findMedianSortedArrays This is an original question from LeetCode, but I have never done the algorithm question bank before... This is also the first time I encountered an algorithm question in an interview. The question is to find the median of two sorted arrays. Solution 1 - 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
- }
The first time I did an algorithm problem, I could only ignore the complexity of the algorithm. It was good enough to be able to complete it. What kind of bicycle would I need... Solution 2 - func findMedianSortedArrays_2(_ array1: [ Int ], _ array2: [ Int ]) -> Double { let c1 = array1. count , c2 = array2. count var a1 = array1, a2 = array2 if c1 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 }
- }
This is the answer I got when I looked up information online... I haven't figured out what the idea is yet, but the interviewer suggested divide and conquer, cutting off the head and tail... I don't know if it's the optimal algorithm. Solution 3 - func findMedianSortedArrays_3(_ array1: [ Int ], _ array2: [ Int ]) -> Double { let total = array1. count + array2. count 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 }
This is the idea I got after consulting Frost God (@halfrost-一缕殇流化隐半边冰霜), and it is indeed very easy to implement. But Frost God modestly said that it is not the optimal solution... Odd number test - 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 Even number test - 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 Time Comparison --- scope of: findMedianSortedArrays_1 --- timing: 2.50845623016357 --- scope of: findMedianSortedArrays_2 --- timing: 1.28746032714844e-05 --- scope of: findMedianSortedArrays_3 --- timing: 0.0358490943908691 It can be seen that the answer found online is the algorithm with the highest performance among the three solutions. Shuang Shen's idea is three orders of magnitude different from the answer on the Internet, and what I wrote is five orders of magnitude different... As expected, the algorithm I wrote is the worst... Solution 4 - @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 Following the idea of Frost God and the hint given by the interviewer, the above algorithm is given, but the order of magnitude of solution 3 is the same Meituan Interview Question 3 UIContorl -> UIButton - 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 {
- }
The above is the original question during the interview. At first, I had no idea what I was asked to do. They said that I just had to implement all the methods above, just like implementing my own UIButton... At first, I thought they wanted me to use CALayer to implement it, which scared me... Fortunately, it wasn't... Then, I followed my usual custom control writing method and wrote a UIImageView, a UILabel, and then assigned the layout... Then I saw the interviewer smiling at me and said, do you think this question is so simple... So simple... Then, you know that UILabel is created only when UIButton setsTitle, and UIImageView is created only when UIButton setsImage. Why do you hardcode the frame? Don't you know that UIView has sizeToFit? Why don't you implement sizeThatFits? You don't know how to use it at all... You know that when UIButton is laid out with AutoLayout, you only need to set the origin coordinates, and the width and height can be adaptive. Why don't you implement it when you customize it? Don't do setBackgroundImage and setImageEdgeInsets. Anyway, you don't know how to use it... What I want to say is, who would leave UIButton unused and use something like UIContorl... Just for a target-action design pattern... Every time I was thinking, he kept interrupting me, maybe this is a strategy of the interviewer... Forget it, I won't complain, just try my best to implement it. - 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
- }
- }
- }
Although some functions have been implemented, I still have no idea about the functions of AutoLayout and EdgeInsets. I would like to ask the experts to help me solve the confusion. Test comparison We compare our own Button with 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()
- }
- }
zero impl - 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()
setTitle && setTitleColor - 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() }
setTitle && setTitleColor && 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()
setImage - 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()
setImage && 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()
setBackgroundImage - 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()
Here, we see that the implementation is different from the system, because I set the bitmap directly in the rendering (display), instead of adding a new view like the system. This will cost less performance... (Modified for the following question) setBackgroundImage && 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()
setTitle && setTitleColor && setImage - 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()
setTitle && setTitleColor && setImage && 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()
setTitle && setTitleColor && setBackgroundImage - 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()
setTitle && setTitleColor && setBackgroundImage && 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()
setTitle && setTitleColor && setImage && setBackgroundImage - 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()
setTitle && setTitleColor && setImage && setBackgroundImage && 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()
What has not been implemented in this question is AutoLayout and EdgeInsets, and there is a slight difference between the optimal size calculated in sizeToFit and the optimal size of the system, as well as the loading of UIImageView and UILabel. update - lazy var titleLabel: UILabel = { let titleLabel = UILabel()
- titleLabel.font = UIFont.systemFont(ofSize: 18)
- titleLabel.textAlignment = .center return titleLabel
- }()
- There is a slight difference between the optimal size calculated in sizeToFit and the optimal size of the system. This problem is that the default system font size of UILabel is 17, while the font size of titleLabel in UIButton is 18.
- internal func setImage(_ image: UIImage) { if !imageViewIsCreated {
- addSubview(imageView) if titleLabelIsCreated {
- insertSubview(imageView, belowSubview: titleLabel)
- }
- imageViewIsCreated = true }
- imageView.image = image
- }
For the issue of loading the UIImageView and UILabel, you need to determine whether the titleLabel exists when settingImage Now that it has reached the exact same, the next step is to solve the problems of AutoLayout and EdgeInsets. Meituan Interview Question 4 Network Architecture Implementation This question really hits my weakness. Network and multithreading are my weakest points. My understanding of threads should be good now, but the network is still lacking. Therefore, after I learn Linux and intensively read AFNetWorking&&SDWebImage in the future, I will write a network architecture to improve myself. Meituan interview summary I don't want to talk about the two algorithm questions, but the skills are not as useful as others, but algorithm questions are not very useful on iOS. I don't believe that those students who have never read algorithm questions can calmly write the optimal solution in a row when facing an algorithm question that I have never seen before. There is also the UI question, let's just trick it, who will put it on a good ready-made one and disgusting yourself, and it must be the same... I have asked the interviewer several times, what function do you want to do... The answer is only, I don't care how you write it, as long as it's the same as the system... Is the product possessed? OK... I am not as good as someone's skills, so it's natural to be killed... I won't make any excuses... I heard from a friend of Meituan that I only recruit technical experts now, and other low-level places will be closed... Hey... Let's go with the flow... Finally, all the source codes in this article can be found on github: - GitHub Repo:https://github.com/coderZsq/coderZsq.target.swift
- Follow: https://github.com/coderZsq
- Resume: https://coderzsq.github.io/coderZsq.webpack.js/#/
|