NSTableView with embedded WebViews - objective-c

I'm currently trying to render html content into custom NSTableCellViews inside an NSTableView. This is to render emails inside an email thread individually. On selection, the NSTableCellView either expands to show the rendered email, or contracts to hide it. It seems to be working fine with a combination of:
tableView:viewForTableColumn:row:
tableView:heightOfRow:
tableViewSelectionDidChange:
and:
noteHeightOfRowsWithIndexesChanged:
reloadDataForRowIndexes:columnIndexes:
Each NSTableCellView has a WebView as its child. The rendered content shows up fine until I start scrolling heavily at which point, off-screen WebViews lose their rendered content. If I force a re-render by contracting and expanding the NSTableCellView, the content appears fine.
Is there a delegate method/a way to fix this? Or should I use something other than WebViews to render html inside an NSTableCellView?

In case someone stumbles here into the future, the solution I used was to set the NSTableView.usesStaticContents to YES. This prevents makeViewWithIdentifier from recycling cells and hence allows the WebView's to persist in different NSTableCellViews.
This will obviously use more memory, but since there is a definite limit to the maximum number of cells inside an email thread, the increase is within acceptable bounds.

Related

Responder Chain (UIWebView inside UItableViewCell) Objective-C

I've been struggling with first responder problem. I put web controller (UIWebView) inside UITableViewCell and now I would like to scroll vertically my table and not affect UIWebView (this case may be done by disabling scrolling scrollview from UIWebView). However problem appears when user zooms into web content, then I want scroll horizontally through web content and still vertically scroll in table (cause cell will be resized to zoomed content).
There is a property called 'multipleTouchEnabled' that should disable the pinch gesture, but I think the user would still be able to double-tap (assuming the cell doesn't consume this gesture). Why not, instead of creating multiple UIWebView's (which have a large overhead) don't you create one hidden UIWebView that loads a website and caches an image, then load this image into the cell.
Ultimately, if you still wanted to use the UIWebView approach, you could probably subclass it and override hitTest/touches methods or handle the gesture recognizers yourself.
Also, if this is for iOS8 I would be using the WKWebView instead.

UIWebView inside full screen UICollectionView with paging

I want to have a full screen UICollectionView with paging, with a UIWebView in every cell.
The WebView should scroll up and down, and the CollectionView should move pages left and right.
Also, I want the pages on the cells will preload so when the user move to a certain page the html page will already be there.
What is the correct way to handle this?
It's hard to put it all in here, so check out if this project gets you closer to solving your problem.
Notice that there is no preloading, because if you'll write your own html and there won't be any network calls, you don't need to preload pages - changes will be instantly visible to your users.
You always gonna have to reload the UIWebView in UICollectionViewCells because they are reusable, but if you want you can make a hack, an UICollectionView that it is 3 times bigger than the frame of your main view it has to begin in the second page and finish in the one before the last.
It is going to have always 3 webviews preloaded (but you can make the hack bigger if you want) or you can make a UIScrollView with pagination activated which always gonna have all of the webview preloaded.

MFMailComposeViewController causes other controls to change position

I have three UIViewControllers being shown modally on top of each other. The third one opens a MFMailComposeViewController and send an email. However, after dismissing that view controller, various controls on other view controllers (not necessarily in the chain of view controllers) have moved in position.
For example, after dismissing the MFMailComposeViewController, one of the labels on the parent ViewController has moved down by about 20px. A scrollview on it's parent has also moved down the same amount. If I enter a separate view controller from here, an imageview is displaced. They always seem to be a control near the top of the screen, and only one per screen.
Has anyone seen this before? I've checked all the code and there nothing which could be causing it. I'm having to reset the frame on these controls every time the screen is shown to prevent them from appearing out of place. But it makes no sense to me.
Thanks.
Have you tried presenting it from the parent view controller?? I had a similar problem and it fixed the issue.
It sounds like layout randomly isn't happening, somehow. I can think of a few things to try:
Check that you're not expicitly calling -layoutIfNeeded, especially in places like -setFrame: or -sizeThatFits: — it can cause a layout of the entire view tree, which will tend to do the wrong thing if layout is already happenin (on iOS 5 it can cause inconsistent layout; on iOS 6 I've observed it getting stuck in a layout loop). You also need to be careful around some methods which perform a layout as a side-effect (UIButton.titleLabel comes to mind — the fix is to call it before adding the view to the hierarchy).
If you're using autoresizing then it should just work — except I've seen it not work if the view isn't attached to a window when its frame changes.
If you're doing layout in -layoutSubviews, override -setFrame: to call -setNeedsLayout. The usual symptom is that "switch tabs, rotate, switch back" results in an incorrect layout.

Changing what is loaded by a nib file

in my iPad application I have a panel of buttons, I have used an UIImageView as this panel and put buttons on top of it and created my nib file. in some views some button of this panel should not be displayed. so what i do is removing those buttons and decreasing the height of the panel (a UIImageView) then reposition the button to take up the space of the removed button. I have created outlets to all of these.
Is this the way to do this? My problem is if I want to change the order my buttons are displayed at some point I can't do it by simply changing the nib file. I'll have to do some changes in the code as well.
In this case don't use the nib to position the buttons in the first place. It sounds like this is one of the occasional cases where you would be better off working solely from code.
Instead of having to worry about some sort of abstraction that protects your layout if you decide to reposition the buttons and about removing and repositioning buttons, you can just do the layout at runtime once your particular view knows what buttons it needs. Your code is already doing much of the work of layout already (removing and repositioning).

Updating UITextView inside UIScrollView while scrolling makes the scrollView stop scrolling

I have a scrollView that contains 12 UIViews set as tiles. Each tile contains a textView.
The scrollView has pagination enabled. So, you have 12 tiles per page and you scroll horizontally.
I am updating the textView whenever I receive information from an API call.
This is updating the textView correctly, but I have a huge problem. Whenever the update happens, the scrollView actually scrolls to the view that was just updated. So whenever I load a new column of tiles, the scrollview stops when it begins loading it, even if it has momentum!
Any idea what might be causing this?
If I lazy load the cells without any information in them everything works right, so I'm thinking it has to do with me updating the textView.
I have already tried:
Using an NSTimer (and setting its mode to NSRunLoopCommonModes).
Using an NSOperationQueue and calling the main thread whenever I need to update UI changes.
None of those worked.
i think the solution lies within your post:
"Using an NSOperationQueue and calling the main thread whenever I need to update UI changes."
Whenever scrollView calls for willScroll, stop the current Images being downloaded & when the scroll view stops scroll & its delegate method is called start the new queue to download images.
My suggestion will be debugging it using instrument. In instrument there is a trace template named "Time profiler", you can actually see how much time your application spends on each tasks.
But if you are updating the textViews, of course the main thread will be blocked, so the scroll view stop scrolling until all the textViews are updated. So my suggestion will be tweaking the performance.
Maybe you are loading too much things in each textView?