Tricky performance problem about UIButton's in UITableViewCell (iPhone) - iphone

I'm going to implement a view similar to the original photo app in iOS.
I created a customized UITableViewCell which has 4 UIButton in it. And it updates the button's image when the image array of the cell changed.
I worked hard to get the performance really satisfying. However, I found a tricky lag problem about it.
When I use my app normally, the scrolling is very smooth without significant lag. But if I keep the app (simulator) running on the "thumbnail grid view", and switch to other applications in Mac OS. After a while (maybe about 1 minute), when I switch back to the simulator, the scroll view gets stuck. It's hard to scroll it. If I click on something switching to another view and then switch back, everything is smooth again. So tricky.
I also tried the TTRemoteExamples which uses three20 to implement the grid view. It also gets stuck after switching between different applications in Mac OS (not in the iOS).
Then I tried not filling the customized cell with UIButton but 4 images. It didn't get stuck. So maybe the reason lies in the conflict between UITableViewCell and UIButton?
I don't know if it only happens on simulator or have potential performance problem when shipped to device (I haven't got the device to test on).
Apple's photo app will never be like this.
So I'm going to implement it from UIScrollView by myself to see if the problem is caused by the UITableView's mechanism. I still want to know the reason for the lag if anyone has come to it and solved it.
Sorry for my poor English, I hope you can catch my meaning.

Who cares what the simulator does, seriously. Let it fart magical evil fairies that hijack the world's financial system causing it to enter a world of collapse...oh wait, maybe it already did that.
Seriously though, look at using code like AQGridView. It's very stable, provides an interface very much like a tableview, and is used in many projects. You also avoid the nonsense that is Three20 going this route. It's win-win.
But remember, always, and I do mean always, care what your app does on a device, if it isn't doing the same thing on the simulator, don't worry about it, you shouldn't be testing on the sim 99% of the time anyway. Users interact with your app on their devices, not your simulator. :)

Referring to Subclassing UITableViewCell section in Table View Programming Guide for iOS,
I finally solved the problem by implementing my custom mimicking the way from the guide, without adding subviews to UITableViewCell.
Apparently, adding too many subviews, only 4 in my code although, caused the strange problem I mentioned above. So, NEVER ADD SUBVIEWS, especially those with UIImageView's in it, to the contentView of UITableViewCell or UITableViewCell itself.
Instead, keep data's in the customized UITableViewCell, and do every drawing related thing in drawRect, using -[UIImage drawAtPoint:] and -[NSString drawAtPoint:withFont:].
In fact, the Apple's guide has mentioned it. It's careless of me skimming the part.
However, I'm still curious about why, as I mentioned, it only occurs when you switch between applications in your Mac OS, not iOS. I don't know the reason indeed.

Related

Rendering a preview of a UIView in another UIView

I have a very intriguing obstacle to overcome. I am trying to display the live contents of a UIView in another, separate UIView.
What I am trying to accomplish is very similar to Mission Control in Mac OS X. In Mission Control, there are large views in the center, displaying the desktop or an application. Above that, there are small views that can be reorganized. These small views display a live preview of their corresponding app. The preview is instant, and the framerate is exact. Ultimately, I am trying to recreate this effect, as cheaply as possible.
I have tried many possible solutions, and the one shown here is as close as I have gotten. It works, however the - (void)drawLayer:(CALayer *)layer inContext:(CGContextRef)ctx method isn't called on every change. My solution was to call [cloneView setNeedsDisplay] using a CADisplayLink, so it is called on every screen refresh. It is very near my goal, but the framerate is extremely low. I think that [CALayer renderInContext:] is much too slow.
If it is possible to have two CALayers render the same source, that would be golden. However, I am not sure how to approach this. Luckily, this is simply a concept app and isn't destined for the App Store, so I can make use of the private APIs. I have looked into IOSurface and Quartz contexts, but I haven't been able to solve this puzzle so far. Any input would be greatly appreciated!
iOS and OSX are actually mostly the same underneath at the lowest level. (However, when you get higher up the stack iOS is actually largely more advanced than OSX as it is newer and had a fresh start)
However, in this case they both use the same thing (I believe). You'll notice something about Mission Control. It isolates "windows" rather than views. On iOS each UIWindow has a ".contentID" property and CALayerHost can use to make the render server share the render context between the 2 of them (2 layers that is).
So my advice is to make your views separate UIWindows and get native mirroring for free-(ish). (In my experience the CALayerHost takes over the target layers place with the render server and so if both the CALayerHost and the window are visible the window won't be anymore, only the layer host will be (which the way they are used on OSX and iOS isn't a problem).)
So if you are after true mirroring, 2 copies of it, you'll need to resort to the sort of thing you were thinking about.
1 Option for this is to create a UIView subclass that uses
https://github.com/yyfrankyy/iOS5.1-Framework-Headers/blob/master/UIKit.framework/UIView-Rendering.h#L12
this UIView private method to get an IOSurface for a target view and then using a CADisplayLink once per second get and draw the surface.
Another option which may work (I'm not sure as I don't know your setup or desired effect) is possibly just to use a CAReplicatorLayer which displays a mirror of a CALayer using the same backing store (very fast and efficient + public stable API).
Sorry I couldn't give you a fixed, "this is the answer reply", but hopefully I've given you enough ideas and possibilities to get started.
I've also included some links to things you might find useful to read.
What's the magic behind CAReplicatorLayer?
http://aptogo.co.uk/2011/08/no-fuss-reflections/
http://iphonedevwiki.net/index.php/SBAppContextHostManager
http://iphonedevwiki.net/index.php/SBAppContextHostView
http://iphonedevwiki.net/index.php/CALayerHost
http://iky1e.tumblr.com/post/33109276151/recreating-remote-views-ios5
http://iky1e.tumblr.com/post/14886675036/current-projects-understanding-ios-app-rendering

Convert Separate TableViewController and ViewController into UISplitView

I currently have an iOS application that was originally developer for the iPhone; it was then decided that it was going to be required for the iPad as well. However, there are not many changes to cater for this (only things such as layout, text size and a few others) - the app is just a bigger version for iPad in reality.
One of the things my app makes use of is a UITableView (with a custom UITableCellView). Each one of these then moves onto a UIView. In order to make it a bit more unique to the iPad, I would like to implement a UISplitView to combine these two, to make better use of the larger screen!
This application was handed to me from a previous developer. A large part (95%) of the UI was coded (and not done in Interface Builder). While I am picking up objective-c, there are still some things which throw me. Therefore, my question to you guys is: would this require a huge change in code if I was to combine my UITableView and UIView into a UISplitView? From what I have seen from playing around with the UISplitView, it doesn't seem so. However, because of all the rest being coded, I think the UISplitView will have to be, is that right? Or can I dump in an xib and string up the coded UITableView and UIView?
Final question, is there a tutorial anyone knows about where they have coded a UISplitView? All of them appear to be using Interface Builder.
I hope that is not too much information!

subviews and performance issues in iOS

I have different view controllers and i linked them using insertsubview
There are atleast three levels of subviews for every screen the users sees.
I havent tested it on device yet.
I want to know whether this causes any performance issues
Also, is using NavigationBarController pop and push views better than addsubview and remove from super view.
(I dont want the back functionality of NavigationBarController and want a custom header. That is why i didnt use NavigationBarController)
This is an interesting statement :
I haven't tested it on device yet.
My advice is simple :
Test it on a device.
Only you know what your app does - you can't possibly think we can answer your question with so little information! 3 doesn't seem a very big number but I don't know what each of those views is doing so maybe it's an issue, maybe not.

Good reasons why to not use XIB files?

Are there any good reasons why I should not use XIB / NIB files with an highly customized UI and extensive animations and super low memory footprint needs?
As a beginner I started with XIB. Then I figured out I couldn't do just about everything in them. It started to get really hard to customize things the way I wanted them to be. So at the end, I threw all my XIBs away and did it all programmatically.
So when someone asks me if XIB is good, I generally say: Yeah, if you want to make crappy boring interfaces and don't care too much about performance, go ahead. But what else could be a reason not to use XIB?
Am I the only iPhone developer who prefers doing everything programmatically for this reasons?
I think that Interface Builder is one of the biggest assets of Mac (and by extension, iPhone) software development. GUIs are visual; why not create them using a visual interface? IB is flexible enough that you can lay out an interface using its "generic" components, and then subclass them where necessary. Sure, if you have a unique interface you're going to have to subclass a view class and perform custom drawing, but you can also lay out your interface in IB and then easily use the inspector to switch the class to your custom subclass.
Honestly I think it's a spectrum of convenience. If you are comfortable writing everything in code then go for it. If you design your project well then it should be about the same amount of work creating new windows, etc. But I know that a lot of people aren't as comfortable with the GUI world so nib/xibs work well there.
I honestly find myself using XIBs as a base quite often and editing them with code to get the specific look I want. Personal preference.
For a specific con on that point, views can be difficult to configure after loading them from a xib. When you have conflicting settings between IB and code that can be nasty to troubleshoot.
Here's a question for the list. What is the performance hit to using a xib? I thought they were a plus because they don't get loaded into memory until you need them. That said, that load time is longer which will slow your program down. Thoughts?
One thing I found better about code is for the event connections on controls, when you search for uses of a method (message) you find them if they are coded and you don't find them if they were set in IB.
On the other hand laying out objects on a view is much easier in IB where you can see their size and positions. When you do that in code you have to guess at the size and origin settings and then run it and make adjustments, then run it again to see what it looks like.
When your application has some kind of "standard" views, go with the XIB. If you need real customization, depending on external content (XML...) do it programatically.
I started using XIBs and now it's all code, I find myself more comfortable this way. I had real problems with XIBs, and now writing the interfaces all in code really saves me time.
I save tons of time when dealing with UIControllers (UITabBarControllers, UINavigationControllers etc.) in the start up phase where all the navigation stuff is hooked up.
I just build X viewControllers with a accompanying XIB, throw in the stuff needed in IB, labels, images etc. This means that for almost any sort of app you can have a proof of concept up in a few hours. This is enough to justify spending some time learning the ins and outs of IB. Especially on the iPhone where you can have a ton of good UI ideas, but they all fail when they move from the Simulator to an actual device.
The best thing, in my mind, is to balance it out, if you find yourself using a lot of time doing the "change the frame 3 px -> compile -> ahh.. needs two pixels more -> change 2 px - compile -> ahh.. 1 more px" for something that could be done in IB, you will seriously start to waste time.
I start as above, but afterwards I often throw the XIBs away for custom stuff. The trick is to not spend hours on implementing versions of custom stuff in code over and over again, but figure out how it should be and do the custom stuff once:)
The XML content of a nib file is very complicated. This makes it extremely difficult to review changes or fix merge conflicts with a version control system like Git.
Interface Builder is a nice idea, but Bret Victor, in his talk "Inventing on Principle" and his essay "Learnable Programming," implicitly challenges Apple to build an even better IDE.
One idea, based on Bret Victor's principle: What if I could select a "Move Tool" in the iOS Simulator app that let me move a button in my app and then the frame code changed in the implementation (.m) file? This would be much better.

Initial iPhone virtual keyboard display is slow for a UITextField. Is this hack around required?

I have an app with a UITextField, amongst other things. When the user first taps on the text field, there is a noticeable delay before the virtual keyboard appears. On a 3GS it isn't too obvious, but on an older iPhone the delay can be around 1 second. After that the keyboard always pops up instantly. The delay is only the first time the keyboard pops up after app startup.
It looks like the initial UIKeyboard instantiation takes some time (quite a bit...) but is kept around after that.
I found very little information about this, which surprised me. However I did find this write up of the issue along with a hack-around solution.
http://blog.weareuproar.com/preloading-the-uikeyboard
My question is: is this hack around the only available solution? Is there a way to signal the framework (e.g. via info plist?) to instantiate the keyboard on startup?
No, there is no other (documented) way to do that. And even Apple's built-in apps (such as Maps) suffer from the same problem. You can either go with the hack you linked to or follow Apple's advice to not load stuff in advance before you really need it. By the way, this isn't much of an issue anymore with the iPhone 3Gs and the new iPod touch. The newer and faster devices load the keyboard almost instantly.