When to use Never [duplicate] - swift

I read the code block enclosed in curly braces after the keyword else in the context of a guard-else flow, must call a function marked with the noreturn attribute or transfer control using return, break, continue or throw.
The last part is quite clear, while I don't understand well the first.
First of all, any function returns something (an empty tuple at least) even if you don't declare any return type. Secondly, when can we use a noreturn function? Are the docs suggesting some core, built-in methods are marked with noreturn?
The else clause of a guard statement is required, and must either call
a function marked with the noreturn attribute or transfer program
control outside the guard statement’s enclosing scope using one of the
following statements:
return
break
continue
throw
Here is the source.

First of all, any function returns something (an empty tuple at least) even if you don't declare any return type.
(#noreturn is obsolete; see Swift 3 Update below.)
No, there are functions which terminate the process immediately
and do not return to the caller. These are marked in Swift
with #noreturn, such as
#noreturn public func fatalError(#autoclosure message: () -> String = default, file: StaticString = #file, line: UInt = #line)
#noreturn public func preconditionFailure(#autoclosure message: () -> String = default, file: StaticString = #file, line: UInt = #line)
#noreturn public func abort()
#noreturn public func exit(_: Int32)
and there may be more.
(Remark: Similar annotations exist in other programming languages
or compilers, such as [[noreturn]] in C++11, __attribute__((noreturn)) as a GCC extension, or _Noreturn for the
Clang compiler.)
You can mark your own function with #noreturn if it also terminates
the process unconditionally, e.g. by calling one of the built-in functions, such as
#noreturn func myFatalError() {
// Do something else and then ...
fatalError("Something went wrong!")
}
Now you can use your function in the else clause of a guard statement:
guard let n = Int("1234") else { myFatalError() }
#noreturn functions can also be used to mark cases that "should not
occur" and indicate a programming error. A simple example
(an extract from Missing return UITableViewCell):
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell: MyTableViewCell
switch (indexPath.row) {
case 0:
cell = tableView.dequeueReusableCellWithIdentifier("cell0", forIndexPath: indexPath) as! MyTableViewCell
cell.backgroundColor = UIColor.greenColor()
case 1:
cell = tableView.dequeueReusableCellWithIdentifier("cell1", forIndexPath: indexPath) as! MyTableViewCell
cell.backgroundColor = UIColor.redColor()
default:
myFatalError()
}
// Setup other cell properties ...
return cell
}
Without myFatalError() marked as #noreturn, the compiler would
complain about a missing return in the default case.
Update: In Swift 3 (Xcode 8 beta 6) the #noreturn attribute
has been replaced by a Never return type, so the above example
would now be written as
func myFatalError() -> Never {
// Do something else and then ...
fatalError("Something went wrong!")
}

simple playground to see how it works ...
//: Playground - noun: a place where people can play
import Foundation
#noreturn func foo() {
print("foo")
exit(1)
}
var i: Int?
guard let i = i else {
foo()
}
print("after foo") // this line will never executed
//prints foo and finish

For instance, consider an assync operation that return either a value or error in result type. We usually write this as follows.
enum Result<Value, Error> {
case success(Value)
case failure(Error)
}
func fetch(_ request: URLRequest,
completion: (Result<(URLResponse, Data), Error>) -> Void) {
// ...
}
Now, if you know a function that always return value, never an error, then we could write :
func alwaysSucceeds(_ completion: (Result<String, Never>) -> Void) {
completion(.success("yes!"))
}
When compiler see Never, it won't force you to write all the switch cases to be exhaustive, so you can skip .failure as follows.
alwaysSucceeds { (result) in
switch result {
case .success(let string):
print(string)
}
}
Ref : https://nshipster.com/never/

Related

How to avoid force casting (as!) in Swift

extension ActionSheetViewController: UITableViewDataSource {
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return sheetActions.count
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: TableCellIds.ActionSheet.actionSheetTableCellIdentifier, for: indexPath) as! ActionsSheetCell
cell.actionCellLabel.text = "My cell content goes here"
return cell
}
}
Above code gives me 'Force Cast Violation: Force casts should be avoided. (force_cast)' error. How can I avoid it?
Some force-casts are unavoidable, especially when interacting with Objective C, which has a much more dynamic/loose type system.
In some cases like this, a force-cast would be self-explanatory. If it crashes, clearly you're either:
getting back nil (meaning there's no view with that reuse identifier),
or you're getting back the wrong type (meaning the cell exists, but you reconfigured its type).
In either case your app is critically mis-configured, and there's no much graceful recovery you can do besides fixing the bug in the first place.
For this particular context, I use a helper extension like this (it's for AppKit, but it's easy enough to adapt). It checks for the two conditions above, and renders more helpful error messages.
public extension NSTableView {
/// A helper function to help with type-casting the result of `makeView(wihtIdentifier:owner:)`
/// - Parameters:
/// - id: The `id` as you would pass to `makeView(wihtIdentifier:owner:)`
/// - owner: The `owner` as you would pass to `makeView(wihtIdentifier:owner:)`
/// - ofType: The type to which to cast the result of `makeView(wihtIdentifier:owner:)`
/// - Returns: The resulting view, casted to a `T`. It's not an optional, since that type error wouldn't really be recoverable
/// at runtime, anyway.
func makeView<T>(
withIdentifier id: NSUserInterfaceItemIdentifier,
owner: Any?,
ofType: T.Type
) -> T {
guard let view = self.makeView(withIdentifier: id, owner: owner) else {
fatalError("This \(type(of: self)) didn't have a column with identifier \"\(id.rawValue)\"")
}
guard let castedView = view as? T else {
fatalError("""
Found a view for identifier \"\(id.rawValue)\",
but it had type: \(type(of: view))
and not the expected type: \(T.self)
""")
}
return castedView
}
}
Honestly, after I got experienced enough with the NSTableView APIs, investigating these issues became second nature, and I don't find this extension as useful. Still, it could save some debugging and frustration for devs who are new the platform.
The force cast is actually correct in this situation.
The point here is that you really don't want to proceed if you can't do the cast, because you must return a real cell and if it's the wrong class, the app is broken and you have no cell, so crashing is fine.
But the linter doesn't realize that. The usual way to get this past the linter is to do a guard let with as?, along with a fatalError in the else. That has the same effect, and the linter will buy into it.
I really like the approach suggested by Alexander at https://stackoverflow.com/a/67222587/341994 - here's an iOS modification of it:
extension UITableView {
func dequeue<T:UITableViewCell>(withIdentifier id:String, for ip: IndexPath) -> T {
guard let cell = self.dequeueReusableCell(withIdentifier: id, for: ip) as? T else {
fatalError("could not cast cell")
}
return cell
}
}
So now you can say e.g.:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell : MyTableViewCell = tableView.dequeue(withIdentifier: "cell", for: indexPath)
// ...
return cell
}
And everyone is happy including the linter. No forced unwraps anywhere and the cast is performed automatically thanks to the generic and the explicit type declaration.
As others have said, a force cast is appropriate in this case, because if it fails, it means you have a critical error in your source code.
To make SwiftLint accept the cast, you can surround the statement with comments as described in this issue in the SwiftLint repo:
// swiftlint:disable force_cast
let cell = tableView.dequeueReusableCell(withIdentifier: TableCellIds.ActionSheet.actionSheetTableCellIdentifier, for: indexPath) as! ActionsSheetCell
// swiftlint:enable force_cast
The right thing to do is: remove force_cast from swift lint’s configuration file. And be professional: only write force casts where you mean “unwrap or fatal error”. Having to “get around the linter” is a pointless waste of developer time.

Explicitly unwrapping optional nil does not cause crash

A few folks asked this question before, yet no answer was accepted.
I have a UITableViewCell that contains a UITextField.
If I click slightly outside of the textField the row highlights. I want to prevent this.
To prevent it I do the following:
override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath! {
return nil
}
This works perfectly fine. Here is my question. The author of the tutorial states:
Note that returning nil from a method is only allowed if there is a
question mark (or exclamation point) behind the return type.
What does he mean that you can put an exclamation mark behind the optional return type? Why doesn't the program crash? Returning nil after I place an exclamation mark after the IndexPath return type doesn't crash. I thought ! would explicitly unwrap the nil and fail?
As of Swift 3, “Implicitly unwrapped optional” is not a separate type,
but an attribute on the declaration of a regular/strong optional.
For the details, see SE-0054 Abolish ImplicitlyUnwrappedOptional type.
A function with an IUO return type can return nil,
and assigning the return value to a variable makes that a regular
optional:
func foo() -> Int! {
return nil
}
let x = foo() // Type of `x` is `Int?`
print(x) // nil
Only if evaluation as an optional is not possible then the value
will be forced-unwrapped (and cause a runtime exception is the
value is nil):
let y = 1 + foo() // Fatal error: Unexpectedly found nil while unwrapping an Optional value
In your case, your
override func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath!
method overrides the UITableViewController method
func tableView(_ tableView: UITableView, willSelectRowAt indexPath: IndexPath) -> IndexPath?
and can return nil. This does not crash unless the caller unwraps
the value.
Remark: The above is meant as an explanation why your code compiles
and works. Generally, I do not see a good reason to use implicitly
unwrapped optional return types. The main use-cases of IUOs are
stated in SE-0054:
The ImplicitlyUnwrappedOptional ("IUO") type is a valuable tool for importing Objective-C APIs where the nullability of a parameter or return type is unspecified. It also represents a convenient mechanism for working through definite initialization problems in initializers.
One way to think this as a choise of the API Implementor. If implementor handles the input arguments it will not be any problem to the API User.
Lets create a drawing text class which just prints at console.
class TextDrawer {
var mustBeText: String!
func renderText(string: String) {
print(string)
}
func renderSafely() {
renderText(string: self.mustBeText ?? "Nothing found to be rendered")
// or
if let safeString = self.mustBeText {
renderText(string: safeString)
}
}
func renderUnsafely() {
renderText(string: mustBeText)
}
}
We have defined the mustBeText as String! means we are allowed to expect any string as well as nil argument.
Now, as we create a instance of the class as below:
let textDrawer = TextDrawer()
textDrawer.mustBeText = nil // this is allowed since the `mustBeText` is `String!`.
textDrawer.renderSafely() // prints -- Nothing found to be rendered
textDrawer.renderUnsafely() // crashes at runtime.
The renderUnsafaly() will crash since its not handling the nil case.

Exception Handling in Swift [duplicate]

I would really like to use a more simple classic try catch block in my Swift code but I can't find anything that does it.
I just need:
try {
// some code that causes a crash.
}
catch {
// okay well that crashed, so lets ignore this block and move on.
}
Here's my dilema, when the TableView is reloaded with new data, some information is still siting in RAM which calls didEndDisplayingCell on a tableView with a freshly empty datasource to crash.
So I frequently thrown the exception Index out of range
I've tried this:
func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
do {
let imageMessageBody = msgSections[indexPath.section].msg[indexPath.row] as? ImageMessageBody
let cell = tableView.dequeueReusableCellWithIdentifier("ImageUploadCell", forIndexPath: indexPath) as! ImageCell
cell.willEndDisplayingCell()
} catch {
print("Swift try catch is confusing...")
}
}
I've also tried this:
func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
print(indexPath.section)
print(indexPath.row)
if msgSections.count != 0 {
if let msg = msgSections[indexPath.section].msg[indexPath.row] as? ImageMessageBody {
let cell = tableView.dequeueReusableCellWithIdentifier("ImageUploadCell", forIndexPath: indexPath) as! ImageCell
cell.willEndDisplayingCell()
}
}
}
This is a very low priority block of code, and I have wasted a lot of time with trial and error figuring out which error handler built into swift works for what seems to be extremely unique situations when I have tons of scenarios just like this one where the code can crash and it will not have any effect on the user experience.
In short, I don't need anything fancy but Swift seems to have extremely specific error handlers that differ based on whether I'm getting a value from a functions return value or getting a value from an array's index which may not exist.
Is there a simple try catch on Swift like every other popular programming language?
As suggested in comments and other answers it is better to avoid this kind of situations. However, in some cases you might want to check if an item exists in an array and if it does safely return it. For this you can use the below Array extension for safely returning an array item.
Swift 5
extension Collection where Indices.Iterator.Element == Index {
subscript (safe index: Index) -> Iterator.Element? {
return indices.contains(index) ? self[index] : nil
}
}
Swift 4
extension Collection where Indices.Iterator.Element == Index {
subscript (safe index: Index) -> Iterator.Element? {
return indices.contains(index) ? self[index] : nil
}
}
Swift 3
extension Collection where Indices.Iterator.Element == Index {
subscript (safe index: Index) -> Generator.Element? {
return indices.contains(index) ? self[index] : nil
}
}
Swift 2
extension Array {
subscript (safe index: Int) -> Element? {
return indices ~= index ? self[index] : nil
}
}
This way you'll never hit Index out of range
You'll have to check if the item is nil
refer this question for more
Trying the Swift3 code in a Playground in Xcode 8.3.2 still leads to a
"crash" when I do let ar = [1,3,4], then let v = ar[5]. Why? – Thomas
Tempelmann May 17 at 17:40
You have to use our customized subscript so instead of let v = ar[5], it wll be let v = ar[safe: 5].
Default getting value from array.
let boo = foo[index]
Add use the customized subscript.
let boo = fee[safe: index]
// And we can warp the result using guard to keep the code going without throwing the exception.
guard let boo = foo[safe: index] else {
return
}
Swift's Error Handling (do/try/catch) is not the solution to runtime exceptions like "index out of range".
A runtime exception (you might also see these called trap, fatal error, assertion failure, etc.) is a sign of programmer error. Except in -Ounchecked builds, Swift usually guarantees that these will crash your program, rather than continuing to execute in a bad/undefined state. These sorts of crashes can arise from force-unwrapping with !, implicit unwrapping, misuse of unowned references, integer operations/conversions which overflow, fatalError()s and precondition()s and assert()s, etc. (And, unfortunately, Objective-C exceptions.)
The solution is to simply avoid these situations. In your case, check the bounds of the array:
if indexPath.section < msgSections.count && indexPath.row < msgSections[indexPath.section].msg.count {
let msg = msgSections[indexPath.section].msg[indexPath.row]
// ...
}
(Or, as rmaddy says in comments — investigate why this problem is occurring! It really shouldn't happen at all.)
Swift 4:
extension Collection where Indices.Iterator.Element == Index {
subscript (exist index: Index) -> Iterator.Element? {
return indices.contains(index) ? self[index] : nil
}
}
Usage:
var index :Int = 6 // or whatever number you need
if let _ = myArray[exist: index] {
// do stuff
}
or
var index :Int = 6 // or whatever number you need
guard let _ = myArray[exist: index] else { return }
Don't it's not considered a unusual state error, its a state of its completely screwed up, do something like
guard array.indicies.contains(index) else { return }
Swift 5
This answer in Swift 5 become:
extension Collection where Indices.Iterator.Element == Index {
subscript (safe index: Index) -> Iterator.Element? {
return indices.contains(index) ? self[index] : nil
}
}
Otherwise from Swift 4 there's the ability to have clauses on associated types and it can become:
extension Collection {
subscript (safe index: Index) -> Element? {
return indices.contains(index) ? self[index] : nil
}
}
You can try a different approach to this. Will surely work!
if msgSections != nil {
for msg in msgSections[indexPath.section] {
if msgSections[indexPath.section].index(of: msg) == indexPath.row {
(Code)
}
}

How do I cast an __NSMallocBlock__ to its underlying type in Swift 3?

I had a trick to help test UIAlertController that worked in Swift 2.x:
extension UIAlertController {
typealias AlertHandler = #convention(block) (UIAlertAction) -> Void
func tapButtonAtIndex(index: Int) {
let block = actions[index].valueForKey("handler")
let handler = unsafeBitCast(block, AlertHandler.self)
handler(actions[index])
}
}
This fails under Swift 3.x with fatal error: can't unsafeBitCast between types of different sizes, which tempts me to believe there might be a way to make the cast work. Can anyone figure it out?
Found a solution that works in Swift 3.0.1
extension UIAlertController {
typealias AlertHandler = #convention(block) (UIAlertAction) -> Void
func tapButton(atIndex index: Int) {
if let block = actions[index].value(forKey: "handler") {
let blockPtr = UnsafeRawPointer(Unmanaged<AnyObject>.passUnretained(block as AnyObject).toOpaque())
let handler = unsafeBitCast(blockPtr, to: AlertHandler.self)
handler(actions[index])
}
}
}
(Originally, the block value was the actual block, not a pointer to the block—which you obviously can't cast to a pointer to AlertHandler)
My answer is based on #Robert Atkins's, but shorter.
The problem here is that, valueForKey returns a Any typed object, and because in Swift,
MemoryLayout<Any>.size == 32
MemoryLayout<AnyObjcBlockType>.size == 8
an assertion will be triggered in unsafeBitCast when casting between types of different sizes.
One work-around is to create an intermediate wrapper and transform back to raw pointer, which satisfies MemoryLayout<UnsafeRawPointer>.size == 8.
A much simpler way is to create an indirect reference directly using protocol AnyObject, relying on the fact that MemoryLayout<AnyObject >.size == 8, we can write following valid code:
typealias AlertHandler = #convention(block) (UIAlertAction) -> Void
func tapButton(atIndex index: Int) {
if let block = actions[index].value(forKey: "handler") {
let handler = unsafeBitCast(block as AnyObject, to: AlertHandler.self)
handler(actions[index])
}
}
If your UIAlertController is an action sheet you can modify Robert's answer to dismiss the UIAlertController before you executed the handler.
dismiss(animated: true, completion: {() in handler(self.actions[index])})
I was using this extension for testing and without this modification my assertions for presented view controller were failing.

Swift Error handling - Unforseen Errors [duplicate]

I would really like to use a more simple classic try catch block in my Swift code but I can't find anything that does it.
I just need:
try {
// some code that causes a crash.
}
catch {
// okay well that crashed, so lets ignore this block and move on.
}
Here's my dilema, when the TableView is reloaded with new data, some information is still siting in RAM which calls didEndDisplayingCell on a tableView with a freshly empty datasource to crash.
So I frequently thrown the exception Index out of range
I've tried this:
func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
do {
let imageMessageBody = msgSections[indexPath.section].msg[indexPath.row] as? ImageMessageBody
let cell = tableView.dequeueReusableCellWithIdentifier("ImageUploadCell", forIndexPath: indexPath) as! ImageCell
cell.willEndDisplayingCell()
} catch {
print("Swift try catch is confusing...")
}
}
I've also tried this:
func tableView(tableView: UITableView, didEndDisplayingCell cell: UITableViewCell, forRowAtIndexPath indexPath: NSIndexPath) {
print(indexPath.section)
print(indexPath.row)
if msgSections.count != 0 {
if let msg = msgSections[indexPath.section].msg[indexPath.row] as? ImageMessageBody {
let cell = tableView.dequeueReusableCellWithIdentifier("ImageUploadCell", forIndexPath: indexPath) as! ImageCell
cell.willEndDisplayingCell()
}
}
}
This is a very low priority block of code, and I have wasted a lot of time with trial and error figuring out which error handler built into swift works for what seems to be extremely unique situations when I have tons of scenarios just like this one where the code can crash and it will not have any effect on the user experience.
In short, I don't need anything fancy but Swift seems to have extremely specific error handlers that differ based on whether I'm getting a value from a functions return value or getting a value from an array's index which may not exist.
Is there a simple try catch on Swift like every other popular programming language?
As suggested in comments and other answers it is better to avoid this kind of situations. However, in some cases you might want to check if an item exists in an array and if it does safely return it. For this you can use the below Array extension for safely returning an array item.
Swift 5
extension Collection where Indices.Iterator.Element == Index {
subscript (safe index: Index) -> Iterator.Element? {
return indices.contains(index) ? self[index] : nil
}
}
Swift 4
extension Collection where Indices.Iterator.Element == Index {
subscript (safe index: Index) -> Iterator.Element? {
return indices.contains(index) ? self[index] : nil
}
}
Swift 3
extension Collection where Indices.Iterator.Element == Index {
subscript (safe index: Index) -> Generator.Element? {
return indices.contains(index) ? self[index] : nil
}
}
Swift 2
extension Array {
subscript (safe index: Int) -> Element? {
return indices ~= index ? self[index] : nil
}
}
This way you'll never hit Index out of range
You'll have to check if the item is nil
refer this question for more
Trying the Swift3 code in a Playground in Xcode 8.3.2 still leads to a
"crash" when I do let ar = [1,3,4], then let v = ar[5]. Why? – Thomas
Tempelmann May 17 at 17:40
You have to use our customized subscript so instead of let v = ar[5], it wll be let v = ar[safe: 5].
Default getting value from array.
let boo = foo[index]
Add use the customized subscript.
let boo = fee[safe: index]
// And we can warp the result using guard to keep the code going without throwing the exception.
guard let boo = foo[safe: index] else {
return
}
Swift's Error Handling (do/try/catch) is not the solution to runtime exceptions like "index out of range".
A runtime exception (you might also see these called trap, fatal error, assertion failure, etc.) is a sign of programmer error. Except in -Ounchecked builds, Swift usually guarantees that these will crash your program, rather than continuing to execute in a bad/undefined state. These sorts of crashes can arise from force-unwrapping with !, implicit unwrapping, misuse of unowned references, integer operations/conversions which overflow, fatalError()s and precondition()s and assert()s, etc. (And, unfortunately, Objective-C exceptions.)
The solution is to simply avoid these situations. In your case, check the bounds of the array:
if indexPath.section < msgSections.count && indexPath.row < msgSections[indexPath.section].msg.count {
let msg = msgSections[indexPath.section].msg[indexPath.row]
// ...
}
(Or, as rmaddy says in comments — investigate why this problem is occurring! It really shouldn't happen at all.)
Swift 4:
extension Collection where Indices.Iterator.Element == Index {
subscript (exist index: Index) -> Iterator.Element? {
return indices.contains(index) ? self[index] : nil
}
}
Usage:
var index :Int = 6 // or whatever number you need
if let _ = myArray[exist: index] {
// do stuff
}
or
var index :Int = 6 // or whatever number you need
guard let _ = myArray[exist: index] else { return }
Don't it's not considered a unusual state error, its a state of its completely screwed up, do something like
guard array.indicies.contains(index) else { return }
Swift 5
This answer in Swift 5 become:
extension Collection where Indices.Iterator.Element == Index {
subscript (safe index: Index) -> Iterator.Element? {
return indices.contains(index) ? self[index] : nil
}
}
Otherwise from Swift 4 there's the ability to have clauses on associated types and it can become:
extension Collection {
subscript (safe index: Index) -> Element? {
return indices.contains(index) ? self[index] : nil
}
}
You can try a different approach to this. Will surely work!
if msgSections != nil {
for msg in msgSections[indexPath.section] {
if msgSections[indexPath.section].index(of: msg) == indexPath.row {
(Code)
}
}