As a developer, it is especially important to have a learning atmosphere and a communication circle. This is my iOS communication group: 812157648. No matter you are white or big, welcome to join us.
1. Given an array, write a function that swaps two elements of the array
- Two X programmer:
That’s easy. Just write it down
func swap(_ nums: inout [Int], _ p: Int, _ q: Int) {
let temp = nums[p]
nums[p] = nums[q]
nums[q] = temp
}
Copy the code
- Ordinary programmer:
First, communicate with the interviewer, what type of array is it? The interviewer will say, whatever. The average programmer smiles and writes the following code
func swap<T>(_ nums: inout [T], _ p: Int, _ q: Int) {
let temp = nums[p]
nums[p] = nums[q]
nums[q] = temp
}
Copy the code
- Literary programmer:
Communicating with the interviewer, what kind of array is it? What other requirements and restrictions are there? The interviewer will say, this is a Swift interview question. Literary programmer understood, so write the following answer:
func swap<T>(_ nums: inout [T], _ p: Int, _ q: Int) {
(nums[p], nums[q]) = (nums[q], nums[p])
}
Copy the code
At the same time, write corresponding tests on the above code to check all kinds of boundary cases, and then confirm that it is correct, and then say, I have completed this problem. This seemingly simple question examines the programmer’s awareness of problem checking, communication, and testing. The properties of Swift’s generics and Tuple are investigated technically.
2. What’s wrong with the following code
public class Node {
public var value: Int
public var prev: Node?
public var post: Node?
public init(_ value: Int) {
self.value = value
}
}
Copy the code
Answer: Weak should be added before var prev or var post. Reason: On the surface, the above code looks fine. But the problem comes when I write this:
let head = Node(0)
let tail = Node(1)
head.post = tail
tail.prev = head
Copy the code
The head and tail point to each other to form a retain cycle.
3. Implement a function where the input is any integer and the output returns the input integer + 2
Many people write on this question like this:
func addTwo(_ num: Int) -> Int {
return num + 2
}
Copy the code
And then the interviewer says, well, what if I want to achieve + 4? The programmer thought for a moment and defined another method:
func addFour(_ num: Int) -> Int {
return num + 4
}
Copy the code
And then the interviewer says, what if I wanted to return + 6, + 8? Can we just define the method once? The correct way to write it is to use the Cauchy property of Swift:
func add(_ num: Int) -> (Int) -> Int {
return { val in
return num + val
}
}
let addTwo = add(2), addFour = add(4), addSix = add(6), addEight = add(8)
Copy the code
4. Simplify the following code
func divide(dividend: Double? , by divisor: Double?) -> Double? { if dividend == nil { return nil } if divisor == nil { return nil } if divisor == 0 { return nil } return dividend! / divisor! }Copy the code
Guard let statements and optional chaining are necessary to aining the assemblies.
func divide(dividend: Double? , by divisor: Double?) -> Double? { guard let dividend = dividend, let divisor = divisor, divisor ! = 0 else { return nil } return dividend / divisor }Copy the code
5. What does the following function print?
var car = "Benz"
let closure = { [car] in
print("I drive \(car)")
}
car = "Tesla"
closure()
Copy the code
Since clousre has declared that car is copied in ([car]), the car in clousre is a local variable and no longer related to the outside car, so “I Drive Benz” is printed. At this point the interviewer smiled and slightly modified the question as follows:
var car = "Benz"
let closure = {
print("I drive \(car)")
}
car = "Tesla"
closure()
Copy the code
Closure has not declared a duplicate car, so clousre will use the global car variable and print “I drive Tesla”
6. What does the following code print out?
protocol Pizzeria {
func makePizza(_ ingredients: [String])
func makeMargherita()
}
extension Pizzeria {
func makeMargherita() {
return makePizza(["tomato", "mozzarella"])
}
}
struct Lombardis: Pizzeria {
func makePizza(_ ingredients: [String]) {
print(ingredients)
}
func makeMargherita() {
return makePizza(["tomato", "basil", "mozzarella"])
}
}
let lombardis1: Pizzeria = Lombardis()
let lombardis2: Lombardis = Lombardis()
lombardis1.makeMargherita()
lombardis2.makeMargherita()
Copy the code
Answer: Print the following two lines
[" tomato ", "basil," "mozzarella"]
[" tomato ", "basil," "mozzarella"]
In the Lombardis code, the makeMargherita code is rewritten, so that makeMargherita in Lombardis is always called. Further, we delete func makeMargherita() from Protocol Pizzeria, and the code becomes:
protocol Pizzeria {
func makePizza(_ ingredients: [String])
}
extension Pizzeria {
func makeMargherita() {
return makePizza(["tomato", "mozzarella"])
}
}
struct Lombardis: Pizzeria {
func makePizza(_ ingredients: [String]) {
print(ingredients)
}
func makeMargherita() {
return makePizza(["tomato", "basil", "mozzarella"])
}
}
let lombardis1: Pizzeria = Lombardis()
let lombardis2: Lombardis = Lombardis()
lombardis1.makeMargherita()
lombardis2.makeMargherita()
Copy the code
At this point, the following result is printed:
[" tomato ", "mozzarella"]
[" tomato ", "basil," "mozzarella"]
Since Lombardis1 is Pizzeria and makeMargherita() has a default implementation, we call the default implementation.
7. What’s the difference between defining constants in Swift and in Objective-C?
People think there’s no difference, because it doesn’t seem to make any difference. OC defines constants like this:
const int number = 0;
Copy the code
Swift defines constants like this:
let number = 0
Copy the code
The first difference is that OC uses const to indicate a constant, while Swift uses let to determine whether it is a constant.
The above distinction further states that the constant types and values indicated by const in OC were determined at the Compilation time; In Swift, a let simply indicates a constant (which can only be assigned once) whose type and value can be either static or a dynamic calculation method, which is determined at Runtime.
8. What is the difference between struct and class in Swift? Take an example from an application
Struct is a value type, and class is a reference type.
As anyone who has seen WWDC knows, struct is recommended by Apple because it is safer than class for passing and copying small data models, and especially useful for multithreading and network requests. Let’s look at a simple example:
class A {
var val = 1
}
var a = A()
var b = a
b.val = 2
Copy the code
In this case, the val of a is changed to 2, because a and b are both reference types, and they essentially point to the same memory. The way to solve this problem is to use structs:
struct A {
var val = 1
}
var a = A()
var b = a
b.val = 2
Copy the code
In this case, A is A struct, A value type, b and A are different things, and changing B has no effect on A.
9. Is Swift an object-oriented or functional programming language?
Swift is both an object-oriented and functional programming language. Swift is object-oriented because it supports class encapsulation, inheritance, and polymorphism, which is almost indistinguishable from a pure object-oriented language like Java. Swift is a functional programming language because it supports such methods as Map, Reduce, Filter, and Flatmap to eliminate intermediate states and mathematical functions, emphasizing the results of operations rather than intermediate processes.
Read the original