feat:add iOS listview
This commit is contained in:
parent
6017e7120d
commit
8e53e4b54b
@ -20,6 +20,7 @@
|
||||
E2334AFE22E9D2070098A085 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = E2334AFD22E9D2070098A085 /* main.m */; };
|
||||
E2334B0822E9D2070098A085 /* ExampleTests.m in Sources */ = {isa = PBXBuildFile; fileRef = E2334B0722E9D2070098A085 /* ExampleTests.m */; };
|
||||
E2334B1322E9D2070098A085 /* ExampleUITests.m in Sources */ = {isa = PBXBuildFile; fileRef = E2334B1222E9D2070098A085 /* ExampleUITests.m */; };
|
||||
E2BF7BF7237E8E9F001B0EDC /* ListDemo.js in Resources */ = {isa = PBXBuildFile; fileRef = E2BF7BF6237E8E9F001B0EDC /* ListDemo.js */; };
|
||||
/* End PBXBuildFile section */
|
||||
|
||||
/* Begin PBXContainerItemProxy section */
|
||||
@ -67,6 +68,7 @@
|
||||
E2334B0E22E9D2070098A085 /* ExampleUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = ExampleUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||
E2334B1222E9D2070098A085 /* ExampleUITests.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ExampleUITests.m; sourceTree = "<group>"; };
|
||||
E2334B1422E9D2070098A085 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; };
|
||||
E2BF7BF6237E8E9F001B0EDC /* ListDemo.js */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.javascript; path = ListDemo.js; sourceTree = "<group>"; };
|
||||
/* End PBXFileReference section */
|
||||
|
||||
/* Begin PBXFrameworksBuildPhase section */
|
||||
@ -123,6 +125,7 @@
|
||||
E21DC9D12302865E00660C5C /* src */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
E2BF7BF6237E8E9F001B0EDC /* ListDemo.js */,
|
||||
E21DC9D22302865E00660C5C /* Snake.js */,
|
||||
E21DC9D32302865E00660C5C /* Counter.js */,
|
||||
);
|
||||
@ -295,6 +298,7 @@
|
||||
isa = PBXResourcesBuildPhase;
|
||||
buildActionMask = 2147483647;
|
||||
files = (
|
||||
E2BF7BF7237E8E9F001B0EDC /* ListDemo.js in Resources */,
|
||||
E21DC9D42302870000660C5C /* Snake.js in Resources */,
|
||||
E21DC9D52302870000660C5C /* Counter.js in Resources */,
|
||||
E2334AFB22E9D2070098A085 /* LaunchScreen.storyboard in Resources */,
|
||||
|
@ -26,7 +26,7 @@ @implementation ViewController
|
||||
- (void)viewDidLoad {
|
||||
[super viewDidLoad];
|
||||
|
||||
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"Snake" ofType:@"js"];
|
||||
NSString *path = [[NSBundle bundleForClass:[self class]] pathForResource:@"ListDemo" ofType:@"js"];
|
||||
NSString *jsContent = [NSString stringWithContentsOfFile:path encoding:NSUTF8StringEncoding error:nil];
|
||||
self.doricContext = [[DoricContext alloc] initWithScript:jsContent source:@"test.js"];
|
||||
[self.doricContext.rootNode setupRootView:[[DoricStackView new] also:^(DoricStackView *it) {
|
||||
|
@ -28,6 +28,8 @@
|
||||
#import "DoricHLayoutNode.h"
|
||||
#import "DoricTextNode.h"
|
||||
#import "DoricImageNode.h"
|
||||
#import "DoricListNode.h"
|
||||
#import "DoricListItemNode.h"
|
||||
|
||||
@interface DoricRegistry ()
|
||||
|
||||
@ -58,6 +60,8 @@ - (void)innerRegister {
|
||||
[self registerViewNode:DoricHLayoutNode.class withName:@"HLayout"];
|
||||
[self registerViewNode:DoricTextNode.class withName:@"Text"];
|
||||
[self registerViewNode:DoricImageNode.class withName:@"Image"];
|
||||
[self registerViewNode:DoricListNode.class withName:@"List"];
|
||||
[self registerViewNode:DoricListItemNode.class withName:@"ListItem"];
|
||||
}
|
||||
|
||||
- (void)registerJSBundle:(NSString *)bundle withName:(NSString *)name {
|
||||
|
26
iOS/Pod/Classes/Shader/DoricListItemNode.h
Normal file
26
iOS/Pod/Classes/Shader/DoricListItemNode.h
Normal file
@ -0,0 +1,26 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/15.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
|
||||
#import "DoricStackNode.h"
|
||||
|
||||
@interface DoricListItemNode : DoricGroupNode<UITableViewCell *>
|
||||
|
||||
@end
|
27
iOS/Pod/Classes/Shader/DoricListItemNode.m
Normal file
27
iOS/Pod/Classes/Shader/DoricListItemNode.m
Normal file
@ -0,0 +1,27 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/15.
|
||||
//
|
||||
|
||||
#import "DoricListItemNode.h"
|
||||
|
||||
|
||||
@implementation DoricListItemNode
|
||||
- (UITableViewCell *)build {
|
||||
return nil;
|
||||
}
|
||||
@end
|
24
iOS/Pod/Classes/Shader/DoricListNode.h
Normal file
24
iOS/Pod/Classes/Shader/DoricListNode.h
Normal file
@ -0,0 +1,24 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/15.
|
||||
//
|
||||
|
||||
#import <Foundation/Foundation.h>
|
||||
#import "DoricSuperNode.h"
|
||||
@interface DoricListNode : DoricSuperNode<UITableView *>
|
||||
|
||||
@end
|
113
iOS/Pod/Classes/Shader/DoricListNode.m
Normal file
113
iOS/Pod/Classes/Shader/DoricListNode.m
Normal file
@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Copyright [2019] [Doric.Pub]
|
||||
*
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
//
|
||||
// Created by pengfei.zhou on 2019/11/15.
|
||||
//
|
||||
|
||||
#import <JavaScriptCore/JavaScriptCore.h>
|
||||
#import "DoricListNode.h"
|
||||
#import "DoricExtensions.h"
|
||||
#import "DoricListItemNode.h"
|
||||
|
||||
@interface DoricListNode () <UITableViewDataSource, UITableViewDelegate>
|
||||
@property(nonatomic, strong) NSMutableDictionary <NSNumber *, DoricListItemNode *> *tempNodes;
|
||||
@property(nonatomic, assign) NSUInteger itemCount;
|
||||
@property(nonatomic, assign) NSUInteger batchCount;
|
||||
@end
|
||||
|
||||
@implementation DoricListNode
|
||||
- (instancetype)initWithContext:(DoricContext *)doricContext {
|
||||
if (self = [super initWithContext:doricContext]) {
|
||||
_tempNodes = [NSMutableDictionary new];
|
||||
_batchCount = 15;
|
||||
}
|
||||
return self;
|
||||
}
|
||||
|
||||
- (UITableView *)build {
|
||||
return [[UITableView new] also:^(UITableView *it) {
|
||||
it.dataSource = self;
|
||||
it.delegate = self;
|
||||
}];
|
||||
}
|
||||
|
||||
- (void)blendView:(UITableView *)view forPropName:(NSString *)name propValue:(id)prop {
|
||||
if ([@"itemCount" isEqualToString:name]) {
|
||||
self.itemCount = [prop unsignedIntegerValue];
|
||||
} else if ([@"renderItem" isEqualToString:name]) {
|
||||
[self.tempNodes removeAllObjects];
|
||||
[self clearSubModel];
|
||||
} else if ([@"batchCount" isEqualToString:name]) {
|
||||
self.batchCount = [prop unsignedIntegerValue];
|
||||
} else {
|
||||
[super blendView:view forPropName:name propValue:prop];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)blend:(NSDictionary *)props {
|
||||
[super blend:props];
|
||||
[self.view reloadData];
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
|
||||
return self.itemCount;
|
||||
}
|
||||
|
||||
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
NSUInteger position = (NSUInteger) indexPath.row;
|
||||
NSDictionary *model = [self itemModelAt:position];
|
||||
NSDictionary *props = model[@"props"];
|
||||
NSString *reuseId = props[@"identifier"];
|
||||
|
||||
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId];
|
||||
if (!cell) {
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseId];
|
||||
}
|
||||
DoricListItemNode *node = self.tempNodes[@(position)];
|
||||
node.view = cell;
|
||||
[node blend:props];
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
|
||||
NSUInteger position = (NSUInteger) indexPath.row;
|
||||
NSDictionary *model = [self itemModelAt:position];
|
||||
|
||||
return 60;
|
||||
}
|
||||
|
||||
- (NSDictionary *)itemModelAt:(NSUInteger)position {
|
||||
NSString *viewId = self.tempNodes[@(position)].viewId;
|
||||
if (viewId && viewId.length > 0) {
|
||||
return [self subModelOf:viewId];
|
||||
} else {
|
||||
DoricAsyncResult *result = [self callJSResponse:@"renderBunchedItems", @(position), @(self.batchCount), nil];
|
||||
JSValue *models = [result waitUntilResult];
|
||||
NSArray *array = [models toArray];
|
||||
[array enumerateObjectsUsingBlock:^(NSDictionary *obj, NSUInteger idx, BOOL *stop) {
|
||||
NSString *thisViewId = obj[@"id"];
|
||||
[self setSubModel:obj in:thisViewId];
|
||||
NSUInteger pos = position + idx;
|
||||
DoricListItemNode *node = [[DoricListItemNode alloc] initWithContext:self.doricContext];
|
||||
node.viewId = thisViewId;
|
||||
[node initWithSuperNode:self];
|
||||
self.tempNodes[@(pos)] = node;
|
||||
}];
|
||||
return array[0];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
@ -48,9 +48,9 @@ NS_ASSUME_NONNULL_BEGIN
|
||||
|
||||
- (void)blendView:(V)view forPropName:(NSString *)name propValue:(id)prop;
|
||||
|
||||
- (void)callJSResponse:(NSString *)funcId, ...;
|
||||
- (DoricAsyncResult *)callJSResponse:(NSString *)funcId, ...;
|
||||
|
||||
+ (DoricViewNode *)create:(DoricContext *)context withType:(NSString *)type;
|
||||
+ (__kindof DoricViewNode *)create:(DoricContext *)context withType:(NSString *)type;
|
||||
|
||||
- (void)requestLayout;
|
||||
@end
|
||||
|
@ -193,7 +193,7 @@ - (void)onClick:(UIView *)view {
|
||||
return [[ret reverseObjectEnumerator] allObjects];
|
||||
}
|
||||
|
||||
- (void)callJSResponse:(NSString *)funcId, ... {
|
||||
- (DoricAsyncResult *)callJSResponse:(NSString *)funcId, ... {
|
||||
NSMutableArray *array = [[NSMutableArray alloc] init];
|
||||
[array addObject:self.idList];
|
||||
[array addObject:funcId];
|
||||
@ -203,11 +203,12 @@ - (void)callJSResponse:(NSString *)funcId, ... {
|
||||
while ((arg = va_arg(args, id)) != nil) {
|
||||
[array addObject:arg];
|
||||
}
|
||||
[self.doricContext callEntity:DORIC_ENTITY_RESPONSE withArgumentsArray:array];
|
||||
DoricAsyncResult *ret = [self.doricContext callEntity:DORIC_ENTITY_RESPONSE withArgumentsArray:array];
|
||||
va_end(args);
|
||||
return ret;
|
||||
}
|
||||
|
||||
+ (DoricViewNode *)create:(DoricContext *)context withType:(NSString *)type {
|
||||
+ (__kindof DoricViewNode *)create:(DoricContext *)context withType:(NSString *)type {
|
||||
DoricRegistry *registry = context.driver.registry;
|
||||
Class clz = [registry acquireViewNode:type];
|
||||
return [(DoricViewNode *) [clz alloc] initWithContext:context];
|
||||
|
@ -43,6 +43,8 @@ typedef void(^DoricFinishCallback)(void);
|
||||
- (BOOL)hasResult;
|
||||
|
||||
- (R)getResult;
|
||||
|
||||
- (R)waitUntilResult;
|
||||
@end
|
||||
|
||||
NS_ASSUME_NONNULL_END
|
||||
|
@ -22,31 +22,32 @@
|
||||
|
||||
#import "DoricAsyncResult.h"
|
||||
|
||||
@interface DoricAsyncResult()
|
||||
@property(nonatomic,strong) id result;
|
||||
@interface DoricAsyncResult ()
|
||||
@property(nonatomic, strong) id result;
|
||||
@end
|
||||
|
||||
@implementation DoricAsyncResult
|
||||
|
||||
- (void)setupResult:(id)result {
|
||||
self.result = result;
|
||||
if(self.resultCallback){
|
||||
if (self.resultCallback) {
|
||||
self.resultCallback(result);
|
||||
}
|
||||
if(self.finishCallback){
|
||||
if (self.finishCallback) {
|
||||
self.finishCallback();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setupError:(NSException *)exception {
|
||||
self.result = exception;
|
||||
if(self.exceptionCallback){
|
||||
if (self.exceptionCallback) {
|
||||
self.exceptionCallback(exception);
|
||||
}
|
||||
if(self.finishCallback){
|
||||
if (self.finishCallback) {
|
||||
self.finishCallback();
|
||||
}
|
||||
}
|
||||
|
||||
- (BOOL)hasResult {
|
||||
return self.result;
|
||||
}
|
||||
@ -57,22 +58,35 @@ - (id)getResult {
|
||||
|
||||
- (void)setResultCallback:(DoricResultCallback)callback {
|
||||
_resultCallback = callback;
|
||||
if(self.result && ![self.result isKindOfClass: [NSException class]]){
|
||||
if (self.result && ![self.result isKindOfClass:[NSException class]]) {
|
||||
callback(self.result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setExceptionCallback:(DoricExceptionCallback)exceptionCallback {
|
||||
_exceptionCallback = exceptionCallback;
|
||||
if([self.result isKindOfClass: [NSException class]]){
|
||||
if ([self.result isKindOfClass:[NSException class]]) {
|
||||
exceptionCallback(self.result);
|
||||
}
|
||||
}
|
||||
|
||||
- (void)setFinishCallback:(DoricFinishCallback)callback {
|
||||
_finishCallback = callback;
|
||||
if(self.result){
|
||||
if (self.result) {
|
||||
callback();
|
||||
}
|
||||
}
|
||||
|
||||
- (id)waitUntilResult {
|
||||
if (self.result) {
|
||||
return self.result;
|
||||
}
|
||||
|
||||
dispatch_semaphore_t semaphore = dispatch_semaphore_create(0);
|
||||
self.resultCallback = ^(id r) {
|
||||
dispatch_semaphore_signal(semaphore);
|
||||
};
|
||||
dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER);
|
||||
return self.result;
|
||||
}
|
||||
@end
|
||||
|
Reference in New Issue
Block a user