NSException Error - Swift 4 [duplicate] - ios

This question already has answers here:
Main Thread Checker: UI API called on a background thread: -[UIApplication applicationState]
(6 answers)
Closed 5 years ago.
stack overflow community. Please don't mark this question as a duplicate as I have seen all the other posts regarding this and have pretty much gone through most of the famous solutions.
Currently, I have some code that allows a user to send messages to a group and also change the group thumbnail and title. However, upon the user doing any of this, my code crashes. I am storing my data in firebase (the data is being successfully uploaded). The problem began when I upgraded from swift 3 to swift 4. Also, this is the specific error I am getting:
libc++abi.dylib: terminating with uncaught exception of type NSException
Here are some solutions/methods I have tried to solve my problem:
I have outruled that this is an outlet problem as the view controller is programmatically created.
I tried adding an exception breakpoint but it didn't show me any specific lines of code for where the crash occurred.
I have also tried cleaning, re-building, and closing Xcode however that doesn't work as well.
I don't think its a problem with uploading data to firebase as I am able to in other parts of my app.
I have also tried scrolling through the threads to get a deeper understanding of where the crash occurs, however that has not been of much help.
Here is a picture of my console output:
Here is the code I use to update the collection view:
func observeConversationMessagesWithConversationId(conversationId: String) {
Database.database().reference().child("conversation-messages").child(conversationId).observe(.childAdded, with: { (snapshot) in
if let messages = ConversationMessages(snapshot: snapshot) {
self.conversationMessages.append(messages)
DispatchQueue.main.async(execute: {
self.collectionView?.reloadData()
let indexPath = NSIndexPath(item: self.conversationMessages.count - 1, section: 0)
self.collectionView?.scrollToItem(at: indexPath as IndexPath, at: .bottom, animated: true)
})
}
}, withCancel: nil)
}
Here is my podfile
Any help would be appreciated. Please note that I would have added some code but I have no clue where the error occurs.

Since you don't know where the error occurs, it might be a good idea to place a few breakpoints in your code so you can pinpoint the crash. Then it will be a lot easier to fix the error when you know the exact line where it happens.
I had the same crash and it was related to UIVisualEffectView, and specifically with adding a subview to it instead of adding it to its .contentView.
If that is your case too, you can find more details here.
Good luck bug hunting.

Related

SwiftUI: app crashed with "UITableView internal inconsistency" error

Update: After spending several hours doing experiment, I finally identify the root cause. See this. I'll close the question.
My app crashed with "UITableView internal inconsistency" error in a random manual testing. Below is the error message (I removed the stack trace because it's long).
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView internal inconsistency: encountered out of bounds global row index while preparing batch updates (oldRow=2, oldGlobalRowCount=2)'
The error usually occurs in UIKit apps. In my SwiftUI app, however, I don't deal with UIKit directly, it's SwiftUI that does it. So my first thought was that this was a bug in SwiftUI. But this is a very basic error (it was an "out of index" error). That, plus the fact it occurred after I made a minor change to the app, makes me not sure. I wonder if anyone saw this issue in your app? Could it be caused by the an incorrect way of doing SwiftUI programming?
More information:
This was first time I observed the crash. I observed it more than once since then but couldn't reproduce it consistently, not to mention provide a simple example to demonstrate it.
I first observed the crash after I made a minor change to my app (though I'm not sure if the change is relevant). The purpose of the change it to generalize the code to implement a custom binding. In the old code, the custom binding reads/writes data by capturing data in closure. In the new code, the custom binding reads/writes data through another binding (could the use of that additional binding cause the issue?). The text field is in a form. The crash occurred when I clicked save button in the form.
Old code:
#ObservedObject var param: Param
...
TextField("Notes", text: Binding(
get: { param.notes ?? "" },
set: { param.note = ($0 != "" ? $0 : nil) } ))
New code:
func nonOptionalText(_ value: Binding<String?>) -> Binding<String> {
return Binding() {
value.wrappedValue ?? ""
} set: { newValue in
value.wrappedValue = (newValue != "" ? newValue : nil)
}
}
...
#ObservedObject var param: Param
...
TextField("Notes", text: nonOptionalText($param.notes))

Crashlytics iOS - Crash at line 0 - Swift sources

I'm currently facing a problem with some Swift source files when a crash occurs. Indeed, on Crashlytics I have a weird info about the line and the reason of the crash. It tells me the source has crashed at the line 0 and it gives me a SIGTRAP error. I read that this error occurs when a Thread hits a BreakPoint. But the problem is that this error occurs while I'm not debugging (application test from TestFlight).
Here is an example when Crashlytics tells me there's a SIGTRAP Error at line 0 :
// Method that crashs
private func extractSubDataFrom(writeBuffer: inout Data, chunkSize: Int) -> Data? {
guard chunkSize > 0 else { // Prevent from having a 0 division
return nil
}
// Get nb of chunks to write (then the number of bytes from it)
let nbOfChunksToWrite: Int = Int(floor(Double(writeBuffer.count) / Double(chunkSize)))
let dataCountToWrite = max(0, nbOfChunksToWrite * chunkSize)
guard dataCountToWrite > 0 else {
return nil // Not enough data to write for now
}
// Extract data
let subData = writeBuffer.extractSubDataWith(range: 0..<dataCountToWrite)
return subData
}
Another Swift file to explain what happens at the line "writeBuffer.extractSubDataWith(range: 0..
public extension Data {
//MARK: - Public
public mutating func extractSubDataWith(range: Range) -> Data? {
guard range.lowerBound >= 0 && range.upperBound <= self.count else {
return nil
}
// Get a copy of data and remove them from self
let subData = self.subdata(in: range)
self.removeSubrange(range)
return subData
}
}
Could you tell me what I'm doing wrong ? Or what can occurs this weird SIGTRAP error ?
Thank you
Crashing with a line of zero is indeed weird. But, common in Swift code.
The Swift compiler can do code generation on your behalf. This can happen quite a bit with generic functions, but may also happen for other reasons. When the compiler generates code, it also produces debug information for the code it generates. This debug information typically references the file that caused the code to be generated. But, the compiler tags it all with a line of 0 to distinguish it from code that was actually written by the developer.
These generic functions also do not have to be written by you - I've seen this happen with standard library functions too.
(Aside: I believe that the DWARF standard can, in fact, describe this situation more precisely. But, unfortunately Apple doesn't seem to use it in that way.)
Apple verified this line zero behavior via a Radar I filed about it a number of years ago. You can also poke around in your app's own debug data (via, for example dwarfdump) if you want to confirm.
One reason you might want to try to do this, is if you really don't trust that Crashlytics is labelling the lines correctly. There's a lot of stuff between their UI and the raw crash data. It is conceivable something's gone wrong. The only way you can confirm this is to grab the crashing address + binary, and do the lookup yourself. If dwarfdump tells you this happened at line zero, then that confirms this is just an artifact of compile-time code generation.
However, I would tend to believe there's nothing wrong with the Crashlytics UI. I just wanted to point it out as a possibility.
As for SIGTRAP - there's nothing weird about that at all. This is just an indication that the code being run has decided to terminate the process. This is different, for example, from a SIGBUS, where the OS does the terminating. This could be caused by Swift integer and/or range bounds checking. Your code does have some of that kind of thing in both places. And, since that would be so performance-critical - would be a prime candidate for inline code generation.
Update
It now seems like, at least in some situations, the compiler also now uses a file name of <compiler-generated>. I'm sure they did this to make this case clearer. So, it could be that with more recent versions of Swift, you'll instead see <compiler-generated>:0. This might not help tracking down a crash, but will least make things more obvious.

Firebase storage imageReference.delete{ (error) in } method crashing my app with "signal SIGABRT"

I'm using:
iOS - Swift 4
Cocoapods 1.4.0
Firebase (5.4.0)
FirebaseCore (5.0.5)
FirebaseStorage (3.0.0)
When I'm running the attached code, my app crashing with signal SIGABRT error at the AppDelegate class and prints libc++abi.dylib: terminating with uncaught exception of type NSException in the console.
I'v tried to run some debugging and what I found is that the problem occurred in the imageReference.delete{ (error) in } method.
*Note that it didn't enter to the block at all, it failed in the method itself and because of that the image is not deleting from Firebase console when I'm calling to the delete method.
My code:
func deleteImage(for url:String){
print(url) // https://firebasestorage.googleapis.com/v0/b/my-app.appspot.com/o/itemsImages%2F225121501531684886976.jpg?alt=media&token=token
let imageReference = Storage.storage().reference(forURL: url)
imageReference.delete { (error) in // Fails here with: libc++abi.dylib: terminating with uncaught exception of type NSException
print("completion") // Not getting to this point
if let error = error{
print(error)
}
}
}
Edit:
After very deep digging I'v understand that my problem is that I'm calling this method via closure at some point of the "events' tree" (I'm calling some function that calling to another function that calling to the delete method from closure) and thats what cause the problem.
Now the question is how can I call it via this closure without make this error? (I can't call it outside of it)
I'd start by asking if you have a strong reference to that image somewhere else ?
Or is the image being used in a UIImage Control?
At the end the problem was with the UITableView itself and not with Firebase.
I didn't update the UITableView's data array correctly and that produced this crashing. I wasn't aware of it because the errors in xCode's console were disabled from some reason (Those answeres helped me to enable it back: #1, #2).
Hope anyone else that will face with wired error like that (without enabled error logs, of course) will be able to use my unpleasant experience and find the solution faster and easier.

Setting cachePolicy of a parse query crashes application

I'm developing in Swift using the latest version of Parse from the website. I am attempting to set my cache policy to the NetworkElseCache value, which is displayed below:
let userRelation = User.currentUser()?.relationForKey("friends")
let userQuery = userRelation!.query()
userQuery.cachePolicy = .NetworkElseCache
userQuery.findObjectsInBackgroundWithBlock {
(users, error) -> Void in
print("Success")
}
The error occurs on the line:
userQuery.cachePolicy = .NetworkElseCache
and if the line is removed, the application runs fine, the error produced is:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException',
reason: 'Method not allowed when Pinning is enabled.'
I really don't have any idea what to do from here, I only started iOS development about a week ago using Parse and Swift, so I'm a bit on the lost side. I don't understand the callstack either, or how it will help me find my problem.
Disable the LocalDataStore in your AppDelegate.m
So comment following line
Parse.enableLocalDatastore() // Comment this line and try
Here's the full explanation from the engineers at Parse. But yes, long story short, if you're using local datastore, you will not be able to also use different cache policies.

UITableView internal bug: unable to generate a new section map with old section count: and new section count: with userInfo (null)

I haven't seen this error before, and I did a search as to why it may be happening but couldn't find any info on it:
CoreData: error: Serious application error. An exception was caught
from the delegate of NSFetchedResultsController during a call to
-controllerDidChangeContent:. UITableView internal bug: unable to generate a new section map with old section count: 1 and new section
count: 0 with userInfo (null)
Does anyone know what might be happening here? I am not sure about the "internal bug" part - does this error indicate a problem with my code or a bug in UITableView?
Stephan already mentioned this in a comment on the original question but I thought it was worth sharing some code. This answer was actually sourced from a comment made by user GERUB on a thread on the apple dev forums found here: https://forums.developer.apple.com/thread/9964
if tableView.numberOfRowsInSection(indexPath.section) == 1{
tableView.deleteSections(NSIndexSet(index: indexPath.section), withRowAnimation: .Automatic)
}else{
tableView.deleteRowsAtIndexPaths([indexPath], withRowAnimation: .Automatic)
}
I have tested this inside of the NSFetchedResultsControllerDelegate method implementations and it works perfectly.
Did you use this NSFetchedResultsController in multiple UITableView. If so, that's the cause. Use one NSFetchedResultsController for one UITableView. Do not just switch queries when switching views.
When using CoreData with the NSFetchedResultsController you don't really need to mess about with checking to see if it's the last item in a section that you are deleting.
You can simply utilise another of NSFetchedResultsControllerDelegate's methods: controller(: NSFetchedResultsController<NSFetchRequestResult>, didChange: NSFetchedResultsSectionInfo, atSectionIndex: Int, for: NSFetchedResultsChangeType).
This delegate method will specifically inform you when a section is added or removed and you can then act accordingly, allowing you to have simpler code.

Resources