I finished building a small app with audio, clicking "next" button will play a sound and take me to the next page, clicking "back" will play a sound and take me back to the previous page. But if I do the next, back twice, the simulator crashes and I receive the below message from the log. Anyone can help please, cheers.
the message is: * Thread1: Programme received signal: "EXC_BAD_ACCESS" *
while the code does compile well and I can turn the pages (41 in total).
This error is most always caused by trying to call a method on an object that has already been deallocated. One way to diagnose this issue is to use the Zombies template in Instruments. It will give you a dialog (with the call stack) when you message a deallocated object. No matter what the exact cause, this is most certainly related to your memory management.
This is a guess.
You said that it crashes if you click next, then back twice.
I'm assuming that you keep the pages in an array, correct? If so, by clicking back twice you are trying to load a page with an index of -1. An array doesn't have an object at the index -1.
If I'm right, All you have to do is this:
// In the back button code:
if(currentPageIndex - 1 < 0) {
// Dont go back
} else {
// Go Back
}
Related
I'm creating a SwiftUI multiplatform app in XCode and I have a section of my code that hangs. I want to update the user so they know what's happening and are willing to wait. I originally planned to have an alert with text that changed and then planned to have a Text element that updated. In both cases this isn't shown until after the code executes and as such only shows the final message (normally the success done message unless an error made it end sooner).
Is there anyway I can have a visible message to the user through an alert or SwiftUI element that is updated right away and thus will be helpful?
The fact that the alert isn't even shown until after the code executes is bad and incorrect. This suggests that you are doing something lengthy on the main thread, and that is an absolute no-no. You are freezing the interface and you risk the WatchDog process crashing your app before the user's very eyes. If something takes time, do it in the background.
I'm working on a screen in my app that allows users to leave comments. Additionally, they can view previous comments by tapping a button. The most recent comments are always at the end of the comments list, and the oldest at the top.
When the view more button is tapped, I fetch 10 previous comments from the database. My fetching code looks like this:
func fetchMoreComments(for gameId: Int, isLoadingMoreComments: Binding<Bool>) {
guard self.canLoadMoreComments else { return }
APIManager
.CommentsAPI
.getMoreComments(for: gameId, lastCommentId: self.lastCommentId!)
.sink(receiveCompletion: { completion in
print("load more comments completion:", completion)
},
receiveValue: {[weak self] response in
if response.statusCode == 200 {
// self?.comments.reserveCapacity((self?.comments.count)! + response.items.count)
let comments = response.items
if let lastCommentId = comments.map({ $0.id! }).min() {
self?.lastCommentId = lastCommentId
}
self?.comments.insert(contentsOf: comments.sorted(), at: 0)
isLoadingMoreComments.wrappedValue = false
self?.canLoadMoreComments = response.items.count >= 1
}
})
.store(in: &subscriptions)
}
Also, I should mention, when the screen is first loaded, there is another function I use to pull the 3 most recent comments to display on the screen the first time the user loads that particular screen.
The problem
As more comments are loaded, the navigation slows down. What I mean is, if I tap the back button to go back to the previous screen, there is a delay of about 4-5 seconds before I'm actually taken back to that screen. The reverse also has the same problem. It takes about 4-5 seconds to load the screen with the comments.
What I've tried
1)
I spent days sorting out memory leaks and cleaning up my code as I tried to find the problem. What I found was that, if I commented out the forloop that reads the array from my view model (the one function I pasted above lives in), then the laggy navigation issue disappears. I've pasted the forloop below. I've tried using .id from my commments object and also .self to improve the performance, but it didn't make a difference.
ForEach(self.liveGameViewModel.comments, id: \.self) { comment in
LiveGameCommentCell(comment: comment)
}
.id(UUID())
2)
I further narrowed things down to a NavigationLink inside the LiveGameCommentCell. That navigation link was a link to the commenter's profile screen. I noticed, once I commented out this navigation link, the navigation lag was partially cured. I could load up to 100 comments (10 at a time), then leave the screen (there would still be a few seconds of lag), however, once navigating back into the screen with the comments, the lag would be completely gone.
3)
Since I could no longer use the navigation, I decided to use a sheet to present a user's profile screen instead. Here's where I noticed another issue, or maybe just the same issue I've had all along. I would load the screen with the comments, and tap on a commenter's image, and the sheet would present itself with no lag. I'd then dismiss the sheet and load a few more comments and tap another commenter's profile image. I noticed, the more comments I loaded, the longer the sheet would take to present itself.
4)
Next, I decided to tweak how many comments are pulled from the database initially. I upped the limit to 100. Without loading more comments, I tapped on a commenter's profile image again, and the lag was there again. The problem is definitely related to the comments.
5)
I tried setting Swift array's reserveCapacity(_:) to 10 on the initial load of comments, then each time more comments were loaded, I'd set the capacity to the current number of comments in the array + the number received in the response. This didn't make much of a noticable difference.
I can't seem to track down this issue, but I know it's directly related to the number of comments on the screen. The more comments there are on the screen, the longer the sheet takes to present, or the longer it takes to navigate back to the previous screen.
I've refactored my code and fixed memory leaks I encountered. Most of the view models related to each screen only live for the life of that screen. For example, when a screen is dismissed, the view model is deinitialised.
Inside instruments, LiveGameCommentCell has the highest count and total duration. The count increases as I load more comments.
What could be causing this issue? I use the same type of functionality on other screens and don't have this issue. The only difference is, the other screens are entirely lists which contain foreach loops, whereas this problematic screen, is made up of the 2 images (host, challenger), some game info, such as, a short descriptive sentence, a deadline, comment count, the category, and then underneath all of this, a section for the list of comments and a text view to post new comments.
I even changed things around so that the API response for the comments would provide all of the info I would need for the comments, rather than utilising foreign keys and making multiple requests from the app. Everything that is needed is delivered in the getMostRecentComments and getMoreComments requests.
There were a few memory leaks I didn't get around to solving because they are most likely related to something else because they show regardless of visiting the screen that shows comments.
Also, I noticed when I first arrive the screen that shows the comments and tap a commenter's profile image, there are no errors. If I tap the next set of 10 comments that are loaded, there are no errors, but as the lagging increases, I notice an error starts to show when I tap on commenter's images. The error is:
[Common] _BSMachError: port 1c433; (os/kern) invalid capability (0x14) "Unable to insert COPY_SEND"
I'd really appreciate some clues that may help me solve this issue. At present, it's not at all obvious to me what is causing this issue.
Thanks in advance
I had a ForEach loop inside a ScrollView, and not inside a List. Replacing the ScrollView with a list, and wrapping my NavigationLinks inside a LazyView solved the issue.
i found like my question answers, but my app stil not working.
I push view to controller-2 from controller-1. In controller-2 Restkit loading data, but not loaded, i quickly press back button to controller-1 and after few seconds app is crushing (Restkit loaded data).
I using ARC.
Please help me fix this problem. Thank you.
This happens because RestKit continues the network activity and then cannot find your controller since it has been closed and its location in memory deallocated. I'd suggest either adding some logic to prevent the user from hitting back while RestKit is loading data, or canceling all pending network requests like mja suggested.
One way to do this is to add the following line to viewDidUnload:
[[[[RKObjectManager sharedManager] client] requestQueue] cancelRequestsWithDelegate:self];
I made my project in storyboard in, due to issue with the custom UITableViewCell I have made a new project, copied all of the data to my new classes and copied my buttons, images etc from the storyboard views to new project's nib/xib files.
Now When I click on any button my app crashes without any error and it opens delegate file and highlights this line of code
return UIApplicationMain(argc, argv, nil, NSStringFromClass([ThisOrThatAppDelegate class]));
I have already made connections for the required actions from IB to controller. Also I have tried Command+Shift+K for clean code. But the problem is still there.
You have to find out first what the problem is:
use the Debug build config and are using lldb or gdb
make sure you have a breakpoint on all exceptions
make sure you have the "Breakpoints" button top left enabled.
run the app
You should break into the debugger. You need to get to a point where the debugger catches the exception.
Then edit your question and tell us what exception you get. I'm going to guess you'll be getting a objc_msgSend() error, which means that some object is trying to message a non-existent or dealloced object. If that turns out to be true, then you can enable "Zombies" (which lets all objects stay around) and see if one of those gets messaged.
If nothing seems to help, then what you need to do is start adding NSLog messages to track your app as it comes up (or use breakpoints, your choice). This takes a long time so you might work backwards - see if your appDelegate application:didFinishLaunchingWithOptions: gets called, and also if you get to the end of it.
Unforunately this type of problem can be take a lot of time to track down. Some object has probably queued a message up for another object on the main queue, so when you get the crash you don't get to see who did what when.
Also, with objc_msgSend problems, when the debugger stops you cannot easily see what object was messaged - but if you turn off the debugger and let the app actually crash, you can find the crash report in the Console app and get more info from that.
I have an iphone app with a modal view. The app crashes when the modal view get dismissed.
As soon as the modal disappear at the bottom of the screen, and consequently the original view is shown behind, then the app crashes with no entry in console view.
I have tried to switch debugger on and I discovered that the app just run fine, with no crashes at all.
-First, I would like to know why such behaviour, shouldn't the debugger sit just on top without "disturbing" the app ?
-Second, without debugger, can you point out what should I look at to solve my problem ? Or if you encounter something similiar ? Please be as much specific you can, because I am not an expert in objective-c programming.
I don't know what details to give you, the app is a normal one with standard iphone component, but for start I can say the modal view (which is built with IB) is called inside a NavigationBar system.
thanks
When these types of things happen, it is almost always because of memory allocation issues. The first step I would take is to do a "Clean All" and a "Build and Analyze", and look at all the analysis warnings. Analyze is very good at finding basic "use before allocate", "use after deallocate", or "wrong number of retains/releases" types of problems.
The next step is to turn on "Zombie" detection mode, which looks for accesses on memory that has already been deleted (in other words, killed objects coming back from the dead.) To do this, get info on your executable, go to the Arguments tab, and add a "variable to be set in the environment" of "NSZombieEnabled" to value "YES". Then look in the console when you run to see if something looks off.
Finally, you might try creating a new configuration where you use all the release mode settings for optimization, but add debug symbols. Maybe that will shake up the allocation disbursement in memory enough to trigger the bug in debug mode.