Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[Request: TableViewIOS] directly wrap UITableView with a TableViewIOS component #332

Closed
gabro opened this issue Mar 27, 2015 · 77 comments
Closed
Labels
Resolution: Locked This issue was locked by the bot.

Comments

@gabro
Copy link
Contributor

gabro commented Mar 27, 2015

According to #143, ListView is a thin wrapper around a UIScrollView.

I'm totally ok with that, however, after trying React Native for a simple app, I really miss a real UITableView, which is probably one of the most pervasive components in any iOS app.

The most unsettling thing so far (I didn't explore much) is the look and feel. In order to achieve a default iOS7-looking table view (with line separators and disclosure indicators on cells, for instance) it's kind of a lot of customization work on top of ListView.

What I ended up with after a few experimenting still doesn't feel like native. Of course one could go through the effort of carefully providing style for the underlying UIScrollView, but honestly, what's the point? :)

Here's a list of features - from the top of my head - we would get "for free" by providing a native wrapper for UITableView (and UITableViewCell):

  • iOS native look and feel
    • line separators (with default inset)
    • disclosure indicators, detail indicators...
    • swipe to reveal delete
    • reorder handle
  • build-in functionalities
    • cell insertion/reordering/deletion
    • delegate events for the above
    • cell caching

Bottom line, what we have so far is an extremely cool and powerful framework for building native apps, which fails at providing a native look&feel for one of (the?) the most common iOS views.

tl; dr I can't imagine iOS native development without UITableView. Please provide a TableViewIOS component :)

@gabro gabro changed the title Feature request: directly wrap UITableView in TableViewIOS Feature request: directly wrap UITableView with a TableViewIOS component Mar 27, 2015
@jaygarcia
Copy link
Contributor

This was brought up a few times during the private beta. @vjeux , have you guys given any more thought into this?

@vjeux
Copy link
Contributor

vjeux commented Mar 27, 2015

We're unlikely going to provide it ourself as I don't forsee any use case for it in the apps we're going to build. But this would be a fantastic component to be built by someone in the open source community :)

@sahrens
Copy link
Contributor

sahrens commented Mar 27, 2015

Unfortunately we don't have any news here. We originally had a UITableView wrapper, but the UITableView API is not well suited for the asynchronous nature of ReactNative, and the resulting code was pretty gross, especially when trying to do smooth animations to grow the heights of rows, which we do in the groups app.

We might revisit this and provide a separate TableViewIOS component that is a wrapper for the use cases you want, but we don't have a concrete plan at this point.

On Mar 27, 2015, at 6:26 AM, Jay Garcia notifications@github.com wrote:

This was brought up a few times during the private beta. @vjeux , have you guys given any more thought into this?


Reply to this email directly or view it on GitHub.

@gabro
Copy link
Contributor Author

gabro commented Mar 27, 2015

Thanks for the feedback.
Do you guys think similar functionalities could be provided by working on the ListView API?

My point was also to raise a warning: the drill-down application where you add/delete/sort rows and see details of each one is for iOS development what a ToDo app is for JS, i.e. it's pretty much the first non-trivial app anyone approaching native development will try to build.

Right now this is slightly cumbersome, hence my concern.

@sahrens, any chance to take a look at the original UITableView wrapper? I might look into this as soon as I have time, and starting from some previous work would definitely help.

Thank you again guys for the great work!

@yosit
Copy link

yosit commented Mar 27, 2015

I think collection views addition would be awesome and it is easily deprecating table views on ios.


Sent from Mailbox

On Fri, Mar 27, 2015 at 7:20 PM, Gabriele Petronella
notifications@github.com wrote:

Thanks for the feedback.
Do you guys think similar functionalities could be provided by working on the ListView API?
My point was also to raise a warning: the drill-down application where you add/delete/sort rows and see details of each one is for iOS development what a ToDo app is for JS, i.e. it's pretty much the first non-trivial app anyone approaching native development will try to build.
Right now this is slightly cumbersome, hence my concern.
@sahrens, any chance to take a look at the original UITableView wrapper? I might look into this as soon as I have time, and starting from some previous work would definitely help.

Thank you again guys for the great work!

Reply to this email directly or view it on GitHub:
#332 (comment)

@rudolf-adamkovic
Copy link
Contributor

@yosit As for now, table views are way more powerful for one-dimensional lists than collection views. Editing, reordering, etc. There's no comparison.

@danicomas
Copy link

Conclusion: The more difficult things is the only that facebook don't want to do it xD Facebook engineers could do it in 1 hour :D @salutis For an API to develop mobile apps to have a list is required.

@clauderic
Copy link

I also think this would be a must-have component for a lot of applications out there

@umhan35
Copy link
Contributor

umhan35 commented May 12, 2015

👍for implementing table view. ListView is not felt native enough.

@rxb
Copy link
Contributor

rxb commented May 12, 2015

What's not feeling right with your styling? I'm using pretty minimal "tableview" styles and I can't tell the difference.

@umhan35
Copy link
Contributor

umhan35 commented May 14, 2015

What I thought was actually the native table cell view. Reimplementing the table view seems not necessary.

@brentvatne
Copy link
Collaborator

Ping me if you implement this, I'm very interested in seeing the result! But given that there are no plans to implement this in the core at the moment I'm going to close the issue!

@kevindeleon
Copy link
Contributor

@brentvatne Should this have been closed? I still think that UITableView is an important feature of iOS that users are accustomed to (swiping to delete, re-ordering, etc), and at the moment ListView just isn't the same thing. This would definitely be a nice feature to have.

@danicomas
Copy link

Of course not @kevindeleon . The ListView doesn't looks native! It is an horrible implementation! You know the official response. It is open source. Up to you xD

@brentvatne
Copy link
Collaborator

@kevindeleon - let's move discussions about features that aren't on the roadmap for core into here: https://discuss.reactjs.org/t/react-native-components-that-you-want-to-see/523

@brentvatne brentvatne reopened this Jun 1, 2015
@brentvatne
Copy link
Collaborator

On second thought, this seems to be pretty important to a lot of people so let's just keep it open here

@brentvatne brentvatne changed the title Feature request: directly wrap UITableView with a TableViewIOS component [Request: TableViewIOS] directly wrap UITableView with a TableViewIOS component Jun 1, 2015
@sahrens
Copy link
Contributor

sahrens commented Jun 1, 2015

@danicomas: besides missing features, what makes you think ListView doesn't feel native?

@danicomas
Copy link

@sahrens I had problems in performance with a lot of rows. I have to try the latest version to verify again.

@sahrens
Copy link
Contributor

sahrens commented Jun 1, 2015

Perf is something we're actively working on and isn't as simple as just using UITableView - we need to properly support view recycling at a low level.

Did you try playing with removeClippedSubviews and the various tunable props on ListView like pageSize? Those were critical optimizations for getting good scroll perf in the Facebook Groups app.

On Jun 1, 2015, at 2:16 PM, Daniel Comas Fernández notifications@github.com wrote:

@sahrens I had problems in performance with a lot of rows. I have to try the latest version to verify again.


Reply to this email directly or view it on GitHub.

@kevindeleon
Copy link
Contributor

@brentvatne thanks.

@sahrens For me, the need is less about performance issues in ListView and more about being able to provide features that are available in UITableView that aren't readily available in ListView (like swipe to delete, reordering, etc...). ListView is nice, but it's just not the same thing, and it would be nice to have the ability to use either.

@danicomas
Copy link

I agree with @kevindeleon.

@sahrens
Copy link
Contributor

sahrens commented Jun 2, 2015

Yup, totally agree on more features being needed, just wanted to make sure there wasn't anything else broken ;)

On Jun 2, 2015, at 5:29 AM, Daniel Comas Fernández notifications@github.com wrote:

I agree with @kevindeleon.


Reply to this email directly or view it on GitHub.

@brentvatne
Copy link
Collaborator

@sahrens - it looks like removeClippedSubviews on ScrollView does nothing, only on RCTView. ScrollView seems to pass that prop on to each row, which if I understand correctly doesn't do much to reduce memory footprint of a long ListView. I've noticed this while working on the React Native Playground app - the memory usage shoots up as we page through a long list of apps. Keeping memory usage down in long ListView's would be a nice performance improvement to get in.

@sahrens
Copy link
Contributor

sahrens commented Jun 5, 2015

cc @nicklockwood

On Jun 4, 2015, at 5:52 PM, Brent Vatne notifications@github.com wrote:

@sahrens - it looks like removeClippedSubviews on ScrollView does nothing, only on RCTView. ScrollView seems to pass that prop on to each row, which if I understand correctly doesn't do much to reduce memory footprint of a long ListView. I've noticed this while working on the React Native Playground app - the memory usage shoots up as we page through a long list of apps. This would be a nice performance improvement to get in.


Reply to this email directly or view it on GitHub.

@gavinkwoe
Copy link

look at this guys, another react-native like hybrid UI solution for iOS, written in Objective-C/C.

https://github.com/hackers-painters/samurai-native

here is an UICollectionView example (also support UITableView and all the other UIKit native components), it's amazing and really can works on your phone and iOS-simulator:

<!DOCTYPE html>

<html class="no-js no-scroll" lang="">

    <head>

        <title>Shot</title>

        <meta charset="utf-8"/>
        <meta http-equiv="X-UA-Compatible" content="IE=edge"/>

        <meta name="description" content=""/>
        <meta name="viewport" content="width=device-width, initial-scale=1"/>

        <meta name="navbar-bg-color" content="#e5508c"/>
        <meta name="navbar-tint-color" content="white"/>
        <meta name="navbar-text-color" content="white"/>

        <link rel="stylesheet" type="text/css" href="../../css/reset.css"/>
        <link rel="stylesheet" type="text/css" href="../../css/main.css"/>

    </head>

    <body>

        <RefreshCollectionView id="list" name="shot" class="list" columns="1" is-vertical>

            <UICollectionViewCell name="author" is-static is-row>
                <div class="author-wrapper" onclick="@selector(viewProfile:)">
                    <img class="author-avatar" name="avatar"/>
                    <div class="author-attribution">
                        <div class="author-title" name="title">Portfolio concept</div>
                        <div class="author-subtitle">by <span class="author-name" name="name">Vadim Sherbakov</span></div>
                    </div>
                </div>
            </UICollectionViewCell>

            <UICollectionViewCell name="shot" is-static is-row>
                <div class="shot-wrapper">
                    <img name="img" class="shot-img" src="http://img.hb.aicdn.com/90b96d207b752453ca2cef1d29af382637342086f507-9rHNhW_fw658"
                     onclick="@selector(viewPhoto:)" />
                </div>
            </UICollectionViewCell>

            <UICollectionViewCell name="attr" is-static is-row stick-top>
                <div class="shot-attribution-wrapper">
                    <div class="shot-attribution">
                        <div class="shot-segment">
                            <div class="shot-segment-wrapper">
                                <!-- <img class="shot-segment-icon" src="icon-views.png"/> -->
                                <span class="shot-segment-count" name="views">6770</span>
                                <span class="shot-segment-suffix">Views</span>
                            </div>
                        </div>
                        <div class="shot-segment">
                            <div class="shot-segment-wrapper">
                                <!-- <img class="shot-segment-icon" src="icon-views.png"/> -->
                                <span class="shot-segment-count" name="comments">19</span>
                                <span class="shot-segment-suffix">Comments</span>
                            </div>
                        </div>
                        <div class="shot-segment">
                            <div class="shot-segment-wrapper">
                                <!-- <img class="shot-segment-icon" src="icon-views.png"/> -->
                                <span class="shot-segment-count" name="likes">591</span>
                                <span class="shot-segment-suffix">Likes</span>
                            </div>
                        </div>
                    </div>
                </div>
            </UICollectionViewCell>

            <!--
            <UICollectionViewCell is-row stick-top>
                <div class="comment-header">
                    <img class="comment-icon" src="icon-views.png"/>
                    <span class="comment-text">COMMENTS</span>
                </div>
            </UICollectionViewCell>
             -->

            <UICollectionViewCell name="comments" class="comment-cell" is-row onclick="@selector(viewComments:)">
                <img class="comment-avatar-img" name="avatar"/>
                <div class="comment-attribution">
                    <p class="comment-name" name="name">Eddy Gann</p>
                    <p class="comment-body" name="text">Just a suggestion for a feature that means a lot to me: In-app web browser (so we can add the shot to buckets and like it.) Just adding a button to show it as it would appear in a mobile browser so we have access to the like button.</p>
                </div>
            </UICollectionViewCell>

        </RefreshCollectionView>

        <style>

            body {
                margin: 0;
                padding: 0;
                width: 100%;
                height: 100%;
                background-color: #e5508c;
            }

            .list {
                display: block;
                width: 100%;
                height: 100%;
            }

            .author-wrapper {
                display: block;
                width: 100%;
                height: 54px;
            }

            .author-avatar {
                display: block;
                margin-top: 8px;
                margin-left: 12px;
                float: left;
                width: 32px;
                height: 32px;
                border-radius: 18px;
                border-width: 2px;
                border-color: white;
                background-color: #999;
            }

            .author-attribution {
                display: block;
                margin-top: 10px;
                margin-left: 12px;
                float: left;
                width: auto;
                height: 32px;
            }

            .author-title {
                display: block;
                width: auto;
                height: 50%;
                line-height: 16px;
                color: #fff;
                text-align: left;
                font-size: 14px;
                font-weight: lighter;
            }

            .author-subtitle {
                display: block;
                width: auto;
                height: 50%;
                line-height: 22px;
                color: rgba( 255, 255, 255, 0.5 );
                text-align: left;
                font-size: 12px;
                font-weight: lighter;
            }

            .author-name {
                margin-left: 4px;
                height: 100%;
                line-height: 22px;
                color: #fff;
                font-size: 14px;
                font-weight: lighter;
            }

            .shot-wrapper {
                display: block;
                width: 100%;
                height: auto;
                margin-bottom: 2px;
            }

            .shot-img {
                display: block;
                margin: 0 auto;
                width: 98%;
                height: equals(width);
                background-color: #eee;
                border-radius: 2px;
                border-width: 2px;
                border-color: white;
                content-mode: fill;
            }

            .shot-attribution-wrapper {
                display: block;
                width: 100%;
                height: auto;
                margin-bottom: 5px;
            }

            .shot-attribution {
                display: block;
                width: 100%;
                height: 34px;
                background-color: #e34383;
            }

            .shot-segment {
                display: inline-block;
                float: left;
                width: 33.3%;
                height: 100%;
            }

            .shot-segment-wrapper {
                display: block;
                margin-left: auto;
                margin-right: auto;
                width: 100px;
                height: 100%;
            }

            .shot-segment-icon {
                display: inline-block;
                margin-top: 6px;
                width: 18px;
                height: 18px;
                content-mode: center;
            }

            .shot-segment-count {
                display: inline-block;
                margin-left: 4px;
                width: auto;
                height: 100%;
                line-height: 34px;
                color: #fff;
                text-align: center;
                font-size: 14px;
                font-weight: lighter;
            }

            .shot-segment-suffix {
                display: inline-block;
                margin-left: 4px;
                width: auto;
                height: 100%;
                line-height: 34px;
                color: rgba( 255, 255, 255, 0.6 );
                text-align: center;
                font-size: 12px;
                font-weight: lighter;
            }

            .comment-header {
                display: block;
                width: 100%;
                height: 30px;
                background-color: #fff;
                /*box-shadow: 0px 1px 2px #eee;*/
            }

            .comment-icon {
                display: inline-block;
                margin-top: 6px;
                margin-left: 15px;
                width: 18px;
                height: 18px;
                content-mode: center;
            }

            .comment-text {
                display: inline-block;
                margin-top: 6px;
                margin-left: 6px;
                width: auto;
                height: 18px;
                line-height: 18px;
                color: #666;
                text-align: center;
                font-size: 10px;
                font-weight: bold;
            }

            .comment-cell {
                display: block;
                width: 100%;
                height: auto;
            }

            .comment-avatar-img {
                display: block;
                float: left;
                margin-top: 4px;
                margin-left: 12px;
                width: 30%;
                max-width: 32px;
                height: 32px;
                border-radius: 18px;
                border-width: 2px;
                border-color: #f0f0f0;
                background-color: #999;
            }

            .comment-attribution {
                display: block;
                margin-left: 12px;
                margin-top: 4px;
                margin-bottom: 10px;
                width: 60%;
                height: auto;
            }

            .comment-name {
                width: 100%;
                height: auto;
                font-weight: lighter;
                font-size: 14px;
                color: rgba( 255, 255, 255, 0.5 );
            }

            .comment-body {
                width: 100%;
                height: auto;
                font-size: 12px;
                color: #fff;
            }

        </style>

    </body>

</html>

@paramaggarwal
Copy link
Contributor

This thread is going nowhere. Definitely does not belong in the core, which is this repo. Maybe somebody can build a UITableView wrapper and share with the community. Let's close this issue?

@ide
Copy link
Contributor

ide commented Aug 5, 2015

Chiming in here based on my experience with ASTableView -- I think it may be a good source of ideas but I would be cautious about porting the architecture straight over to react. I found ASTableView fundamentally hard to use when dealing with asynchronous events, and its implementation had/has some complex locking. It's certainly non-trivial and at the end of the day it doesn't run on Android.

@mannyvergel
Copy link

Hi guys, just want to share my proof of concept of react native wrapping a UITableView: https://github.com/mannyvergel/ReactNativeMVTableView

To reiterate, this is just a proof of concept, so many things do not function yet. I was able to generate the table from a list of dummy data. The main issue is that there's a flicker when the table cells are refreshing. This is caused by the bridge between the native and the javascript because every cell will call javascript. My knowledge in react native is very limited, I only rely on few documentation and reading the examples and source codes.

So I was wondering if it's possible to take a React class, pass it directly to Objective C and generate it there directly? Or another way maybe is to cache it to avoid calling javascript for every UITableView cell. Contributors are certainly welcome.

@jaygarcia
Copy link
Contributor

@jordwalke,

TBH, if I look at the current inventory of open issues with ListView, i still come to the conclusion that there are problems with that component or an education issue with usage of that component.

My specific problem seems to revolve around performance. I have a list of items that need to be rendered and no matter how i try to tweak the three performance parameters, there is always a problem.

For example, if i want the list view to render quickly, i set a low number for initialListSize. However, when scrolling, things always catch up, which ends up in an abrupt stop, and rendering taking place.

I have yet to find the magic combination of "initialListSize, pageSize and scrollRenderAheadDistance".

These issues are exhibited on a fast macbook pro using the iOS simulator, an iPhone 6 and an iPhone 5.

@jordwalke
Copy link

@jaygarcia I love the video on twitter! Is that list view issue the one you showed in the video, where it seems to stop when you drag it? I haven't seen anything like that and I wonder if it has something to do with the gestures getting canceled by some modal dismiss.

  • Does the issue still happen if you take the list out of a modal (otherwise blank app).
  • Make sure you never test perf in dev mode alert(__DEV__) should alert 0.
  • Does the issue happen if you prerender all of the items? (within reason).

@sghiassy
Copy link

sghiassy commented Aug 7, 2015

@jaygarcia - Check out my comment at: #499 (comment)

Depending on where your performance issues are stemming from - it could help

@paramaggarwal
Copy link
Contributor

@sahrens I tried using the ListView with removeClippedSubviews={true} and overflow: 'hidden' on all of the rows - but still the memory grows linearly as I scroll down. (I verified that I have setup correctly using the View Hierarchy Debugger.) All the view instances are still in memory right? They get removed from the view hierarchy, but there is still a reference to them and hence they continue to take up RAM? I am trying to understand how this attribute actually affects memory utilisation.

@nicklockwood
Copy link
Contributor

@paramaggarwal it mostly doesn't affect memory consumption, it just helps with scroll performance.

However, if your cells contain images or text, the backing stores for those are released when the views are removed from the screen, so that could help to reduce memory (that's a recent optimization though, and may not be in the github trunk yet).

@paramaggarwal
Copy link
Contributor

Thanks @nicklockwood. So how is the Groups app currently running on iPhone 4/4s? In my app, I face crashes when scrolling further down on a long feed as the memory just keeps growing!

(The fix I have in place currently is to use onChangeVisibleRows and hide and show rows, but let them keep their layout.)

@nicklockwood
Copy link
Contributor

@paramaggarwal Groups is using the unloading images feature. If that's not yet implemented on your version, that might explain why you're running out of memory when Groups doesn't.

@paramaggarwal
Copy link
Contributor

Makes sense. Thanks @nicklockwood.

@aksonov
Copy link

aksonov commented Aug 18, 2015

I've got big performance problems to display large sets of data - like countries list with ListView. It is terrible. If I want to scroll to last country (like previous user selection) i should set enough timeout, because rendering takes significant time. I don't understand why UITableViewIOS wrapper cannot be included into React distribution.

Anyway, for a while, i've created UITableView-wrapper component by myself, maybe it could be useful for community. It also supports JSON sources so data could be loaded directly to iOS, not via JS (otherwise data will be part of generated JS and could significantly affect loading time!):
https://github.com/aksonov/react-native-tableview

@nicklockwood
Copy link
Contributor

@aksonov this looks great!

It's not a good idea to use the RCT prefix for your classes though. When we eventually introduce our own RCTTableView it will conflict with yours.

@aksonov
Copy link

aksonov commented Aug 20, 2015

Thanks, got it. So is built-in RCTTableView planned for release? Any ETA?

@nicklockwood
Copy link
Contributor

We don't have a specific schedule for it at this time.

@christopherdro
Copy link
Contributor

I think anyone interesting in working with UITableView should take a look at @aksonov https://github.com/aksonov/react-native-tableview

There are some kinks but if enough people are interested we can all work on it as a community.
Who knows, it might end up getting merged in. :)

@kevindeleon
Copy link
Contributor

Wow! Great work @aksonov -- Will have to play around with this when I get a chance. Just curious, does it support swipe actions such as swipe to delete? I believe it's commitEditStyling

@aksonov
Copy link

aksonov commented Sep 15, 2015

No at this moment. If enough people will be interesting, i will include it to the roadmap. If you want to implement it, PR is welcome.

15 сент. 2015 г., в 3:56 PM, Kevin deLeon notifications@github.com написал(а):

Wow! Great work @aksonov https://github.com/aksonov -- Will have to play around with this when I get a chance. Just curious, does it support swipe actions such as swipe to delete?


Reply to this email directly or view it on GitHub #332 (comment).

@danicomas
Copy link

@aksonov How is the perfomance in an iOS 7.1 iPhone 4?

@aksonov
Copy link

aksonov commented Sep 16, 2015

@danicomas Sorry, don't have any idea, maybe you could check. The component supports JSON from app bundle, in this case performance will be the same as in native UITableView (actually that is main use case of the component - to display long lists effectively, like list of countries - ListView cannot do it now). Potentially it could support any 'native (objective-c) datasources, but it requires objective-c / swift programming.

One problem I want to solve now, maybe FB team could advise something - implement real 'factory' for UITableiView cells from JS code. For now i can only pass concrete view for concrete cell - so performance will be not good for large lists because cells will be not reused. I guess it is almost impossible to implement because objective-c code could call JS method only in async way...

@jaygarcia
Copy link
Contributor

This thread should be closed. The FB team has almost unanimously said that they feel that such a component does not belong in RN Core. ListView is a fine UI component and is extremely flexible, sans some bugs that could be worked out.

@ide @brentvatne, this should be closed.

@zcstarr
Copy link

zcstarr commented Oct 29, 2015

@jaygarcia I don't think this thread should be closed, UITableView in core would go along way in increasing the utility and longevity of the project. Its simply tricky and probably a bit time consuming to do @nicklockwood said back in Aug. there's simply no set schedule for this. That said, the suggested components area is most definitely not the place for UITableView discussion

@gastonmorixe
Copy link

+1

@paramaggarwal
Copy link
Contributor

Please use https://productpains.com/product/react-native/ to report requests.

@jsierles
Copy link
Contributor

Given the lack of activity on this, and the success of Product Pains, I'm closing this issue to help with cleanup.

@facebook facebook locked as resolved and limited conversation to collaborators Jul 23, 2018
@react-native-bot react-native-bot added the Resolution: Locked This issue was locked by the bot. label Jul 23, 2018
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
Resolution: Locked This issue was locked by the bot.
Projects
None yet
Development

No branches or pull requests