When the user selects a row in my table, I need to load a bunch of data with CoreData. This takes several seconds (at least when running on the simulator - haven't tested on a device yet, but I imagine it will still be pretty long). I want to display a loading popover screen (I'm developing for iPad) when the user selects a row, then have it disappear once the data is loaded.
When working with UIButtons, I've always done this by triggering both a TouchDown and TouchUp method. I put the code to display the popover on the TouchDown, then do all my actual work (so in this case loading from CoreData) in the TouchUp. Then at the end of TouchUp, I close the popover.
Is there a way to split up touches in a table view the same way as ones on a button?
So while I was typing up the question I came across something in the Apple Docs for willSelectRowAtIndexPath and it looks like that is there to address this very issue. I didn't see any other topics on this on SO, so I figured I'd make use of this "Answer own question - Q&A" feature on here, so maybe people looking for this in the future will find it a little easier.
Huge FYI block:
I should note that willSelectRowAtIndexPath is actually supposed to return an NSIndexPath, unlike didSelectRowAtIndexPath (which returns void). However, I originally had
-(void)tableView:(UITableView *)tableView willSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
//stuff
}
Note the void return type. Xcode (Version 4.5) allowed this without any errors or warnings (and even had it for me in the autocomplete list). When I ran the code this way, I always hit an invisible breakpoint in libobjc.A.dylib'objc_autorelease: (maybe becaues I have the "All Exceptions" breakpoint enabled?). I couldn't get past this breakpoint, I never got any debug information in the debugger output console, and the app never terminated. I happened to look at the Apple Doc again and notice that it was supposed to return an NSIndexPath (specifically, the index path the code should interpret as being the one that was selected), but if I didn't happen to see it there, I never would have known what the problem was.
Related
My app is using a 2nd UIWindow to show a special screen if iOS wants to take a screenshot of the app.
By accident I used [UIWindow makeKeyWindow:] on my main window if I wanted to remove the 2nd window again. This really should be makeKeyAndVisible: instead but I'm wondering why it worked at all.
I mean: most of the time (99%), my 2nd window was removed as expected and my main window became visible.
I'm asking because I'm wondering if I have really found the problem or if there might still be something else?
Or could it be that the method was incorrectly bound in (previous) MonoTouch versions?
Each method maps to the selector of the same name makeKeyAndVisible and makeKeyWindow.
Or could it be that the method was incorrectly bound in (previous) MonoTouch versions?
GIT history shows (me ;-) that both never changed since they were first added (more than two years ago).
Documentation about the former states:
You can also hide and reveal a window using the inherited hidden property of UIView.
Maybe this happens in your code (or even within the iOS code).
I'm using Xcode 4.2 to write and Clang 3.0 to build a program that demonstrates a particular crash.
The program has a window that it means to keep around that is set in the nib to “Release When Closed”, so it's over-released in subsequent uses. It's meant to be a sheet, so it's shown using beginSheet:modalForWindow:modalDelegate:didEndSelector:contextInfo:. Trying to show the window a second or third time should crash the app.
I remember that happening a year ago, with the program receiving EXC_BAD_ACCESS and that triggering the debugger to stop at that point. I also remember being able to hunt the problem down in Instruments using the Zombies template.
That's what I want (this program is part of a presentation to show debugging techniques), but that's not what's happening now. Now, the program doesn't crash; Instruments shows that the retain count on the window gets down to 1 twice, but no lower, so it does not get deallocated.
That would be fine if the problem stopped there; I could simply hide and show the sheet another time or two. The problem is, the second time I bring up the (should-be-dead-but-still-has-at-least-one-retain-keeping-it-alive) sheet, it's numb.
By that I mean that neither the sheet nor any control in it (it contains a field, a text view, and two buttons) responds to events. The heartbeat does nothing in it; the window has an OK button, but when the window is numb, the OK button does not pulse. Nothing works to dismiss the sheet.
But the program is not crashed. I can still interact with the menus and the Dock shows that the program is responding. If I try to quit it, it beeps, since it has a sheet up.
What's causing the window to go numb, and what can I do about it?
Here's a reduced version of the program that also exhibits the problem: https://github.com/boredzo/NumbWindow
I don't think you should be using -close to make the sheet go away. If you change the [sheet close]; line to be [sheet orderOut:self];, then it works properly.
As for why they're different, I don't know. But my experience has been to always use -orderOut: to dismiss sheets, and never -close. The documentation backs me up on this:
Listing 3 Did-end selector
- (void)didEndSheet:(NSWindow *)sheet returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
{
[sheet orderOut:self];
}
tl;dr:
You're using the wrong method to make the panel go away.
UPDATE: With the blush of shame I discovered that the order had nothing to do with the speed of tapping. I was calling the visual code before the super touchesEnded:withEvent call, which was why if you tapped really fast, the display never got a chance to draw the highlighted state before being dismissed again. Because the code that was actually causing the main thread to block just a few milliseconds, the highlighted state would stay visible until the main thread unblocked again, where as if you tapped really fast, it looked like nothing happened at all. Moving the super call up to the top of the overridden method fixed it all. Sorry, if any moderator sees this post it can be deleted. shame
This problem must have been asked a 1000 times at SO, yet I can't find the explanation to match my specific issue.
I have a UIButton subclass with a custom design. Of course the design is custom enough that I can't just use the regular setSomething:forControlState: methods. I need a different backgroundcolor on touch, for one, and some icons that need to flash.
To implement these view changes, I (counter-intuitively) put the display code in (A) touchesBegan:withEvent and (Z) touchesEnded:withEvent:, before calling their respective super methods. Feels weird, but it works as intended, or so it seemed at first.
After implementing addTarget:action:forControlEvents was used to bind the UIControlEventTouchUpInside to the method (X) itemTapped:, I would expect these methods to always fire in the order (A)(X)(Z). However, if you tap the screen real fast (or the mouse in simulator), they fire in the order (A)(Z)(X). Where (A) and (Z) follow each other in such rapid succession, that the whole visual feedback for tapping is invisible. This is unwanted behavior. This also can't be the way to go, for so many apps need similar behavior, right?
So my question to you is: What am I doing wrong? One thing I'm guessing is that the visual appearance of the buttons shouldn't be manipulated in the touchesBegan:withEvent and touchesEnded:withEvent, but then where? Or am I missing some other well known fact?
Thanks for the nudge,
Eric-Paul.
I don't know why the order is different, but here's 2 suggestions to help deal with it.
What visual changes are you making to the button? If it's things like changing title/image/background image, you can do all this by modifying the highlighted state of the button. You can set a few properties like title and background image per-state. When the user's finger is down on the button, the highlighted state is turned on, so any changes you make to this state will be visible at this time. Do note that if you're making use of the selected state on the button, then you'll need to also set up the visual appearance for UIControlStateHighlighted|UIControlStateSelected, otherwise it will default back to inheriting from Normal when both highlighted & selected are on.
The other suggestion is to ditch touchesBegan:withEvent: and touchesEnded:withEvent: and switch over to using the methods inherited from UIControl, namely beginTrackingWithTouch:withEvent: and endTrackingWithTouch:withEvent:. You may also want to implement continueTrackingWithTouch:withEvent: and use the touchInside property to turn off your visual tweaks if the touch leaves the control.
I don't know how it happened, but all of a sudden in my table view I can't make an empty selection anymore. Like a table view row always has to be selected, and it can't be deselected by clicking somewhere else in the table view. I can select a different row, but I can't make an empty selection.
In the Interface Builder attributes for the table view empty selection is enabled, so I don't know where to look next. The one major change I made was that I installed OS X Snow Leopard. I'm not sure if this issue has something to do with that.
Thanks
I struck this exact same issue (I am using XCode 4.2 but compiling against the 10.6sdk). NSOutlineView::deselectAll just was not deselecting things. I have a fairly complex NSOutlineView which exhibits the same behavior. I had a look on the apple developer forums and other places to try and work around this issue. However in the end working around this for me was very simple and I could just use:
- (void) myDeselectAll
{
[self selectRowIndexes:[NSIndexSet indexSet] byExtendingSelection:NO];
}
Try doing it programmatically with the setter method setAllowsEmptySelection:. Alternatively, try disabling empty selection in IB, saving, then enabling it, saving one more time. That might fix it.
Also make sure that something in tableView:shouldSelectRow: isn't stopping you from it (provided you've implemented this delegate method).
This is a bit old, but for those who need an answer to this:
Use the interface builder and mark the array controller. remove checkmark "avoid empty selection".
If not done so, create an outlet for the array controller. Here I have called it DocumentArrayController.
then to empty selection:
[_DocumentArrayController removeSelectionIndexes:
[_DocumentArrayController selectionIndexes]];
Do you have your columns bound to an array controller? If so, check the controller's attributes.
I'm not allowed to say much more than this: It seems to be a problem with 10.6 specifically
Here is my scenario:
I am building a location finder using the iPhone mapkit. I have an array stored in the application delegate to hold the information about the location of a store (name, address, etc.). When a certain button is pressed, a view slides in with a textfield and a button which performs a lookup of the users input, and returns all of the necessary information.
All of this works fine and the points get plotted onto the map. However, if I go and try to do a search a second time, the application crashes. I am trying to remove all of the objects from the array when the xml parser begins:
- (void)parserDidStartDocument:(NSXMLParser *)parser {
[dataTempForSearch removeAllObjects];
}
and the debugger simply puts an arrow on the method call with no real explanation as to why...
Has anyone run into a scenario like this before? any thoughts as to why this might be happening only on the second time the action is performed?
It's hard to tell based on just that one line of code.
It's probably a memory management issue, but what specifically I can't say.
Shots in the dark:
I would destroy and re-create my parser each time I did a search.
I would also clear the dataTempForSearch immediately after passing the data to the app delegate, not right when you go to do another search.
MapKit has some very nasty problems. When you get that odd behaviour of the debugger putting an arrow at that line, take a look at the call stack provided to you (this can be seen in debug mode on the left side usually). I'll bet you it's to do with MapKit.