1. Write a function to swap two elements of an array
- Binary X programmer: That’s easy, just write the following results
func swap(_ nums: inout [Int], _ p: Int, _ q: Int) {
let temp = nums[p]
nums[p] = nums[q]
nums[q] = temp
}Copy the code
- Common programmer: First talk to the interviewer, what kind of array is it? The interviewer will say, “Any.” 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
- Arts programmer: Communicate 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. The literary programmer took the hint and wrote 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, check various boundary conditions, and then confirm that everything is correct, and then say, “I’m done with this problem.” This topic seems to be simple, but it actually examines the programmer’s awareness of examining, communicating, and testing. The properties of Swift 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 preceded by var prev or var post. Reason: On the surface, the above code looks fine. But as SOON as I wrote this, the question came up:
let head = Node(0)
let tail = Node(1)
head.post = tail
tail.prev = headCopy the code
At this point, head and tail point to each other in a retain cycle.
3. Implement a function whose input is any integer and whose output returns the input integer + 2
Many people write this question like:
func addTwo(_ num: Int) -> Int {
return num + 2
}Copy the code
And then the interviewer will say, well, what if I want to achieve + 4? The programmer thought about it and defined another method:
func addFour(_ num: Int) -> Int {
return num + 4
}Copy the code
What if I want to do something that returns + 6, + 8? Can you define a method only once? The correct way to write this is to use Swift’s Cauchy property:
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
The guard let statements and optional chaining are used to solve the problem
func divide(dividend: Double? , by divisor: Double?) -> Double? {
guard let dividend = dividend, letdivisor = 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 it copies car ([car]), the car in clousre is a local variable that is no longer related to the outside car, so “I Drive Benz” is printed. At this point, the interviewer smiled and modified the title slightly as follows:
var car = "Benz"
let closure = {
print("I drive \(car)")
}
car = "Tesla"
closure()Copy the code
At this point, the Closure does not declare copying car, so Clousre is still using the global car variable and will print “I drive Tesla”.
6. What does the following code print?
protocol Pizzeria {
func makePizza(_ ingredients: [String])
func makeMargherita(a)
}
extension Pizzeria {
func makeMargherita(a) {
return makePizza(["tomato"."mozzarella"])}}struct Lombardis: Pizzeria {
func makePizza(_ ingredients: [String]) {
print(ingredients)
}
func makeMargherita(a) {
return makePizza(["tomato"."basil"."mozzarella"])}}let lombardis1: Pizzeria = Lombardis(a)let lombardis2: Lombardis = Lombardis()
lombardis1.makeMargherita()
lombardis2.makeMargherita()Copy the code
The answer: Print the following lines [“tomato”, “basil”, “mozzarella”] [“tomato”, “basil”, “mozzarella”]. In Lombardis code, rewrite the makeMargherita code, So makeMargherita in Lombardis is always called. Further, we delete func makeMargherita() from protocol Pizzeria
protocol Pizzeria {
func makePizza(_ ingredients: [String])
}
extension Pizzeria {
func makeMargherita(a) {
return makePizza(["tomato"."mozzarella"])}}struct Lombardis: Pizzeria {
func makePizza(_ ingredients: [String]) {
print(ingredients)
}
func makeMargherita(a) {
return makePizza(["tomato"."basil"."mozzarella"])}}let lombardis1: Pizzeria = Lombardis(a)let lombardis2: Lombardis = Lombardis()
lombardis1.makeMargherita()
lombardis2.makeMargherita()Copy the code
The following result is printed: [“tomato”, “mozzarella”] [“tomato”, “basil”, “mozzarella”] Because Lombardis1 is Pizzeria and makeMargherita() has a default implementation, At this point we call the default implementation.
7. What is the difference between defining constants in Swift and objective-C?
The average person would think there is no difference, because it seems there is no difference in writing. OC defines constants like this:
const int number = 0;Copy the code
Swift defines constants like this:
let number = 0Copy the code
The first difference is that OC uses const to represent a constant, while Swift uses let to determine whether it is a constant. Further to this distinction, the const types and values indicated in OC are determined during compilation time; In Swift, let simply indicates a constant (which can only be assigned once), and its type and value can be either static or a dynamic evaluation method, which is determined at Runtime.
8. What is the difference between struct and class in Swift? Let me give you an example from an application
Struct is a value type and class is a reference type. As anyone who has seen WWDC knows, Structs are recommended by Apple because they are more secure than classes when passing and copying small data models, and are especially useful for multithreading and network requests. Let’s look at a simple example:
class A {
var val = 1
}
var a = A(a)var b = a
b.val = 2Copy the code
Val of A is also changed to 2, since both a and B are reference types and essentially refer to the same memory. The solution to this problem is to use struct:
struct A {
var val = 1
}
var a = A(a)var b = a
b.val = 2Copy the code
Now A is A struct, 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 object-oriented and functional programming language. Swift is object-oriented because it supports class encapsulation, inheritance, and polymorphism, almost no different from pure object-oriented languages like Java in this respect. Swift is a functional programming language, because Swift supports map, Reduce, filter, flatMap and other methods to remove intermediate states and mathematical functions, placing more emphasis on calculation results rather than intermediate processes.