Поэтому мне нравится объявлять переменные для удержания возвращаемого значения, а затем возвращать указанную переменную в следующей строке, что упрощает отладку моего кода. Я могу просто установить точку останова в строке возврата и посмотреть, какое значение она возвращает. Я использую это везде, и это значительно упрощает отладку всего моего кода.
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
let cellCount = models.count
return cellCount
}
Но тогда у вас есть сценарий, в котором у вас есть опции и различные условия, которые должны быть выполнены, чтобы ваш метод имел смысл. Guard заявление отлично подходит для проверки соблюдения некоторых условий, но не вводит пирамиды гибели.
Но проблема с ранним возвратом заключается в том, что вы получаете по крайней мере две точки выхода (поскольку guard
требует return
в этом контексте) от вашего метода, что затрудняет отладку.
// Instantiate using dependency injection
private let reachability: ReachabilityProtocol
private let apiClient: APIClientProtocol
// Returns true if could start login request, else false
func loginUser(username: String, password: String) -> Bool {
defer {
// Not possible, would be nice! Return value would be an implicitly declared variable
// exaclty like the variables 'newValue' and 'oldValue' in property observers!
print("return value: \(returnValue)")
}
guard reachability.isOnline && !username.isEmpty && !password.isEmpty { return false }
apiClient.loginUser(username, password: password)
return true
}
Было бы здорово, если бы Swift 3.X сделал инструкция отсрочки способна перехватывать возвращаемое значение, не так ли?
Это значительно упростит отладку, но при этом будет использоваться guard
и ранние возвраты. У меня нет понимания того, что такое когда-либо писать компиляторы и т. д., но мне кажется, что это не будет так уж сложно реализовать в следующих версиях Swift?
Можете ли вы придумать другой способ получения одной точки для чтения возвращаемого значения метода с несколькими точками выхода? (Не дожидаясь предложенного мною улучшения до defer
?)
Изменить:
Мой пример с логином выше не идеален, простите, зачем мне писать такой код? Ха-ха! Но есть много других подобных сценариев, может быть, что-то вроде этого, использование do-try-catch
также затрудняет отладку кода:
// We don't know the return value of this function! Makes it hard to debug!
func fetchUserByFirstName(firstName: String, andLastName lastName: String, fromContext context: NSManagedObjectContext) -> User? {
defer {
// Not possible, would be nice! Return value would be an implicitly declared variable
// exaclty like the variables 'newValue' and 'oldValue' in property observers!
print("return value: \(returnValue)")
}
guard !firstName.isEmpty else { print("firstName can't be empty"); return nil }
guard !lastName.isEmpty else { print("lastName can't be empty"); return nil }
// Imagine we have some kind of debug user... Does not really make sense, but good for making a point.
guard firstName != "DEBUG" else { return User.debugUser }
let fetchRequest = NSFetchRequest(entityName: Users.entityName)
let predicate = NSPredicate(format: "firstName == \(firstName) AND lastName == \(lastName)")
fetchRequest.predicate = predicate
do {
let user = try context.executeFetchRequest(fetchRequest)
return user
} catch let error as NSError {
print("Error fetching user: \(error)")
}
return nil
}