Bad Access in `top_level_code` when I set instance variable - swift

Ok, this is an odd error and it's taken me many hours to track down the exact location (although the cause remains unknown). The error only occurs on 64-bit devices. In other words, it works fine on my iPhone 5, but crashes on my iPhone 6 Plus.
Essentially, I have a private variable in a class:
class Manager {
private lastUpdated:NSDate?
}
Initially, it's not set. This class retrieves messages from a server and then sets the lastUpdated variable to NSDate().
private func checkForNewMessages(complete:Result<[Message]> -> ()) {
self.server.userMessages(u, fromDate: self.lastUpdated) { result in
result.onSuccess { messages in
self.insertMessages(messages)
self.lastUpdated = NSDate()
complete(Result(messages))
}
result.onError { err in complete(Result(err)) }
}
}
I've deleted extraneous code, but nothing inside the code path that's crashing (just stuff around it)
Note: I'm using a Result enum. For more info about this kind of enum, this article is pretty good at explaining it: Error Handling in Swift.
The first time the manager retrieves messages, everything works fine and the lastUpdated value is set correctly. If I then try to retrieve messages again, the app crashes when it tries to set self.lastUpdated = NSDate().
I can get it to work if I delay the assignment by using GCD, dispatch_after. But I don't want to do that.
Does anyone have any idea why this is occurring?
Update
This is only occurring when I assign a NSDate. It's not occurring if I try to set another object type (Int, Bool, String) etc.
The crash occurs if I change the stored variable to NSTimeInterval and attempt to set it from NSDate.timeIntervalSinceReferenceDate()
The crash occurs if I store an array of updates and attempt to simply append a new date to that array.
The crash occurs if I attempt to set lastUpdated before the server is called rather than in the callback.
The crash occurs if I wrap NSDate in another class.
The crash occurs is I set lastUpdated in a background thread
The crash doesn't occur if I println(NSDate()) (removing the assignment)

Ok, it took me numerous hours but I finally figured it out.
This will be a little difficult to explain and I'm not certain I fully understand what is going on. The error actually occurred in the Server class that was making the request. It took the lastUpdated date, converted it to a string and then sent that up to the server. The first run, there was no date, so no issue. In the second run, it took the date and used a date formatter to convert it to a string. However, I thought that stringFromDate returned an Optional. It does not. Normally, the compiler would warn me if I attempted to unwrap something that wasn't an option. However, I use Swift's functional aspects to use Infix operators to unwrap and conditionally pass the unwrapped value to another function, which can then pass it's value on. It allows me to chain unwraps together so I can avoid "nested if-let hell".
Very simple but powerful:
infix operator >>? { associativity left}
func >>? <U,T>(opt: T?, f: (T -> U?)) -> U? {
if let x = opt {
return f(x)
}
return nil
}
Note that the function must return an Optional. For some reason, the Swift compiler missed the fact that stringFromDate did not return an optional and so it didn't warn me. I'm not sure why that is, it's certainly warned me before:
if let update = fromDate >>? self.dateFormatter.stringFromDate {
This fails, but not immediately
Unwrapping a non-optional value doesn't immediately result in a crash, error or anything apparently. I successfully used the date string to send and receive data from the server. I'm not certain why unwrapping a non-optional string would later result in a crash and that only when I attempted to set the instance variable that of the backing NSDate object the string was generated from. I think somehow, unwrapping a non-optional screwed up some pointers, but not necessarily the pointer to the unwrapped object. I think the crash itself has to do with Swift attempting to release or dealloc the original instance variable (lastUpdated) when a new one is set, but found the memory address messed up. I think only a Apple Swift engineer could tell me what actually happened, but perhaps there are clues here to how Swift works internally.

Related

Swift 5 LLDB error: warning: <EXPR>:12:9: warning: initialization of variable '$__lldb_error_result' was never used

Full Error Message:
error: warning: <EXPR>:12:9: warning: initialization of variable '$__lldb_error_result' was never used; consider replacing with assignment to '_' or removing it
var $__lldb_error_result = __lldb_tmp_error
~~~~^~~~~~~~~~~~~~~~~~~~
_
error: <EXPR>:19:5: error: use of unresolved identifier '$__lldb_injected_self'
$__lldb_injected_self.$__lldb_wrapped_expr_7(
^~~~~~~~~~~~~~~~~~~~~
This error appears in Console when I interrogate the value of a Dictionary<String, String> property within a generic UITableViewController (TVC).
More Detail...
I have a generic TVC (noted above) that is more or less based on the framework outlined in the book "Core Data" by Florian Kugler and Daniel Eggert and takes, amongst other things, a generic value of T.
class TVCDataSource_List<T: Managed, etc...>
This generic TVC includes a dictionary that is designed to hold a list of longer 'alternative' names for the TVC's section headers.
var dictionarySectionData: [String: String] = [:]
I've elected to program the TVC this way because it seems more efficient to hold a reference to a name as a short two character String in the data model attribute (section identifier) than a long name as a String.
I've tried populating this dictionary at many different places in code, most of which work but all with the same outcome, specifically:
I step through the code using the debugger and, as expected, the dictionary is populated via a single fetch request to the persistent store;
Immediately following, a call to print(dictionarySectionData.description) to the console, prints out a properly populated dictionary, as expected;
Interrogating LLDB with p dictionarySectionData (or po) immediately before and after this print to console, produces the Full Error Message detailed at the start of this question;
At the same time, the Assistant Editor Variable Viewer shows the dictionary to be empty, which surprisingly conflicts with the print;
I continue to step through the code to construct the TVC, as the dictionary no longer has its key value pairs, I cannot recall the value for my section header and as expected, the console reports "Fatal error: Unexpectedly found nil while unwrapping an Optional value".
I've done a bit of simple research:
This Blog by Scott Berrevoets titled "Re-binding self: the debugger's break(ing) point".
This Swift Bug Report by Keith Smiley titled "LLDB: warning: initialization of variable '$__lldb_error_result'".
This Swift Bug Report by Zev Eisenberg titled "error: use of undeclared type '$__lldb_context' in NSAttributedString extension".
It seems that I may have either:
stumbled across a bug in the compiler; or
attempted to set the value for the dictionary within the generic TVC such that the compiler interprets an attempt to re-bind to self??
Frankly neither of which I understand and from my shallow knowledge of the compiler and Swift, would take me months, possibly years of learning and experience. Which I'm happy to slowly accumulate over time.
I do have a satisfactory solution... instead of building a dictionary of the longer 'alternative' names for the TVC's section headers at the beginning of the TVC lifecycle, I run a fetch request EACH TIME the code resolves the name for the current TVC section header. This works perfectly and does not block the UI (yet).
However, it really annoys me that I cannot run one fetch at the start of the construction of my generic TVC to prepare a concise dictionary of longer 'alternative' names for the TVC's section headers and instead have to run a fetch for each section that the user decides to scroll through. To perform one fetch and hold a dictionary of 12-15 key value pairs in memory seems far more efficient that running many fetches.
Has any one experienced this problem?
If so, are you able to offer any advice?
UPDATE
The problem seems to be with my use - or perhaps more correctly, my misuse - of the explicitly unwrapped Optional.
Here is the code I use to populate the dictionary...
func createDictionaryOfSectionHeaderText() {
let request = Types.preparedFetchRequest
// noting .preparedFetchRequest is a static var, available through generics
let key = "typeParent.typeParentName"
let name = "Taxonomy"
let predicate = NSPredicate(format: "%K == %#", argumentArray: [key, name])
request.predicate = predicate
var results: [Types] = []
do {
results = try <<My NSManagedObjectContext>>.fetch(request)
}
catch {
let fetchError = error
print(fetchError)
}
for type in results {
let formatSortOrder = String(format: "%02d", type.sortOrder)
dictionarySectionData[formatSortOrder] = type.typeName
}
}
There were two elements of code that caused the error message...
A. As above in the func createDictionaryOfSectionHeaderText()
let stringSortOrder = String(type.sortOrder)
let formatSortOrder = String(format: "%02d", stringSortOrder)
...which was feeding a string into the format "%02d", uncertain of the effect... TBA.
(Now changed from those two lines to the single let formatSortOrder = String(format: "%02d", type.sortOrder) - which of course works.)
B. Within the UITableViewDelegate method func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView?
stringHeaderText = dictionarySectionData[stringSectionName]!
// "Fatal error: Unexpectedly found nil while unwrapping an Optional value"
...which, following more thought on the matter, is exactly as expected when explicitly unwrapping the Optional, when that Optional is nil!!
So, when I change the setter to stringHeaderText by removing the instruction to explicitly unwrap, and instead offer a default value when nil, my programming problem disappears.
stringHeaderText = dictionarySectionData[stringSectionName] ?? "ERROR"
I may even provide an answer if/when I understand this better.
These issues should be solved in XCode 12.
There were indeed a lot of bugs in XCode 10 & 11, especially when it came to Generics

Why to avoid forced unwrapping

There are cases where you forgot to set a value (so it's actually a bug), and running the program with forced unwrapping can crash the problem, and that can allow you to track down the bug where you forgot to set the value that you should have set.
From posts talking about avoiding forced unwrapping, it's always brought up that forced unwrapping can crash the program therefore it's a bad thing. What's so bad about crashing a problem when it actually has a bug?
Please give examples where forced unwrapping can be bad.
(I'm not saying forced unwrapping is suitable for everything.)
Forced unwrapping (and I'm going to include force-casting as well) should only be used when you, as the programmer, know for a fact that an optional will never actually ever be nil unless that nil represents a clear bug in your code during development (and then you want it to crash).
There are many examples where this type of forced unwrapping is appropriate. Examples include:
Getting the path to a known file in your app bundle (nil means you forgot to target the file during development).
Force casting a call to UITableView dequeueReusableCell (nil means you have a mistake in your storyboard).
Getting a specific component from DateComponents when you just specially asked Calendar for that component (nil mean you have a typo).
There are obviously many other cases where forced-unwrapping is appropriate but you must have a clear understanding of those cases.
But there are just as many runtime decisions that result in optionals that you can't guarantee and such cases should not be forced unwrapped.
Examples include:
Dealing with any user input. Never assume a user enters valid data. Never assume a value can be converted as expected. Always check for nil results.
Parsing JSON results. Never assume the data you get matches some expected format even if that format is clearly documented and always seems to work. Things change over time. Gracefully handle such unexpected data instead of just assuming a value will always be there and of the assumed data type.
Dealing with any API that can throw or return optional results. Things can go wrong. Errors happen. Never assume you will get back a valid answer. Code defensively.
In the end, a developer with the proper experience and understanding of how optionals work, what they mean, and when a value may or may not ever actually be nil is in a position to safely use forced unwrapping when appropriate. Use it wisely.
Never use forced-unwrapping just because Xcode suggested it to make the compiler happy.
Forced unwrapping is bad because your program is not guaranteed to be accessing an actual variable at the time of execution. When this happens your program might be attempting to perform a mathematical calculation on a number that doesn't exist, and your app would crash. Your point of in the development phase if it crashes you would be able to narrow down why the crash happened and fix the issue of it being nil at runtime for your development phase, but what about in production?
For example, if you were retrieving some sort of number from a web service you may want to compare this number to something local, maybe a version number:
if let json = try? JSONSerialization.jsonObject(with: responseData, options: .allowFragments) as? [String: Any],
let serverAPIVersion:NSNumber = json["API_Version_Number"] as? NSNumber {
if self.currentAPIVersion.uintValue < serverAPIVersion.uintValue {
self.updateVersionWith(number: serverAPIVersion)
}
}
In the code above we are safely unwrapping the "API_Version_Number" from the JSON we get from the server. We are safely unwrapping because if there weren't a value for "API_Version_Number" then when we would try to do the comparison to the current version, the program would crash.
// This will crash if the server does not include "API_Version_Number in json response data
let serverAPIVersion:NSNumber = json["API_Version_Number"] as! NSNumber
And in production there are things out of your control (many times a server side issue) that may lead to unpopulated variables. That is why it is best to conditionally unwrap to gain access to values safely in your code to keep things from crashing at execution time.
There's nothing wrong with crashing a program if it actually has a bug...if you can not work your way around the crash
But as #phillip-mills says in his comment:
...asked by people who use forced unwrapping without understanding that's what's causing the crash
We often see examples where people force unwrap optionals that, for some unexpected reason, isn't there, and in that case it makes sense to try to unwrap the optional "gracefully.
An Example of Bad Forced Unwrapping
Lets say you have a backend service that gives you some JSON which you parse into a model object and present in a view.
Lets say you have a model like this one:
struct Person {
let firstName: String?
let lastName: String?
}
And in a UITableView you populate some cells with person objects. Something along the lines of:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
//dequeue your cell
//get your person element from some array
//populate
cell.firstNameLabel.text = person.firstName!
cell.lastNameLabel.text = person.lastName!
return cell
}
At some point you probably will end up with a Person without a firstName (you can say that that is a problem with the backend and so on and so forth but....it'll probably happen :) ) If you force unwrap, your app will crash where it shouldn't be necessary. In this case you could have gotten away with a graceful unwrap
if let firstName = person.firstName {
cell.firstNameLabel.text = firstName
}
Or you could have used the Nil Coalescing Operator
let firstName = person.firstName ?? ""
Finally, as #rmaddy says in his answer
Forced unwrapping is bad because your program is not guaranteed to be accessing an actual variable at the time of execution
You can not always be sure that the data is what you expect it to be.
And when you have the possibility to actually only do some operation if you're absolutely sure that the data you're operating on is valid, that is, if you've unwrapped it safely...it'd be stupid not to use that option :)
Hope that helps you.

Swift 2: Why is it necessary to apply ‘as!’ after getting new object by ‘copy()’?

I’ve created new SKEmitterNode object using copy() method. After that i’ve tried to write emitter.position but Xcode said «Ambiguous reference to member ‘position’». But, when i use type conversion «as! SKEmitterNode» after the «copy()», everything is ok. Can you explain me, please, why am i need to use «as!» in this case? I can’t understand this because when i check value type of «emit» variable in debugger, i can see that it’s already have the type SKEmitterNode, even without using «as! SKEmitterNode» after «copy()».
class GameScene: SKScene, SKPhysicsContactDelegate {
let bangEmitter : SKEmitterNode = SKEmitterNode(fileNamed: "MyParticle")!
func makeBang(position: CGPoint) {
// this method causes an error in second line
// but, emit is already have type SKEmitterNode, as debugger says
var emit = bangEmitter.copy()
emit.position = position
// this works ok
var emit = bangEmitter.copy() as! SKEmitterNode
emit.position = position
}
}
Because copy() is a method defined by NSObject and is meant to be overriden by subclasses to provide their own implementation. NSObject itself doesn't support it and will throw an exception if you call copy() on it.
Since it's meant for subclassing, there's no way to tell what the class of the object that will be returned. In Objective-C, it returns an id; in Swift, this becomes AnyObject. Since you, the programmer, know what kind of object you are copying from, you can use as! SomeClass to tell the compiler what kind of object the copy is.
This also speaks to the difference between ObjectiveC and Swift. Objective-C is dynamic. In Objective-C, every time you send a message, the run time will check if the object responds to the message. This happens at run time. In Swift, you call a method and this happens at compile time. The compiler must know the object's type in order to call the right function / method.
This explains why you get emit as an SKEmitterNode in the debugger - this is run time. The compiler doesn't know that at compile time.
Using the as! is an indicator that a check may fail.
Swift 1.2 separates the notions of guaranteed conversion and forced conversion into two distinct operators. Guaranteed conversion is still performed with the as operator, but forced conversion now uses the as! operator. The ! is meant to indicate that the conversion may fail. This way, you know at a glance which conversions may cause the program to crash.
Reference: https://developer.apple.com/swift/blog/?id=23
Look up the definition of the function copy() and you'll see that it always returns Any, therefore you always need to cast it to the object that you're seeking.

Dictionary containing an array - Why is unwrapping necessary?

I'm trying to wrap my head around why what feels intuitive is illegal when it comes to a dictionary containing an array in Swift.
Suppose I have:
var arr = [1,2,3,4,5]
var dict = ["a":1, "b":2, "test":arr]
I can easily access the dictionary members like so:
dict["a"]
dict["b"]
dict["test"]
As expected, each of these will return the stored value, including the array for key "test":
[1,2,3,4,5]
My intuitive reaction to this based on other languages is that this should be legal:
dict["test"][2]
Which I would expect to return 3. Of course, this doesn't work in Swift. After lots of tinkering I realize that this is the proper way to do this:
dict["test"]!.objectAtIndex(2)
Realizing this, I return to my intuitive approach and say, "Well then, this should work too:"
dict["test"]![2]
Which it does... What I don't really get is why the unwrap isn't implied by the array dereference. What am I missing in the way that Swift "thinks?"
All dictionary lookups in Swift return Optional variables.
Why? Because the key you are looking up might not exist. If the key doesn't exist, the dictionary returns nil. Since nil can be returned, the lookup type has to be an Optional.
Because the dictionary lookup returns an Optional value, you must unwrap it. This can be done in various ways. A safe way to deal with this is to use Optional Chaining combined with Optional Binding:
if let value = dict["test"]?[2] {
print(value)
}
In this case, if "test" is not a valid key, the entire chain dict["test"]?[2] will return nil and the Optional Binding if let will fail so the print will never happen.
If you force unwrap the dictionary access, it will crash if the key does not exist:
dict["test"]![2] // this will crash if "test" is not a valid key
The problem is that Dictionary’s key-based subscript returns an optional – because the key might not be present.
The easiest way to achieve your goal is via optional chaining. This compiles:
dict["test"]?[2]
Note, though, that the result will still be optional (i.e. if there were no key test, then you could get nil back and the second subscript will not be run). So you may still have to unwrap it later. But it differs from ! in that if the value isn’t present your program won’t crash, but rather just evaluate nil for the optional result.
See here for a long list of ways to handle optionals, or here for a bit more background on optionals.
In the Objective-C world, it has potential crash if you are trying to access 3 by dict[#"test"][2]. What if dict[#"test"] is nil or the array you get from dict[#"test"] has two elements only? Of course, you already knew the data is just like that. Then, it has no problem at all.
What if the data is fetched from the backend and it has some problems with it? This will still go through the compiler but the application crashes at runtime. Users are not programmers and they only know: The app crashes. Probably, they don't want to use it anymore. So, the bottom line is: No Crashes at all.
Swift introduces a type called Optional Type which means value might be missing so that the codes are safe at runtime. Inside the Swift, it's actually trying to implement an if-else to examine whether data is missing.
For your case, I will separate two parts:
Part 1: dict["test"]! is telling compiler to ignore if-else statement and return the value no matter what. Instead, dict["test"]? will return nil if the value if missing. The terminology is Explicit Unwrapping
Part 2: dict["test"]?[2] has potential crash. What if dict["test"]? returns a valid array and it only has two element? This way to store the data is the same using dict[#"test"][2] in Objective-C. That's why it has something called Optional Type Unwrapping. It will only go the if branch when valid data is there. The safest way:
if let element = dict["test"]?[2] {
// do your stuff
}

Treating a forced downcast as optional will never produce 'nil'

I've been playing around with Swift and discovered that when down casting an object to be inserted into a dictionary, I get a weird warning: Treating a forced downcast to 'String' as optional will never produce 'nil'. If I replace as with as? then the warning goes away.
func test() -> AnyObject! {
return "Hi!"
}
var dict = Dictionary<String,String>()
dict["test"]=test() as String
Apple's documentation says the following
Because downcasting can fail, the type cast operator comes in two different forms. The optional form, as?, returns an optional value of the type you are trying to downcast to. The forced form, as, attempts the downcast and force-unwraps the result as a single compound action.
I'm unclear as to why using as? instead of as is correct here. Some testing reveals that if I change test() to return an Int instead of a String, the code will quit with an error if I continue using as. If I switch to using as? then the code will continue execution normally and skip that statement (dict will remain empty). However, I'm not sure why this is preferable. In my opinion, I would rather the program quit with an error and let me know that the cast was unsuccessful then simply ignore the erroneous statement and keep executing.
According to the documentation, I should use the forced form "only when you are sure that the downcast will always succeed." In this case I am sure that the downcast will always succeed since I know test() can only return a String so I would assume this is a perfect situation for the forced form of down casting. So why is the compiler giving me a warning?
Let's take a closer look at your last line, and explode it to see what's happening:
let temporaryAnyObject = test()
let temporaryString = temporaryAnyObject as String
dict["test"] = temporaryString
The error is on the second line, where you are telling the compiler to enforce that temporaryAnyObject is definitely a String. The code will still compile (assuming you don't treat warnings as errors), but will crash if temporaryAnyObject is not actually a String.
The way as works, with no ?, is basically saying "from now on, treat the result of this expression as that type IF the result is actually of that type, otherwise we've become inconsistent and can no longer run.
The way as? works (with the ?) is saying "from now on, treat the result of this expression as that type IF the result is actually of that type, otherwise the result of this expression is nil.
So in my exploded example above, if test() does return a String, then the as downcast succeeds, and temporaryString is now a String. If test() doesn't return a String, but say an Int or anything else not subclassed from String, then the as fails and the code can no longer continue to run.
This is because, as the developer in complete control, you told the system to behave this way by not putting the optional ? indicator. The as command specifically means that you do not tolerate optional behavior and you require that downcast to work.
If you had put the ?, then temporaryString would be nil, and the third line would simple remove the "test" key/value pair from the dictionary.
This might seem strange, but that's only because this is the opposite default behavior of many languages, like Obj-C, which treat everything as optional by default, and rely on you to place your own checks and asserts.
Edit - Swift 2 Update
Since Swift 2, the forced, failable downcast operator as has been removed, and is replaced with as!, which is much Swiftier. The behavior is the same.
You can solve this warning from two angles. 1. The value you return 2. The type that you are expected to return. The other answer speaks about the 1st angle. I'm speaking about the 2nd angle
This is because you are returning a forced unwrapped and casted value for an optional. The compiler is like, "If you really want to just force cast all optionals then why not just make the expected return parameter to be a non-optional"
For example if you wrote
func returnSomething<T> -> T?{ // I'm an optional, I can handle nils SAFELY and won't crash.
return UIViewController as! T // will never return a safe nil, will just CRASH
}
Basically you told yourself (and the compiler) I want to handle nils safely but then in the very next line, you said nah, I don't!!!
The compiler would give a warning:
Treating a forced downcast to 'T' as optional will never produce 'nil'
An alternative is to remove the ?
func returnSomething<T>() -> T{ // I can't handle nils
return UIViewController() as! T // I will crash on nils
}
Having that said, likely the best way is to not use force cast and just do:
func returnSomething<T>() -> T?{ // I can handle nils
return UIViewController() as? T // I won't crash on nils
}
It looks like there is bug open about this warning fo some years now...
https://bugs.swift.org/browse/SR-4209 So it shows even in situations where it is obvious what you are doing and right.