facebook / componentkit Goto Github PK
View Code? Open in Web Editor NEWA React-inspired view framework for iOS.
Home Page: http://www.componentkit.org/
License: Other
A React-inspired view framework for iOS.
Home Page: http://www.componentkit.org/
License: Other
Verify that site builds
Hey guys,
similar to your example project i am using a CollectionViewController. each cell represents a product.
a ProductModel has readonly properties like (name, brand, photo...) and a boolean property: liked.
liked tells me if the current logged in user has already liked the product.
now back to the cells. the componenttree in my cell has somewhere a button with two different images representing the liked state. after the user presses the button i must request the server to set the new state and the server returns a new ProductModel.
I am unsure where to trigger the async operation.
Should i enqueue an update in my ViewController to update the cell? But then i have to give the components in my cell a callback/selector to a function in my VC?!
I meet some struggle to layout the component.
| [HEART]==============[REPLY] |
Space-between justify-content is not supported now.
So what I do it now is nest
CKBackgroundLayoutComponent:
component:[heart StackComponent]
backgroundComponent:[reply StackComponent]
This is not beautiful. If there is some better and simple solutions?
CKComponentActionSend
can crash if called after updateState
because updating state may unmount the component synchronously.
See: #86
@adamjernst says:
This is really a bug with updateState that we plan to address shortly. It shouldn't synchronously unmount; instead that should be deferred to the end of the run loop.
Hey guys,
this project made me really feel happy while watching the video. I really like the concept of declarative style and thus love React.
I am really excited and will really try it out the next days.
While watching the video I thought "oh how cool, this is like it needed swift as language. Because immutability... this is so much swift like". I thought, how would I implement it in swift. Then at the end of the video you got me!!!
Any timeline or news working on swiftifieing this thing?
I want some buttons to toggle their images when tapped, and I've implemented that by updating the component's state. However, I also want to send an action upstream to a Controller which will handle the server work.
Concretely:
|LinkComponentController <– does the heavy lifting
|LinkComponent
\___LinkVoteComponent <– updates its own UI, holds the voting state
\___Link*Component <– etc - other components which also get the LinkComponentController to do stuff
(where a Link is basically analogous to a Story in Facebook terms)
If I implement a LinkVoteComponentController
, is it kosher for that to call [self.component updateState:...]
*? Do I call CKComponentActionSend from the Component? Or am I barking up the wrong responder tree?
* currently, I just implement actions in the LinkVoteComponent
directly, and update the state, with no server-side code implemented. Trying to find a way to avoid having to bake that into the Component.
Basically, the question boils down to, in Facebook terms: How do I structure a Story-like component to handle an action similar to liking a Story?
Component in a collection view cell - I want to align a label on the left side and an image on the right side:
-------------------------------------------------------- |
---|
--- Label_text------------------------ image---- |
------------------------------------------------------- |
-------------------------------------------------------- |
I believe I need to use the stack layout component but I'm not sure what the flags should be:
+(instancetype)newWithModel:(ItemModel *)model {
CKStackLayoutComponent *stack = [CKStackLayoutComponent newWithView:{
[UIView class],
{
{@selector(setBackgroundColor:),[UIColor redColor]} // want to see that the container is being streched
}
} size:{} style:{
.alignItems = CKStackLayoutAlignItemsStretch,
.direction = CKStackLayoutDirectionHorizontal,
}children:{
{
.component = [CKLabelComponent newWithLabelAttributes:{
.string = @"Label",
.color = [UIColor whiteColor]
}viewAttributes:{}]
},
{
.component = [CKImageComponent newWithImage:image],
.alignSelf = CKStackLayoutAlignSelfEnd // shouldn't this align it to the end of the box?
}
}];
return [super newWithComponent:stack];
}
It's theoretically possible for a race condition to occur if a state update occurs between two model updates. This is so rare we haven't even noticed it when using ComponentKit in Facebook's News Feed, but we should fix it.
My plan is to implement a STM-like system for computing updates to the CKComponentLifecycleManager
's state to resolve this issue.
Since CKLabel/Text Components are based on UIControl, they capture touches, this is problematic in a UICollectionView when the desire is that the user is able to tap on any area of the cell and the didSelectItemAtIndexPath:
to be called.
Is there anyway to disable this?
Currently I'm trying to create a half screen width component so that in theory I could have two cells side by side.
This is the code I've got and my expectation is that it would fill only half the width of the screen but it fills the whole screen width instead:
return [super newWithComponent:
[CKComponent
newWithView:{
[UIView class],
{
{@selector(setBackgroundColor:),[UIColor redColor]}
}
}
size:{
.width = CKRelativeDimension::Percent(0.5),.height = 120
}]];
- (void)callAndReleaseCompletionBlock:(BOOL)canceled;
{
if (_operationCompletionBlock) {
_operationCompletionBlock(self.value, canceled);
// Guarantee that _operationCompletionBlock is released on _callbackQueue:
self.operationCompletionBlock = nil;
}
}
See: "canceled**;**"
I'd fix it myself, but I haven't yet gotten a company CLA signed (sorry).
It is already possible to use CKComponentDataSource directly to have a UITableView using component and we provided [some sample code]((http://componentkit.org/docs/datasource-dive-deeper.html#example-use-it-in-your-viewcontroller-to-power-a-uitableview) for it. Even though UICollectionView present a lot more advantages than UITableView (perf, animations, real abstraction for the layout ...) my plan to make things better with UITableViews is :
The component kit is amazing! The amount of code is nothing compared with the traditional.
I'm trying to figure out how to handle rotations. Because all view has to be updated, I would need to update all the models. This works as long as the amount is not big (>100).
Any ideas on this? BTW, I noticed that facebook app for iOS doesn't support rotations.
I have a component which will be used in a collectionview. This component in turn can be built up with many other components so I have a CKStackLayoutComponent which I want to insert multiple children. The number of children will be dynamic (in reality no more than 4), what is the best way to build these up and pass to the children of a CKStackLayoutComponent?
Xcode is displaying an error for line 69 in CKTextKitRendererCache.h :
const Key(CKTextKitAttributes a, CGSize cs);
The error is : Constructor cannot have a return type.
Not sure if this is specific to me or widespread.
Is it possible to use it with node ? Maybe in future.
Our CKStackLayoutComponent
doesn't support these, unlike CSS. See #62.
-boundsAnimationFromPreviousComponent:
supplies a way to specify how the top-level UICollectionViewCell
should be animated when its bounds change. However this animation does not apply to component-created subviews of the cell.
Provide a way to perform such animations. Useful for inline expansion of textual content.
I see ComponentKit | ComponentKit | A React Inspired ....
in the title.
I right aligned the text component, limited it to 1 line and set a truncation string. The truncation string doesn't display as expected
If I scroll far enough away and then scroll back, it'll have the expected background color, but will remain otherwise. My ViewController/CollectionView code is structured very closely to wildeguess's
Example code:
return [super newWithComponent:
[CKInsetComponent
newWithInsets:{.left = 10, .right = 10}
component:[CKStackLayoutComponent
newWithView:{
[UIView class],
{{@selector(setBackgroundColor:), [UIColor fpEggshell]}}
}
size:{}
style:{
.alignItems = CKStackLayoutAlignItemsCenter,
.direction = CKStackLayoutDirectionHorizontal,
} children:{
{[CKImageComponent newWithImage:[context imageNamed:@"btn_asdf"]]}, // placeholder
{[CKTextComponent
newWithTextAttributes:{
.attributedString = postedInAttributedString,
} viewAttributes:{
{@selector(setBackgroundColor:), [UIColor fpEggshell]}
} accessibilityContext:{}]},
{[CKComponent new], .flexGrow = YES},
{[CKImageComponent newWithImage:[context imageNamed:@"btn_dots"]],
.alignSelf = CKStackLayoutAlignSelfEnd,
}}]]];
Those methods are not called on CKComponentSubclass:
I have a very large collection of objects, kind of like Facebook feed, and would like to present it with CKCollectionViewDataSource
.
Typically I'd use NSFetchedResultsController
where I can listen for changes on context for a NSFetchRequest
. Do you have any recommendation to do it in ComponentKit
with data backed by Core Data?
I want to implement the "pan to reveal" auxiliary actions seen in the mail app. ("Delete","Archive"...)
Reading the responder chain doc:
"Drop down and mutate the underlying views directly as the user performs a gesture."
Not sure what exactly I should be mutating , and not sure if the state is saved if the user scrolls.
State meaning the new appearance of the view that was mutated.
For instance:
+(instancetype)newWith.... {
....
....
CKBackgroundLayoutComponent *background = [CKBackgroundLayoutComponent newWithComponent:stack background:[CKComponent newWithView:{
[UIView class],
{
{
@selector(setBackgroundColor:),[UIColor whiteColor]
},
{CKComponentViewAttribute::LayerAttribute(@selector(setCornerRadius:)), @4.0},
{shadow,[UIColor blackColor]},
**{CKComponentPanGestureAttribute(@selector(didPan:gesture:))}**
}
}size:{}]];
...
...
return [super newWithComponent:...];
I added the gesture to the background view of the component (Not sure if this is the suggested way)
Also not sure what happens to the background's view "Subviews" - ( sub components).
This isn't giving any sort of result I would want:
-(void)didPan:(CKComponent *)component gesture:(UIPanGestureRecognizer *)gesture {
CGRect frame = component.viewContext.frame;
frame.origin.x += [gesture translationInView:gesture.view.superview].x;
gesture.view.frame = frame;
[gesture setTranslation:CGPointZero inView:gesture.view.superview];
}
Thanks!
I see that when I press the truncated string the area around it changes colors.
How can I get the "tap" action and change the colors of that highlight?
Thanks,
I follow the instruction on
http://componentkit.org/docs/getting-started.html
The wildeguess repo build fail.
ld: library not found for -lPods-ComponentKit
clang: error: linker command failed with exit code 1 (use -v to see invocation)
How can we solve this out? THanks
Is it possible to change the color of the links?
Thank you.
The online documentation is missing for some basic components like CKTextComponent, CKLabelComponent.
Wondering if there is a plan to update it?
I'm looking for how to set an action for attributed string being tapped
Including GCC_TREAT_WARNINGS_AS_ERRORS
in the podspec's xcconfig parameters doesn't mean that ComponentKit alone will be compiled with -Werror
. Instead a line will be added to Pods/Target\ Support\ Files/Pods/Pods.*.xcconfig
, against which project and pods code will be compiled.
While treating warnings as errors is a good policy, it's (unfortunately) not a reasonable constraint to impose on other projects. The flag should be removed. Fortunately, this should be equivalent and applicable more narrowly to ComponentKit specifically:
+ s.compiler_flags = '-Werror -Wall'
s.xcconfig = {
'CLANG_CXX_LANGUAGE_STANDARD' => 'c++11',
'CLANG_CXX_LIBRARY' => 'libc++',
- 'GCC_TREAT_WARNINGS_AS_ERRORS' => 'YES'
Would it be kosher to include a weak reference to a delegate (i.e. a ViewController) in the context so that the component can set its controller's delegate?
Is that a valid pattern (I suspect possibly not)? Are there better ways to route events?
Specifically, I want to implement the tap on a couple of buttons in a component to present view controllers from the current one, and was wondering what strategies are preferred to connect component actions back to their owning view controllers.
Is the absence of an umbrella header an oversight, or part of the framework's opinions?
reproduce:
UICollectionViewController enqueue changeset:
_sizeRangeProvider = [CKComponentFlexibleSizeRangeProvider providerWithFlexibility:CKComponentSizeRangeFlexibleHeight];
[_dataSource
enqueueChangeset:{listSctions, listItems}
constrainedSize:[_sizeRangeProvider sizeRangeForBoundingSize:self.collectionView.bounds.size]];
CKCollectionViewDataSource returns MyComponent
return [super newWithComponent:[CKStackLayoutComponent
newWithView:{}
size:{}
style:{
.direction = CKStackLayoutDirectionHorizontal
}
children:{
{
[CKTextComponent
newWithTextAttributes:{
.attributedString = [[NSMutableAttributedString
alloc]
initWithString:@"Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry's standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum"
attributes:@{
NSFontAttributeName: [UIFont systemFontOfSize:17.0f],
NSForegroundColorAttributeName : [UIColor blueColor]
}]
}
viewAttributes:{}
accessibilityContext:{}]
}
}]
];
result: the text is clipped by the cell and in one line
I was following the guide as specified here:
http://componentkit.org/docs/advanced-views.html
And implemented the following code
@implementation AndFinallyNewsStoryComponent
+ (instancetype)newWithHeadline:(NSString *)headline
shortDescription:(NSString *)shortDescription
stats:(NSAttributedString *)stats
andImage:(UIImage *)image
{
return [super newWithComponent:
[CKComponent
newWithView:{&gradientOverlay}
size:{.width = 50,.height = 50}]];
}
static GradientOverlay *gradientOverlay(void) {
return [[GradientOverlay alloc] initWithColor:[UIColor redColor]];
}
This produces an unexpected compiler warning in the form of: Incompatible pointer types passing 'GradientOverlay ()()' to parameter of type 'UIView ()()'
GradientOverlay is currently a subclass of UIView, should this be something else? It's not specified in the docs of any additional changes needed.
Is there a reason why CKCollectionViewDataSource
doesn't expose
- (NSInteger)numberOfSections;
- (NSInteger)numberOfObjectsInSection:(NSInteger)section;
the same way CKComponentDataSource
does?
Or maybe it could expose that it implements UICollectionViewDataSource
?
I'd probably prefer the same interface as CKComponentDataSource
, since implementing UICollectionViewDataSource
is just an implementation detail.
Any hint on how we should do to handle tap or long tap on text or URL in CKTextComponent
?
I cannot set a delegate for UITextView
, and cannot find anything similar in CKTextComponentView
/ CKTextComponentViewControlTracker
?
What I currently doing is add a gesture recognizer and attach it to CKTextComponentView
, and find the corresponding attributed text at user tap position. This work except I cannot get text highlighted as user click on the link.
There is this section in the docs:
Interfaces that aren't lists or tables aren't ideally suited to ComponentKit since it is optimized to work well with a UICollectionView.
That was a bit surprising and I guess it means that ComponentKit was designed for the NewsFeed and other feeds within Facebook. That being said, does that mean you all use the normal imperative, mutative iOS APIs for other parts of the FB app or some other technology that isn't open sourced? Is ComponentKit not suited for just laying out a simple UIView e.g.?
ComponentKit.podspec doesn't specify which headers are public, which causes all headers to be public.
Let me take the code snippet from componentKit org as example. But I found there is a little confusing, the sender is CKButtonComponent, not the ChildComponent. In that case the ParentComponent can not update the state of ChildComponent.
Is there any suggestion about how the update the ChildComponent by the ParentComponent
**
@implementation ParentComponent
+ (instancetype)new
{
return [super newWithComponent:
[ChildComponent
newWithAction:@selector(someAction:)]];
}
- (void)someAction:(CKComponent *)sender
{
// Do something
}
@end
@implementation ChildComponent
+ (instancetype)newWithAction:(CKComponentAction)action
{
return [super newWithComponent:
[CKButtonComponent
newWithAction:action]];
}
@end
A somewhat obscure but nice feature would be the ability to override the hit test at the root view in a component hierarchy.
In the documentation under "state"
http://componentkit.org/docs/state.html
The described method of changing state implies calling a method on CKComponent which isn't exposed in the .h file
@interface CKComponent
- (void)updateState:(id (^)(id))updateBlock; // not in .h file of CKComponent - compiler error . I manually added it to my class , get a "not implemented" warning but it works .
@end
The documentation should also explain adding the CKComponentActionAttribute
or another method of getting the callback
Having an appledocs generated API documentation would provide for a nice complement to the documentation we have and allow it to be used in tools like Dash.
Reading up on component controllers -
It makes sense that any delegation related to the component should be handled in the component controller.
I would like to implement UIGestureRecognizerDelegate
in the controller, but since I am creating the CKComponentPanGestureAttribute
in the component +new
method, how this is done isn't to obvious just by reading the documentation on component controllers.
For instance the following case creating a text component which has a pan attached to it:
CKTextComponent *text = [CKTextComponent newWithTextAttributes:{
.attributedString = [attString copy],
.truncationAttributedString = [NSAttributedString moreAttributedString],
.maximumNumberOfLines = static_cast<NSUInteger>([state boolValue] ? 0 : 4)
}viewAttributes:{
{@selector(setBackgroundColor:),[UIColor clearColor]},
{CKComponentActionAttribute(@selector(didTapContinueReading))},
{CKComponentPanGestureAttribute(@selector(didPan:gesture:))} // I've implemented this method in the controller class
// How do I set the delegate of the yet to be created pan gesture?
}accessibilityContext:{
}];
Furthermore, since the components model should be immutable , it wouldn't make sense for the controller to "kidnap" the gesture recognizer in the lifecycle methods (such as - (void)didMount
)
What am I missing?
It would be great if there were an option for a CKCompositeComponent to construct a CALayer hierarchy instead (or, with a bit more work, in addition to) its UIView hierarchy. CALayers are more lightweight than UIViews and more performant.
Thanks so much for ComponentKit! It's awesome, the example scrolls so smooth! Of course I switched over to 6.2 but just letting you all know (you probably already do) about these:
/Users/jwright/Downloads/ios_examples/componentkit/ComponentTextKit/TextKit/CKTextKitRendererCache.mm:28:12: Out-of-line definition of 'Key' does not match any declaration in 'CK::TextKit::Renderer::Key'
and
/Users/jwright/Downloads/ios_examples/componentkit/Examples/WildeGuess/Pods/Headers/Build/ComponentKit/CKTextKitRendererCache.h:69:9: Constructor cannot have a return type
Hi there
This is a StackOverflow kind of question and not really an issue, but I couldn't ask it there (apparently I can't create the tag componentkit
with my reputation, can someone else do it?).
I've just started playing with ComponentKit and I'm having some difficulties aligning 2 labels horizontally.
I want the first one close to the left margin and the second close to the right.
With auto layout, I can do it with this set of constraints:
H:|-0-[_label1]-[_label2]-0-|
Everything I tried doesn't seem to be working, I always get the same result:
This is the super-simple component:
+ (instancetype)newWithText1:(NSString *)text1 text2:(NSString *)text2
{
return [super
newWithComponent:
[CKStackLayoutComponent
newWithView:{}
size:{}
style:{
.direction = CKStackLayoutDirectionHorizontal,
.alignItems = CKStackLayoutAlignItemsCenter
}
children:{
{
[CKLabelComponent
newWithLabelAttributes:{
.string = text1,
.font = [UIFont systemFontOfSize:20],
.color = [UIColor blackColor]
}
viewAttributes:{
{@selector(setBackgroundColor:), [UIColor clearColor]}
}],
.alignSelf = CKStackLayoutAlignSelfStretch
},
{
[CKLabelComponent
newWithLabelAttributes:{
.string = text2,
.font = [UIFont systemFontOfSize:20],
.color = [UIColor redColor],
.alignment = NSTextAlignmentRight
}
viewAttributes:{
{@selector(setBackgroundColor:), [UIColor clearColor]}
}],
.alignSelf = CKStackLayoutAlignSelfStretch
}
}]];
}
If anyone has any advice that would be greatly appreciated. I also have an example project
Hello
I try use Example: Use it in your ViewController to power a UITableView in this link http://componentkit.org/docs/datasource-dive-deeper.html
But when I compile project I have error in CKArrayControllerChangeset.h - 'map' file not found.
How I can resolve this problem?
Thanks
It looks like this isn't supported out of the box and that the component TextKit exist in order to render text on a background queue?
What would a good way of handling text input from a UIText{Field,View} be? Wrap the textDidChange etc delegates/notifications in an compontent action?
A declarative, efficient, and flexible JavaScript library for building user interfaces.
🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.
TypeScript is a superset of JavaScript that compiles to clean JavaScript output.
An Open Source Machine Learning Framework for Everyone
The Web framework for perfectionists with deadlines.
A PHP framework for web artisans
Bring data to life with SVG, Canvas and HTML. 📊📈🎉
JavaScript (JS) is a lightweight interpreted programming language with first-class functions.
Some thing interesting about web. New door for the world.
A server is a program made to process requests and deliver data to clients.
Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.
Some thing interesting about visualization, use data art
Some thing interesting about game, make everyone happy.
We are working to build community through open source technology. NB: members must have two-factor auth.
Open source projects and samples from Microsoft.
Google ❤️ Open Source for everyone.
Alibaba Open Source for everyone
Data-Driven Documents codes.
China tencent open source team.