

Show HN: iOS Table View that automatically adjusts with keyboard show/hide - bobspryn
https://github.com/sprynmr/FUNTable

======
LinaLauneBaer
During the code review (see below) I found that you are actually resizing the
table view to accomplish the effect. This is (in my opinion) not the right way
to do it. Here is a suggestion:

Instead of adjusting the frame of the Table View simply work with the
contentInset property. This is how UITableViewController does its job.

Short Code Review if you don't mind: (I only want to help - not to be a jerk)

Line 35: Please remove your -init override. You are doing nothing there and if
you want to have custom initialization use initWithCoder: and initWithFrame:
instead of init

Line 61: id (star)appDelegate = [[UIApplication sharedApplication] delegate];

Please remove the "(star)"

Line 64: CGRect windowRect = appDelegate.window.bounds;

You are trying to get the window bounds. Why are you not using: CGRect
windowRect = self.window.bounds;

Line 73: viewRectAbsolute = FixOriginRotation(viewRectAbsolute, orientation,
windowRect.size.width, windowRect.size.height);

Are you aware of: CGRectGetHeight(…) and CGRectGetWidth(…)? I am not saying
you should use these functions instead but you could consider using them. I
like them very much:

viewRectAbsolute = FixOriginRotation(viewRectAbsolute, orientation,
CGRectGetWidth(windowRect), CGRectGetHeight(windowRect));

Line 79: int remainder = (viewRectAbsolute.origin.y +
viewRectAbsolute.size.height + keyboardFrame.size.height) -
windowRect.size.height;

Again: Consider the functions mentioned above. More importantly replace "int"
with "NSInteger" - or even better with CGFloat.

Line 80: if (remainder > 0 && !(remainder > frame.size.height + 50)) {

When using CGFloat you want to make sure to use 0.0 and 50.0.

Line 82: float duration = [[userInfo
objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];

Why are you assigning the result of -doubleValue to a float?

~~~
jrmg
_When using CGFloat you want to make sure to use 0.0 and 50.0._

Actually, on iOS, CGFloat is 32 bits, so you should use '0.0f' and '50.0f'.

On the Mac, in, 64-bit, it's a 64-bit value, so your advice would be correct
there.

It is slightly annoying there's no easy way to write a CGFloat literal in a
cross-platform way apart from the overly verbose '((CGFloat)50.0)'.

~~~
LinaLauneBaer
You are - of course - correct. Did too much Mac development lately. :)

------
thought_alarm
You should be setting the TableView's `contentInset` and
`scrollIndicatorInsets` properties, rather than adjusting the TableView's
frame.

Convert the keyboard frame to the superview's coordinate system using
`-convertRect:fromView:`, e.g. :

    
    
        keyboardFrame = [tableView.superview convertRect:keyboardFrame
                                                fromView:tableView.window];
    

The bottom inset is then simply the difference between the TableView's height
and the keyboard's Y coordinate.

You would also set those properties and scroll to the selected row in the same
animation block.

~~~
bobspryn
I believe I started to try that method but ran into issues. Wasn't aware of
the scrollIndicatorInsets though, so maybe that was the issue.

Would that method have any significant advantages? Less code? Would it avoid
all the crazy frame calculations depending on the rotation?

~~~
thought_alarm
Yes, `-convertRect:fromView:` replaces your frame calculations based on
rotation.

~~~
bobspryn
Ah yes. I see now that I totally missed the fact that the keyboard rect also
needed to be converted. Well that was a painful point to miss!

Cool. I'll give that a whirl. Those rotation bits were a biatch. Thanks for
the pointers.

------
bobspryn
Hopefully this is useful to someone. Obviously this could also just be a
little display helper class (composition > inheritance) or even a category,
but this was my original implementation. Might update it in the future. All
the crazy coordinate stuff was the painful part.

------
LinaLauneBaer
Isn't the same functionality already part of UITableViewController?

~~~
bobspryn
Yes, if the tableView is your main view. Otherwise you are left rolling your
own solution. In the case of the iPad, the tableView is rarely my main view
for my controller, so I needed a little more flexible solution.

~~~
LinaLauneBaer
Why don't you have simply two UITableViewControllers + a Split View Controller
in your example? Because of the divider of the Split View?

~~~
bobspryn
Per iOS standard design, only one ViewController is supposed to manage a full
screen (iPhone) or region of a screen (iPad eg. split view controller). That's
because you want to keep the view hierarchy pretty straightforward, instead of
taking the view portions of other view controllers and inserting them as
subviews of another VC. (Makes you feel dirty). Suggest watching the WWDC 2011
video on Customer Container VC's for an explanation.

Also it would be quite a bit of overkill and extra communication and code to
back every table with a full blown view controller.

------
eps
Ironically, the screencast doesn't appear to be working on iPad.

~~~
bobspryn
Hmm.. It should have. I'll check it out.

~~~
bobspryn
Should be working now, although they don't seem to do the typical fullscreen
thing. They should be able to with the file type and specs, but oh well.

