i am developing a book reader on ipad. i am using the swipe gesture to navigate to the next page. But my app is getting hanged on crashed when i try to navigate (swipe) at a fast pace. So, is there any way to restrict the number of continuous or consecutive swipes…???
Please help with me with your inputs. They will help me go a long way in my project. Thankyou
You could throttle the number of swipes you are handling by skipping say every third swipe or so). However, that would just add frustration for the user, as they'll be swiping and nothing would be happening. And if you actually go that route, at least add a wait cursor, so that the user is aware the app is busy.
However, you really should figure out why the app is crashing (or hanging - not clear from your question) and fix it. If the user wants to leaf quickly through the pages, you should let them.
Use a flag that keeps track of when you are paging. When you swipe, only trigger the paging mechanism if the flag is NO, and immediately set it to YES when paging. When your paging mechanism finishes, set it back to NO.
Related
I have implemented a client for a paginated REST service where I populate the whole table with empty entries and then load them in the background using pagination when the user starts scrolling the table.
This seems to work very well except for a little detail: I am calling reloadRowsAtIndexPaths: in the main UI thread (because UIKit requires so), and I feel the animation sometimes makes me lose input touches.
This is, the user starts scrolling through the list and items start to load. Sometimes a reload animation happens at the same time the user is just touching the screen again, and this touch is not recognized. The scrolling then doesn't continue and stops. It doesn't happen all the time, and I guess it is an infrequent user case (the user is expected to read each row of results before scrolling down) but it annoys me to no end.
I'm doing most of my animations with blocks and the flag UIViewAnimationOptionAllowUserInteraction is really helpful, so is there a block version of reloadRowsAtIndexPaths where the reload animation would not block the user interaction with the scrolling?
I think the solution you seek is to background-load your data in a thread (as you describe) and only call reloadRowsAtIndexPaths: once the data is received and ready to display. You should also probably redisplay the data NOT animated.
I don't think there's anything you can do to get around the missed touches with your current scheme. My suggestion is to "do what iOS wants" rather than "try to cajole iOS to do what you want." Yes, probably not the answer you wanted to hear, but I think that's just the way it works.
(Btw, you can always use bugreporter.apple.com to make an enhancement request! :)
I'm trying to investigate a very long start up time for my app and could use some help. It takes about 6-7 seconds to start up and that's just FAR too long. I'm not loading any data sets or anything, but the app is a calculator so my xib does have lots of buttons and button images.
I'd like to use Instruments (or something else) to analyze where all of the time is being spent so that I can optimize, but the documentation for Instruments isn't really giving me much on specifics of how to use it for this specific problem and/or how to interpret the results.
Do you have any suggestions for how to test this? A pointer to a tutorial on how to use Instruments for this? An iTunes U video or something else?
Any suggestions are welcome!
Kenny
Palimondo asked how I eventually solved my problem... it was a bunch of small changes and I'm not truly sure where the savings came in to play and I'll explain why below.
My app is a calculator, so it has a ton of buttons. I thought at first it must be the button loading causing the problem, but as I explained in the comments above to Paul, even if I loaded 0 buttons, that only shaved 1 second off of the start up time. After changing many small things, I was able to save 3 seconds off of start up time which was good enough.
I had a background image that was a nice textured-gradient-ish image. I reduced the file size on it (changed the texture, exported it with different options).
I went from loading 100 buttons up front (it's a calculator) to loading about 15, but attempted to do it in a secret fashion so the user wouldn't notice. About 50 of the buttons aren't visible to start anyway because you have to tap a Shift button to see them, so they were easy to lazy-load. The others are visible, but I figured that the user isn't going to tap most of those right at start-up because they need to hit some numbers first. So I left all of the number pad buttons and the Clear button in the xib so they are loaded on start up but removed everything else from the xib.
That left me with a big blank area on the screen and you could actually see the buttons filling in the blank area as I lazy loaded them (filling very quickly, but you could see the blank area and then all the buttons appear). So I updated the background gradient graphic to include images of the buttons. The buttons appear to be there, but they aren't, so unless the user taps a fake button within 2 seconds they never notice a problem... and usually they just try to tap that button again anyway and by then it usually has been lazy-loaded and therefore works.
Before doing any of the above suggestions:
Is this 6-7 seconds while running from XCode? Or from starting directly by tapping it on the iPhone?
Debuggers and instruments won't help you much here, since they just add to the overhead, and won't help as much in profiling because it poisons the data you'll see.
Edit:
In terms of profiling tools, you may want to look into using Shark:
http://www.switchonthecode.com/tutorials/using-shark-to-performance-tune-your-iphone-app
It's pretty simple to use in general. It's sorta self-explanatory.
Here are couple of suggestions:
do you need all those buttons loading up at once?
do you (over)use transparencies in your images?
are the images the exact size required? Stretching (resizing) takes time to compute
do you perform any operation that is blocking the main thread?
I would measure the startup time of an empty dummy app (maybe the XCode Window-based app template) on your actual device (debugger disconnected). Then start adding your initialization code, views and objects from your app into this dummy app until you find what's slowing the startup time the most.
I have an issue with one of my c# applications, it has a single form which is stretched over two monitors and works fine, however if I lock the screen and come back to it, the application reverts to a single screen view.
I was wondering if anyone had come across something like this before or knew why this was happening?
thanks
I think this happens because the second screen is disabled during the desktop is locked.
If you now log in again, the form will reinitialize it's position before the second monitor is activated again.
This small article might help you, to solve the problem :)
I have used to loading a default image in my appication. So i have set to,
Sleep(3); in my delegate.m class.
But sometimes it will take more than 6 to 7 minutes. So i want to display the image 3 seconds only and then it goes to my appilcation based on my requirements.
Which one is best way to do that?
Sleep(3) or [NSThread sleepForTimeInterval:3.0] or something else;
And i must display the image 3 seconds only. Please explain me.
(Note: And I declared setter and getter methods only in my deleagte class.)
Please explain me.
As Rob noted, Apple strongly recommends against a splash screen unless it hides some necessary behind the scenes process (like loading game graphics.) It is so strongly discouraged that some people have claimed that their apps have been rejected for using an unnecessary splash screen.
The default.png doesn't exist to create a splash screen. Instead it exist to allow you to create the illusion that your initial view loads faster than it does. You supposed to use it to provide an image of your initial view so that the enduser can begin to cognitively orient themselves to the interface. By the time they have oriented themselves to the interface and moved their finger to touch the interface, it is live.
Why? Because iPhone apps are supposed be quick in, quick out. People don't sit down to use them at a desk like a desktop. People use then on the go. Sometimes they use them in the middle of a conversation.
I tell my clients to test out the usability of their apps (except for games) while walking, riding an exercise bike etc as well as in the middle of a face-to-face and phone conversation. In those circumstances, a three second pause is a big deal and very noticeable especially if the app is a practical app. Imagine if every time you opened the Contact app you had to pause three seconds to see an Apple splash screen. You would get peeved in a hurry.
The key thing here is that an unnecessary splash screen doesn't add any value for the user. It is a selfish act on the part of the software publisher to eat the end users time so that the publisher can build brand recognition for the sole benefit of the publisher. Wasting three seconds of the users time every time they use the app adds up in a hurry. (In my experience, it also makes the user perceive that the overall app is slow and clunky.)
However, if you do want to shoot yourself in the foot or if you have a client hell bent on a splash screen, you do it like this:
The splash screen appears until the first view loads so you delay the loading of the first view. In the app delegates applicationDidFinishLaunching: method, remove all the code that loads the first view into the window. Replace it with a NSTimer. Put the code to load the first view in the timer's fire method.
With that setup the app will display the default.png as it launches, when it gets to applicationDidFinishLaunching:it will appear to pause from the end users perspective because no view will appear to replace the default.png.
You should note that the standard launch time for an app is 3-5 seconds. So you may not have to do anything to show the splash screen for 3 seconds. It might happen automatically.
Apple strictly recommends against this (using sleep in this way), especially in the scenario of showing a splash screen.
The best thing to do is create a view that looks like your Default.png file, then have that be the first NIB.. you could then set an NSTimer to transition (with animation if you want) to your main view/window/controller.
I have disabled interactions in my primary view (which contains some subviews I use as buttons).
I keep this disabled while I have a secondary view up indicating network activity (loading data). When it is finished, I re-enable interactions in the primary view.
This is so the user isn't tapping those buttons while the network operation takes place.
Anyway, all seems well, but the if the user starts tapping buttons in the primary view, once the re-enable occurs those touch events (from the past few seconds) actually trigger. Not the touches-began, which highlights the buttons, but the functions called on the touches-ended. Its like its queued the whole time it was disabled and "races to catch up".
It is very bizarre, why would touch events be queued while the view has its user interaction disabled?
It's hard to be confident of an answer here without seeing the code, but here is one idea:
If your network activity is synchronous, aka blocking, then it could be the case that the user's touches are queued before they get a chance to hit any of your code. If that's the case, then those touches won't be sent into your responder chain until the network activity finishes, and they'd never get a chance to "know" that you'd disabled interaction with those controls.
Here's one way you could help debug your situation: Add some debug NSLog statements in the top layer (what you call the secondary view) that's indicating network activity. Make sure the secondary view's frame is big enough to include those touches, and see if it logs the touches as soon as they happen. If not, my guess might be correct. If yes, well, you still get useful information - and you might be able to simply capture the touches at this level, instead of allowing them to queue up.
If this guess is correct, the least hacky fix I can think of would be make your network operations asynchronous.
If you don't want to do that, you could also try using an NSTimer to leave the network activity indicator up for a split second after the synchronous call completes. This way, your responder chain could clear out the queue of incoming touches, and ignore them if that's the desired behavior.