Files
flipper/docs/extending/layout-inspector.md
Pritesh Nandgaonkar d022cd0e42 Add iOS docs draft for Layout Inspector
Summary:
Updated syntax and code references, but someone else please
check the details here.

Reviewed By: jknoxville

Differential Revision: D15181483

fbshipit-source-id: 93ed636c2d72f33151759e822d77e80e3abd6f03
2019-05-02 12:38:31 -07:00

6.1 KiB

id, title
id title
layout-inspector Extending Layout Inspector

The Layout Inspector plugin can be extended to support new kinds of UI components. You can also extend it to customize the data made available in the sidebar. Depending on whether you want to expose new data on Android or iOS, there are different interfaces you can use.

Layout Inspector

Android

Node Descriptor

To expose an object to the Layout Inspector in Flipper you have to implement a NodeDescriptor which describes your object. For example the ViewDescriptor describes View objects and the FragmentDescriptor describe Fragment instances. These descriptors have a set of callbacks used to expose children and data associated with the object they describe. See NodeDescriptor for the full API.

NodeDescriptor implementations should not subclass other NodeDescriptor implementations. Instead to re-use existing behavior from a more generic descriptor, you should prefer to use delegate.

Don't

class ViewGroupDescriptor extends ViewDescriptor<ViewGroup> {
  public String getName(ViewGroup node) {
    return super.getName(node);
  }
}

Do

class ViewGroupDescriptor extends NodeDescriptor<ViewGroup> {
  public String getName(ViewGroup node) {
    NodeDescriptor descriptor = descriptorForClass(View.class);
    return descriptor.getName(node);
  }
}

Register a Descriptor

Register your descriptor in the DescriptorMapping used to instantiate the InspectorFlipperPlugin.

final FlipperClient client = FlipperClient.createInstance(mContext);
final DescriptorMapping descriptorMapping = DescriptorMapping.withDefaults();
descriptorMapping.register(MyObject.class, new MyObjectDescriptor());
client.addPlugin(new InspectorFlipperPlugin(mContext, descriptorMapping));

Extending an existing Descriptor

You may not need to create a whole new descriptor but instead you may just want to change extend an existing one to expose some new piece of data. In that case just locate the correct descriptor and edit its getData, getAttributes and perhaps setData methods.

iOS

SKNodeDescriptor

To expose an object to the layout inspector in Sonar you have to implement a SKNodeDescriptor which describes the object. For example SKViewDescriptor describes UIView objects, and the SKComponentDescriptor describes CKComponent objects. These descriptors have necessary callbacks which is used to expose its children and data associated with the object they describe. See SKNodeDescriptor for the full available API.

SKNodeDescriptor implementations should never be subclass other SKNodeDescriptor implementations. Instead re-use existing behaviour by explicitly using other descriptors and delegate behaviour.

Don't

@interface SKArbitraryViewDescriptor : SKViewDescriptor<ArbitraryView *>

@end

@implementation SKArbitraryViewDescriptor

- (NSString *)identifierForNode:(ArbitraryView *)node 
{
  return [super identifierForNode:node];
}

@end

Do

@interface SKArbitraryViewDescriptor : SKNodeDescriptor<ArbitraryView *>
@end

@implementation SKArbitraryViewDescriptor

- (NSString *)identifierForNode:(ArbitraryView *)node 
{
  SKNodeDescriptor *descriptor = [self descriptorForClass:[UIView class]];
  return [descriptor identifierForNode:node];
}

@end

Register a Descriptor

In order to register your descriptor for an object, you use SKDescriptorMapper. After registering all descriptors you pass on the descriptor-mapper object to the plugin during initialisation.

[descriptorMapper registerDescriptor:[SKArbitraryViewDescriptor new]
                            forClass:[AbritraryView class]];
                                           

There's already a set of descriptors registered by default in SKDescriptorMapper, and if you want to add a descriptor to the default set you can do it in SKDescriptorMapper.

Extending an existing Descriptor

Sometimes all you need is to extend the functionality of an existing descriptor. In that case you just need to locate the correct descriptor and edit the methods dataForNode, attributesForNode, and possibly dataMutationsForNode.

Subdescriptors

If you want to extend the SKComponentKitLayoutDescriptor and add an additional section based on the nodes of the SKComponentLayoutDescriptor, you will have to subclass SKSubDescriptor.

#import <FlipperKitLayoutComponentKitSupport/SKSubDescriptor.h>

@interface YourSubDescriptor: SKSubDescriptor

@end


@implementation YourSubDescriptor

- (NSString *) getName {
  return @"Section Name";
}

- (NSString *)getDataForNode:(SKComponentLayoutWrapper *)node {
	return @"Meta data"
}

@end

#endif

Once you have implemented the descriptor, you will have to setup the Layout plugin as follows.

NSArray<SKSubDescriptor *> *registeredSubDescriptors = @[ yourSubDescriptors ];
SKDescriptorMapper *layoutDescriptorMapper = [[SKDescriptorMapper alloc] initWithDefaults];
[FlipperKitLayoutComponentKitSupport setUpWithDescriptorMapper: layoutDescriptorMapper subDescriptors: registeredSubDescriptors];
[client addPlugin: [[FlipperKitLayoutPlugin alloc] initWithRootNode: application
                                           withDescriptorMapper: layoutDescriptorMapper]];
let subDescriptors = [ yourSubDescriptors ]
let layoutDescriptorMapper = SKDescriptorMapper(defaults: ())
FlipperKitLayoutComponentKitSupport.setUpWith(layoutDescriptorMapper, subDescriptors: subDescriptors)
client?.add(FlipperKitLayoutPlugin(rootNode: application, with: layoutDescriptorMapper!))