Repository: incubator-weex Updated Branches: refs/heads/master 7984b16c7 -> e31458ac3
* [iOS] use the first cell-slot template while the templateType is not specified * [iOS] support componentHook callJS method * [iOS] create life-cycle for recycle-list component * [iOS] support lifecycle about create, destroy, attach and detach * [iOS] fix compiler complains * [iOS] use switch and case for template selection * [iOS] remove unused code * [iOS] update read default case * [iOS] support lifecycle for recycleList component close #1023 * [iOS] add component method for operating data * [iOS] bugfix * [iOS] rename @componentId to @templateId * [iOS] support v-once * [iOS] support non-object in javaScript on data * [iOS] bugfix about insertRange on recycleList * [iOS] formate data * [iOS] add recycleListComponentRef for data * [iOS] fix bug about v-once * [iOS] log interrupt update info * [iOS] bugfix about parse member property * [iOS] bugfix about recyle-list * [iOS] update playground version Project: http://git-wip-us.apache.org/repos/asf/incubator-weex/repo Commit: http://git-wip-us.apache.org/repos/asf/incubator-weex/commit/e31458ac Tree: http://git-wip-us.apache.org/repos/asf/incubator-weex/tree/e31458ac Diff: http://git-wip-us.apache.org/repos/asf/incubator-weex/diff/e31458ac Branch: refs/heads/master Commit: e31458ac334446a1d83a8c424676bc8961bc960e Parents: 7984b16 Author: acton393 <zhangxing610...@gmail.com> Authored: Mon Dec 25 17:54:49 2017 +0800 Committer: acton393 <zhangxing610...@gmail.com> Committed: Fri Feb 9 19:23:33 2018 +0800 ---------------------------------------------------------------------- ios/playground/WeexDemo/Info.plist | 4 +- .../WeexSDK/Sources/Bridge/WXBridgeContext.h | 3 + .../WeexSDK/Sources/Bridge/WXBridgeContext.m | 27 +++ .../Component/RecycleList/WXCellSlotComponent.h | 3 +- .../Component/RecycleList/WXCellSlotComponent.m | 7 +- .../RecycleList/WXComponent+DataBinding.h | 2 +- .../RecycleList/WXComponent+DataBinding.mm | 89 ++++++- .../Component/RecycleList/WXJSASTParser.mm | 3 +- .../RecycleList/WXRecycleListComponent.h | 11 +- .../RecycleList/WXRecycleListComponent.m | 236 ++++++++++++++----- .../RecycleList/WXRecycleListDataManager.h | 11 + .../RecycleList/WXRecycleListDataManager.m | 56 +++++ .../RecycleList/WXRecycleListTemplateManager.h | 2 + .../RecycleList/WXRecycleListTemplateManager.m | 14 +- .../RecycleList/WXRecycleListUpdateManager.m | 5 - .../Component/Recycler/WXRecyclerComponent.m | 1 - .../Sources/Component/WXComponent_internal.h | 2 + .../WeexSDK/Sources/Events/WXComponent+Events.m | 25 ++ .../WeexSDK/Sources/Manager/WXBridgeManager.h | 9 + .../WeexSDK/Sources/Manager/WXBridgeManager.m | 14 ++ .../Sources/Manager/WXComponentManager.m | 4 +- ios/sdk/WeexSDK/Sources/Model/WXComponent.m | 3 + ios/sdk/WeexSDK/Sources/Module/WXDomModule.m | 16 ++ .../Sources/View/WXComponent+ViewManagement.m | 4 + 24 files changed, 468 insertions(+), 83 deletions(-) ---------------------------------------------------------------------- http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/playground/WeexDemo/Info.plist ---------------------------------------------------------------------- diff --git a/ios/playground/WeexDemo/Info.plist b/ios/playground/WeexDemo/Info.plist index 6fd3e06..5ee55ec 100644 --- a/ios/playground/WeexDemo/Info.plist +++ b/ios/playground/WeexDemo/Info.plist @@ -26,7 +26,7 @@ <key>CFBundlePackageType</key> <string>APPL</string> <key>CFBundleShortVersionString</key> - <string>2.0</string> + <string>2.2</string> <key>CFBundleSignature</key> <string>????</string> <key>CFBundleURLTypes</key> @@ -39,7 +39,7 @@ </dict> </array> <key>CFBundleVersion</key> - <string>2</string> + <string>3</string> <key>LSRequiresIPhoneOS</key> <true/> <key>NSAppTransportSecurity</key> http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h index 8ef129f..b3b66b6 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.h @@ -18,6 +18,7 @@ */ #import <Foundation/Foundation.h> +#import <JavaScriptCore/JavaScriptCore.h> @class WXCallJSMethod; @class WXSDKInstance; @@ -122,4 +123,6 @@ **/ - (void)resetEnvironment; +- (void)callJSMethod:(NSString *)method args:(NSArray *)args onContext:(JSContext*)context completion:(void (^)(JSValue * value))complection; + @end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m index 5af88a0..af473cf 100644 --- a/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m +++ b/ios/sdk/WeexSDK/Sources/Bridge/WXBridgeContext.m @@ -557,6 +557,33 @@ _Pragma("clang diagnostic pop") \ [self performSelector:@selector(_sendQueueLoop) withObject:nil]; } +- (void)callJSMethod:(NSString *)method args:(NSArray *)args onContext:(JSContext*)context completion:(void (^)(JSValue * value))complection +{ + NSMutableArray *newArg = nil; + if (!context) { + if ([self.jsBridge isKindOfClass:[WXJSCoreBridge class]]) { + context = [(NSObject*)_jsBridge valueForKey:@"jsContext"]; + } + } + if (self.frameworkLoadFinished) { + newArg = [args mutableCopy]; + if ([newArg containsObject:complection]) { + [newArg removeObject:complection]; + } + WXLogDebug(@"Calling JS... method:%@, args:%@", method, args); + JSValue *value = [[context globalObject] invokeMethod:method withArguments:args]; + if (complection) { + complection(value); + } + } else { + newArg = [args mutableCopy]; + if (complection) { + [newArg addObject:complection]; + } + [_methodQueue addObject:@{@"method":method, @"args":[newArg copy]}]; + } +} + - (void)executeAllJsService { for(NSDictionary *service in _jsServiceQueue) { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.h index 4e62676..e3721be 100644 --- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.h +++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.h @@ -20,9 +20,10 @@ #import <Foundation/Foundation.h> #import "WXComponent.h" +static const NSString *WXDefaultRecycleTemplateType = @"default"; @interface WXCellSlotComponent : WXComponent -@property (nonatomic, strong) NSString *templateType; +@property (nonatomic, strong) NSString *templateCaseType; - (void)updateCellData:(NSDictionary *)data; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m index 0cbd97b..a6adec0 100644 --- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXCellSlotComponent.m @@ -25,8 +25,6 @@ #import "WXAssert.h" #import "WXScrollerComponent.h" -static const NSString *WXDefaultRecycleTemplateType = @"WXDefaultRecycleTemplateType"; - @implementation WXCellSlotComponent - (instancetype)initWithRef:(NSString *)ref @@ -39,7 +37,10 @@ static const NSString *WXDefaultRecycleTemplateType = @"WXDefaultRecycleTemplate self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]; if (self) { // TODO: isRecycle / insertAnimation / deleteAnimation / keepScrollPosition - _templateType = attributes[@"templateType"] ? [WXConvert NSString:attributes[@"templateType"]] : WXDefaultRecycleTemplateType; + if (attributes[@"default"]) { + _templateCaseType = @"default"; + } + _templateCaseType = attributes[@"case"] ? [WXConvert NSString:attributes[@"case"]] : WXDefaultRecycleTemplateType; _lazyCreateView = YES; _isNeedJoinLayoutSystem = NO; } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h index 971252a..b68b159 100644 --- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h +++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.h @@ -22,10 +22,10 @@ static const NSString *WXBindingIdentify = @"@binding"; static const NSString *WXBindingMatchIdentify = @"[[match]]"; static const NSString *WXBindingRepeatIdentify = @"[[repeat]]"; +static const NSString *WXBindingOnceIdentify = @"[[once]]"; static const NSString *WXBindingRepeatExprIdentify = @"@expression"; static const NSString *WXBindingRepeatIndexIdentify = @"@index"; static const NSString *WXBindingRepeatLabelIdentify = @"@alias"; @interface WXComponent (DataBinding) - @end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm index aad49da..aeb6a36 100644 --- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm +++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXComponent+DataBinding.mm @@ -21,8 +21,13 @@ #import "WXComponent_internal.h" #import "WXSDKInstance_private.h" #import "WXComponentManager.h" +#import "WXSDKManager.h" #import "WXAssert.h" #import "WXJSASTParser.h" +#import "WXBridgeManager.h" +#import "WXUtility.h" +#import "WXRecycleListComponent.h" +#import "WXRecycleListDataManager.h" #import <JavaScriptCore/JavaScriptCore.h> @@ -43,7 +48,30 @@ static JSContext *jsContext; - (void)updateBindingData:(NSDictionary *)data { WXAssertComponentThread(); + NSString * listRef = nil; + NSIndexPath *indexPath = nil; + NSDictionary * dictionary = nil; + listRef = data[@"recycleListComponentRef"]; + indexPath = data[@"indexPath"]; + NSString *phase = data[@"@phase"]; + if (!indexPath || !listRef) { + if (data[@"aliasKey"]) { + id key = data[@"aliasKey"]; + dictionary = data[key]; + } else { + dictionary = data; + } + listRef = dictionary[@"recycleListComponentRef"]; + indexPath = dictionary[@"indexPath"]; + } + if (!phase && dictionary) { + phase = dictionary[@"@phase"]; + } + if (!indexPath || !listRef) { + return; + } + WXRecycleListComponent * recycleListComponent = (WXRecycleListComponent*)[self.weexInstance.componentManager componentForRef:listRef]; if (_isSkipUpdate) { _isSkipUpdate = NO; return; @@ -62,7 +90,7 @@ static JSContext *jsContext; } if (templateComponent->_bindingProps) { - NSMutableDictionary *newData = [NSMutableDictionary dictionary]; + __block NSMutableDictionary *newData = [NSMutableDictionary dictionary]; [templateComponent->_bindingProps enumerateKeysAndObjectsUsingBlock:^(NSString * _Nonnull key, WXDataBindingBlock _Nonnull block, BOOL * _Nonnull stop) { BOOL needUpdate; id value = block(data, &needUpdate); @@ -71,9 +99,43 @@ static JSContext *jsContext; } }]; + if (self.attributes[@"@isComponentRoot"]) { + if (![recycleListComponent.dataManager virtualComponentDataWithIndexPath:indexPath]) { + static NSUInteger __componentId = 0; + self->_virtualComponentId = [NSString stringWithFormat:@"%@@%ld", listRef, __componentId % (2048*1024)]; + __componentId++; + dispatch_semaphore_t semaphore = dispatch_semaphore_create(0); + [[WXSDKManager bridgeMgr] callComponentHook:self.weexInstance.instanceId componentId:self.attributes[@"@templateId"] type:@"lifecycle" hook:@"create" args:@[self->_virtualComponentId, newData] competion:^(JSValue *value) { + [newData addEntriesFromDictionary:[value toDictionary][@"0"]]; + [newData setObject:indexPath forKey:@"indexPath"]; + [newData setObject:listRef forKey:@"recycleListComponentRef"]; + [[recycleListComponent dataManager] updateVirtualComponentData:self->_virtualComponentId data:newData]; + dispatch_semaphore_signal(semaphore); + }]; + dispatch_semaphore_wait(semaphore, DISPATCH_TIME_FOREVER); + + [[WXSDKManager bridgeMgr] callComponentHook:self.weexInstance.instanceId componentId:self->_virtualComponentId type:@"lifecycle" hook:@"attach" args:nil competion:nil]; + if ([newData count]) { + data = newData; + } + } else { + newData[@"componentDataId"] = self->_virtualComponentId; + NSDictionary * virtualComponentData = [recycleListComponent.dataManager virtualComponentDataWithIndexPath:indexPath]; + [newData addEntriesFromDictionary:virtualComponentData]; + [newData addEntriesFromDictionary:data]; + data = newData; + } + } + } + if (phase) { + NSMutableDictionary * newData = [data mutableCopy]; + newData[@"@phase"] = phase; data = newData; } - + if (self->_templateComponent && self->_templateComponent->_dataBindOnce && recycleListComponent && data[@"@phase"]) { + WXLogInfo(@"interrupt update data: %@ because of v-once ", data); + return; + } if (!_isRepeating) { WXDataBindingBlock repeatBlock = templateComponent->_bindingRepeat; if (repeatBlock) { @@ -126,12 +188,16 @@ static JSContext *jsContext; [self.weexInstance.componentManager updateAttributes:newAttributesOrStyles forComponent:self.ref]; } else if (i == WXDataBindingTypeEvents) { [self _addEventParams:newAttributesOrStyles]; + } else if (i == WXDataBindingTypeProp) { } } } NSArray *subcomponents = self.subcomponents; for (WXComponent *subcomponent in subcomponents) { + if (subcomponent->_virtualComponentId &&dictionary[@"componentDataId"] && ![subcomponent->_virtualComponentId isEqualToString:dictionary[@"componentDataId"]]) { + continue; + } [subcomponent updateBindingData:data]; } } @@ -289,7 +355,9 @@ static JSContext *jsContext; } if (type == WXDataBindingTypeAttributes) { - if ([WXBindingMatchIdentify isEqualToString:name]) { + if ([WXBindingOnceIdentify isEqualToString:name]) { + _dataBindOnce = [WXConvert BOOL:binding]; + } else if ([WXBindingMatchIdentify isEqualToString:name]) { WXJSASTParser *parser = [WXJSASTParser parserWithScript:binding]; WXJSExpression *expression = [parser parseExpression]; _bindingMatch = [self bindingBlockWithExpression:expression]; @@ -323,7 +391,7 @@ static JSContext *jsContext; *needUpdate = NO; return nil; } else if (expression->is<WXJSIdentifier>()) { - NSString *identiferName = [NSString stringWithCString:(((WXJSIdentifier *)expression)->name).c_str() encoding:[NSString defaultCStringEncoding]]; + NSString *identiferName = [NSString stringWithCString:const_cast<char*>((((WXJSIdentifier *)expression)->name).c_str()) encoding:NSUTF8StringEncoding]; if (data[identiferName]) { *needUpdate = YES; return data[identiferName]; @@ -344,9 +412,16 @@ static JSContext *jsContext; return [object objectAtIndex:[propertyName unsignedIntegerValue]]; } } else { - NSString *propertyName = [NSString stringWithCString:(((WXJSStringLiteral *)member->property)->value).c_str() encoding:[NSString defaultCStringEncoding]]; - *needUpdate = objectNeedUpdate; - return object[propertyName]; + WXJSExpression * memberExpression = member->property; + if (memberExpression->is<WXJSIdentifier>()) { + NSString *propertyName = [NSString stringWithCString:(((WXJSStringLiteral *)member->property)->value).c_str() encoding:[NSString defaultCStringEncoding]]; + *needUpdate = objectNeedUpdate; + return object[propertyName]; + } else { + id retvalue = [self bindingBlockWithExpression:member->property](object, &objectNeedUpdate); + *needUpdate = objectNeedUpdate || propertyNeedUpdate; + return retvalue; + } } return nil; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm index 7e7a565..0be6647 100644 --- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm +++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXJSASTParser.mm @@ -826,10 +826,9 @@ static int binaryPrecedence(WXJSToken *token) - (WXJSExpression *)parseMemberExpression { WXJSExpression *expr = [self parsePrimaryExpression]; - if ([self match:"."]) { [self expect:"."]; - WXJSExpression *property = [self parsePrimaryExpression]; + WXJSExpression * property = [self parseMemberExpression]; WXJSMemberExpression *memberExpr = new WXJSMemberExpression(); memberExpr->object = expr; memberExpr->property = property; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h index a072752..e4be617 100644 --- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h +++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.h @@ -20,6 +20,15 @@ #import <Foundation/Foundation.h> #import "WXScrollerComponent.h" -@interface WXRecycleListComponent : WXScrollerComponent +@class WXRecycleListDataManager; +@class WXRecycleListTemplateManager; +@class WXRecycleListUpdateManager; + +@interface WXRecycleListComponent : WXScrollerComponent + +@property(nonatomic, strong) WXRecycleListDataManager *dataManager; +@property(nonatomic, strong) WXRecycleListTemplateManager *templateManager; +@property(nonatomic, strong) WXRecycleListUpdateManager *updateManager; + @end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m index 71a52f5..03f233a 100644 --- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListComponent.m @@ -29,6 +29,9 @@ #import "WXRecycleListDataManager.h" #import "WXRecycleListTemplateManager.h" #import "WXRecycleListUpdateManager.h" +#import "WXBridgeManager.h" +#import "WXSDKManager.h" +#import "WXComponent+DataBinding.h" @interface WXRecycleListComponent () <WXRecycleListLayoutDelegate, WXRecycleListUpdateDelegate, UICollectionViewDelegateFlowLayout, UICollectionViewDataSource> @@ -36,11 +39,7 @@ @implementation WXRecycleListComponent { - WXRecycleListDataManager *_dataManager; - WXRecycleListTemplateManager *_templateManager; - WXRecycleListUpdateManager *_updateManager; - - NSString *_templateKey; + NSString *_templateSwitchKey; NSString *_aliasKey; NSString *_indexKey; __weak UICollectionView *_collectionView; @@ -52,11 +51,14 @@ } WX_EXPORT_METHOD(@selector(appendData:)) -WX_EXPORT_METHOD(@selector(insertData:atIndex:)) -WX_EXPORT_METHOD(@selector(updateData:atIndex:)) -WX_EXPORT_METHOD(@selector(removeData:)) +WX_EXPORT_METHOD(@selector(appendRange:)) +WX_EXPORT_METHOD(@selector(insertData:data:)) +WX_EXPORT_METHOD(@selector(updateData:data:)) +WX_EXPORT_METHOD(@selector(removeData:count:)) WX_EXPORT_METHOD(@selector(moveData:toIndex:)) WX_EXPORT_METHOD(@selector(scrollTo:options:)) +WX_EXPORT_METHOD(@selector(insertRange:range:)) +WX_EXPORT_METHOD(@selector(setListData:)) - (instancetype)initWithRef:(NSString *)ref type:(NSString *)type @@ -66,11 +68,11 @@ WX_EXPORT_METHOD(@selector(scrollTo:options:)) weexInstance:(WXSDKInstance *)weexInstance { if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) { - _dataManager = [[WXRecycleListDataManager alloc] initWithData:attributes[@"listData"]]; + _dataManager = attributes[@"listData"]? [[WXRecycleListDataManager alloc] initWithData:attributes[@"listData"]] : [WXRecycleListDataManager new]; _templateManager = [WXRecycleListTemplateManager new]; _updateManager = [WXRecycleListUpdateManager new]; _updateManager.delegate = self; - _templateKey = [WXConvert NSString:attributes[@"templateKey"]] ? : @"templateType"; + _templateSwitchKey = [WXConvert NSString:attributes[@"switch"]]; _aliasKey = [WXConvert NSString:attributes[@"alias"]]; _indexKey = [WXConvert NSString:attributes[@"index"]]; _sizeCache = [NSMutableDictionary dictionary]; @@ -120,6 +122,15 @@ WX_EXPORT_METHOD(@selector(scrollTo:options:)) NSArray *listData = attributes[@"listData"]; [self _updateListData:listData withCompletion:nil animation:NO]; } + if (attributes[@"switch"]) { + _templateSwitchKey = [WXConvert NSString:attributes[@"switch"]]; + } + if (attributes[@"alias"]) { + _aliasKey = [WXConvert NSString:attributes[@"alias"]]; + } + if (attributes[@"index"]) { + _indexKey = [WXConvert NSString:attributes[@"index"]]; + } } - (CGPoint)absolutePositionForComponent:(WXComponent *)component @@ -179,18 +190,33 @@ WX_EXPORT_METHOD(@selector(scrollTo:options:)) #pragma mark - Exported Component Methods -- (void)appendData:(NSArray *)appendingData +- (void)appendData:(id)appendingData { - if (![appendingData isKindOfClass:[NSArray class]]) { - WXLogError(@"wrong format of appending data:%@", appendingData); + if (!appendingData){ + return; + } + NSMutableArray * newListData = [[_dataManager data] mutableCopy]; + [newListData addObject:appendingData]; +} + +- (void)appendRange:(NSArray*)data +{ + if (![data isKindOfClass:[NSArray class]]) { + WXLogError(@"wrong format of appending data:%@", data); return; } NSArray *oldData = [_dataManager data]; - [_updateManager updateWithAppendingData:appendingData oldData:oldData completion:nil animation:NO]; + [_updateManager updateWithAppendingData:data oldData:oldData completion:nil animation:NO]; } -- (void)insertData:(id)data atIndex:(NSUInteger)index +- (void)setListData:(NSArray*)data +{ + if ([data count]) { + [_dataManager updateData:data]; + } +} +- (void)insertData:(NSUInteger)index data:(id)data { // TODO: bring the update logic to UpdateManager // TODO: update cell because index has changed @@ -202,47 +228,110 @@ WX_EXPORT_METHOD(@selector(scrollTo:options:)) NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0]; [UIView performWithoutAnimation:^{ - [_collectionView insertItemsAtIndexPaths:@[indexPath]]; + [self->_collectionView insertItemsAtIndexPaths:@[indexPath]]; }]; } } -- (void)updateData:(id)data atIndex:(NSUInteger)index +- (void)updateComponentData:(NSString*)componentDataId componentData:(NSDictionary*)componentData callback:(NSString*)callbackId { - // TODO: bring the update logic to UpdateManager - NSMutableArray *newListData = [[_dataManager data] mutableCopy]; - if (index < newListData.count) { - newListData[index] = data; - [_dataManager updateData:newListData]; - - NSIndexPath *indexPath = [NSIndexPath indexPathForItem:index inSection:0]; - UICollectionViewCell *cellView = [_collectionView cellForItemAtIndexPath:indexPath]; - WXCellSlotComponent *cellComponent = (WXCellSlotComponent *)cellView.wx_component; - if (cellComponent) { - [self _updateBindingData:data forCell:cellComponent atIndexPath:indexPath]; + NSMutableDictionary * virtualComponentData = [[_dataManager virtualComponentDataWithId:componentDataId] mutableCopy]; + NSIndexPath * indexPath = virtualComponentData[@"indexPath"]; + if (!indexPath) { + return; + } + virtualComponentData = virtualComponentData?:[NSMutableDictionary new]; + [virtualComponentData addEntriesFromDictionary:componentData]; + [_dataManager updateVirtualComponentData:componentDataId data:[virtualComponentData copy]]; + virtualComponentData[@"@phase"] = @"update"; + virtualComponentData[@"callbackId"] = callbackId; + [self _updateDataForCellSlotAtIndexPath:indexPath data:virtualComponentData]; +} + +- (void)_updateDataForCellSlotAtIndexPath:(NSIndexPath*)indexPath data:(NSDictionary*)data +{ + if(!indexPath || !data) { + return; + } + WXPerformBlockOnMainThread(^{ + UICollectionViewCell * cellView = [self->_collectionView cellForItemAtIndexPath:indexPath]; + WXCellSlotComponent * cellSlotComponent = (WXCellSlotComponent*)cellView.wx_component; + if (cellSlotComponent) { + [self _updateBindingData:data forCell:cellSlotComponent atIndexPath:indexPath]; } + // callback when update virtual component data success. + NSString * callbackId = data[@"callbackId"]; + if (callbackId) { + [[WXSDKManager bridgeMgr] callBack:self.weexInstance.instanceId funcId:callbackId params:@{@"result":@"success"}]; + } + }); +} + +- (void)updateData:(NSUInteger)index data:(id)data +{ + NSMutableArray * newListData = [[_dataManager data] mutableCopy]; + if (!data && index > [newListData count]) { + return; + } + NSIndexPath * indexPath = [NSIndexPath indexPathForRow:index inSection:0]; + NSDictionary * virtualComponentData = [_dataManager virtualComponentDataWithIndexPath:indexPath]; + if ([virtualComponentData[WXBindingOnceIdentify] boolValue]) { + return; + } + + // TODO: bring the update logic to UpdateManager + newListData[index] = data; + [_dataManager updateData:newListData]; + NSString* virtualComponentId = [_dataManager virtualComponentIdWithIndexPath:indexPath]; + [_dataManager updateVirtualComponentData:virtualComponentId data:data]; + NSMutableDictionary * newData = nil; + if (![data isKindOfClass:[NSDictionary class]]) { + newData = [NSMutableDictionary new]; + [newData setObject:@"data" forKey:data]; + data = newData; + } + newData = [data mutableCopy]; + newData[@"@phase"] = @"update"; + [self _updateDataForCellSlotAtIndexPath:indexPath data:[newData copy]]; +} + +- (void)insertRange:(NSInteger)index range:(NSArray*)data +{ + if (![data count]) { + WXLogDebug(@"ignore invalid insertRange"); + return; } + + NSMutableArray * newListData = [[_dataManager data] mutableCopy]; + NSRange range = NSMakeRange(index,[data count]); + NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:range]; + [newListData insertObjects:data atIndexes:indexSet]; + [_dataManager updateData:newListData]; + [_collectionView reloadData]; } -- (void)removeData:(NSArray *)indexes +- (void)removeData:(NSInteger)index count:(NSInteger)count { // TODO: bring the update logic to UpdateManager + NSMutableArray *newListData = [[_dataManager data] mutableCopy]; - NSMutableIndexSet *indexSet = [NSMutableIndexSet new]; - NSMutableArray *indexPaths = [NSMutableArray array]; - for (NSNumber *index in indexes) { - if ([index unsignedIntegerValue] >= newListData.count) { - WXLogError(@"invalid remove index:%@", index); - continue; - } - [indexSet addIndex:[index unsignedIntegerValue]]; - [indexPaths addObject:[NSIndexPath indexPathForItem:[index unsignedIntegerValue] inSection:0]]; + if (index > [newListData count] || index + count - 1 > [newListData count]) { + + return; } - + NSIndexSet *indexSet = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(index, count)]; [newListData removeObjectsAtIndexes:indexSet]; + __block NSMutableArray<NSIndexPath*>* indexPaths = [NSMutableArray new]; + [indexSet enumerateIndexesUsingBlock:^(NSUInteger idx, BOOL * _Nonnull stop) { + NSIndexPath* indexPath = [NSIndexPath indexPathForRow:idx inSection:0]; + [indexPaths addObject:indexPath]; + }]; + [_dataManager updateData:newListData]; + [_dataManager deleteVirtualComponentAtIndexPaths:indexPaths]; [UIView performWithoutAnimation:^{ - [_collectionView deleteItemsAtIndexPaths:indexPaths]; + [self->_collectionView deleteItemsAtIndexPaths:indexPaths]; + [self->_collectionView reloadSections:[NSIndexSet indexSetWithIndex:0]]; }]; } @@ -258,7 +347,7 @@ WX_EXPORT_METHOD(@selector(scrollTo:options:)) NSIndexPath *fromIndexPath = [NSIndexPath indexPathForItem:fromIndex inSection:0]; NSIndexPath *toIndexPath = [NSIndexPath indexPathForItem:toIndex inSection:0]; [UIView performWithoutAnimation:^{ - [_collectionView moveItemAtIndexPath:fromIndexPath toIndexPath:toIndexPath]; + [self->_collectionView moveItemAtIndexPath:fromIndexPath toIndexPath:toIndexPath]; }]; } @@ -287,11 +376,30 @@ WX_EXPORT_METHOD(@selector(scrollTo:options:)) #pragma mark - Private -- (void)_updateBindingData:(NSDictionary *)data forCell:(WXCellSlotComponent *)cellComponent atIndexPath:(NSIndexPath *)indexPath +- (void)_updateBindingData:(id)data forCell:(WXCellSlotComponent *)cellComponent atIndexPath:(NSIndexPath *)indexPath { - if (_aliasKey) { - data = @{_aliasKey:data}; + id originalData = data; + if (![originalData isKindOfClass:[NSDictionary class]]) { + if (_aliasKey) { + NSMutableDictionary * dictionary = [NSMutableDictionary dictionary]; + [dictionary setObject:data forKey:_aliasKey]; + data = dictionary; + } else { + return; + } + } + + if (!data[@"indexPath"] || !data[@"recycleListComponentRef"]) { + NSMutableDictionary * dataNew = [data mutableCopy]; + dataNew[@"recycleListComponentRef"] = self.ref; + dataNew[@"indexPath"] = indexPath; + data = dataNew; } + + if ([originalData isKindOfClass:[NSDictionary class]] && _aliasKey &&!data[@"phase"]) { + data = @{_aliasKey:data,@"aliasKey":_aliasKey}; + } + if (_indexKey) { NSMutableDictionary *dataNew = [data mutableCopy]; dataNew[_indexKey] = @(indexPath.item); @@ -301,8 +409,9 @@ WX_EXPORT_METHOD(@selector(scrollTo:options:)) #ifdef DEBUG NSDate *startTime = [NSDate date]; #endif + WXPerformBlockSyncOnComponentThread(^{ - [cellComponent updateCellData:data]; + [cellComponent updateCellData:[data copy]]; }); #ifdef DEBUG double duration = -[startTime timeIntervalSinceNow] * 1000; @@ -350,16 +459,13 @@ WX_EXPORT_METHOD(@selector(scrollTo:options:)) - (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { // 1. get the data relating to the cell - NSDictionary *data = [_dataManager dataAtIndex:indexPath.row]; - if (!data || ![data isKindOfClass:[NSDictionary class]]) { - WXLogError(@"No data or wrong data format for index:%zd, data:%@", indexPath.item, data); - return nil; - } + id data = [_dataManager dataAtIndex:indexPath.row]; // 2. get the template type specified by data - NSString *templateType = data[_templateKey]; + NSString * templateType = [self templateType:indexPath]; + _templateManager.collectionView = collectionView; if (!templateType) { - WXLogError(@"Each data should have a value for %@ to indicate template type", _templateKey); + WXLogError(@"Each data should have a value for %@ to indicate template type", _templateSwitchKey); return nil; } @@ -392,9 +498,7 @@ WX_EXPORT_METHOD(@selector(scrollTo:options:)) WXLogDebug(@"Return cell view:%@, indexPath:%@", cellView, indexPath); - dispatch_async(dispatch_get_main_queue(), ^{ - [self handleAppear]; - }); + [self handleAppear]; return cellView; } @@ -424,8 +528,8 @@ WX_EXPORT_METHOD(@selector(scrollTo:options:)) if (size) { return [size CGSizeValue]; } else { - NSDictionary *data = [_dataManager dataAtIndex:indexPath.row]; - WXCellSlotComponent *cell = [_templateManager templateWithType:data[_templateKey]]; + + WXCellSlotComponent *cell = [_templateManager templateWithType:[self templateType:indexPath]]; CGSize size = cell.calculatedFrame.size; _sizeCache[indexPath] = [NSValue valueWithCGSize:size]; return CGSizeMake(_collectionView.frame.size.width, size.height); @@ -456,4 +560,22 @@ WX_EXPORT_METHOD(@selector(scrollTo:options:)) } +- (NSString*)templateType:(NSIndexPath*)indexPath +{ + NSDictionary *data = [_dataManager dataAtIndex:indexPath.row]; + // default is first template. + NSString *templateType = [_templateManager topTemplate].templateCaseType; + if (!data || ![data isKindOfClass:[NSDictionary class]]) { + return templateType; + } + + if (_templateSwitchKey &&data[_templateSwitchKey]){ + templateType = data[_templateSwitchKey]; + } else if (data[WXDefaultRecycleTemplateType]){ + // read the default type. + templateType = data[WXDefaultRecycleTemplateType]; + } + return templateType; +} + @end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h index fc053c5..0a5641e 100644 --- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h +++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.h @@ -31,4 +31,15 @@ - (NSInteger)numberOfItems; +- (NSInteger)numberOfVirtualComponent; + +- (NSDictionary*)virtualComponentDataWithId:(NSString*)componentId; + +- (void)updateVirtualComponentData:(NSString*)componentId data:(NSDictionary*)data; + +- (NSDictionary*)virtualComponentDataWithIndexPath:(NSIndexPath*)indexPath; + +- (NSString*)virtualComponentIdWithIndexPath:(NSIndexPath*)indexPath; + +- (void)deleteVirtualComponentAtIndexPaths:(NSArray<NSIndexPath*>*)indexPaths; @end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m index 8d27171..5f6f1fc 100644 --- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m +++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListDataManager.m @@ -25,6 +25,17 @@ @implementation WXRecycleListDataManager { NSArray *_data; + NSMapTable<NSString*, NSDictionary*>* _virtualComponentData; + NSMapTable<NSIndexPath*, NSString*>* _renderStatus; +} + +- (instancetype)init +{ + if (self = [super init]) { + _virtualComponentData = [NSMapTable strongToStrongObjectsMapTable]; + _renderStatus = [NSMapTable strongToStrongObjectsMapTable]; + } + return self; } - (instancetype)initWithData:(NSArray *)data @@ -68,4 +79,49 @@ return [_data count]; } +- (void)updateVirtualComponentData:(NSString*)componentId data:(NSDictionary*)data +{ + if (!componentId) { + return; + } + NSIndexPath * indexPath = [data objectForKey:@"indexPath"]; + [_virtualComponentData setObject:data forKey:componentId]; + [_renderStatus setObject:componentId forKey:indexPath]; + +// NSMutableDictionary* newComponentData = [[_virtualComponentData objectForKey:componentId] mutableCopy]; +// if (newComponentData) { +// [newComponentData addEntriesFromDictionary:data]; +// } else { +// newComponentData = [data mutableCopy]; +// } +} + +- (void)deleteVirtualComponentAtIndexPaths:(NSArray<NSIndexPath*>*)indexPaths +{ + [_virtualComponentData removeAllObjects]; + [_renderStatus removeAllObjects]; +} + +- (NSDictionary*)virtualComponentDataWithId:(NSString*)componentId +{ + return [_virtualComponentData objectForKey:componentId]; +} + +- (NSString*)virtualComponentIdWithIndexPath:(NSIndexPath*)indexPath +{ + return [_renderStatus objectForKey:indexPath]; +} + +- (NSDictionary*)virtualComponentDataWithIndexPath:(NSIndexPath*)indexPath +{ + NSString * componentDataId = [self virtualComponentIdWithIndexPath:indexPath]; + + return [self virtualComponentDataWithId:componentDataId]; +} + +- (NSInteger)numberOfVirtualComponent +{ + return [_virtualComponentData count]; +} + @end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h index 389dbb8..926c2f1 100644 --- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h +++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.h @@ -30,4 +30,6 @@ - (WXCellSlotComponent *)templateWithType:(NSString *)type; +- (WXCellSlotComponent *)topTemplate; + @end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m index 87ecd90..199d551 100644 --- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m +++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListTemplateManager.m @@ -62,7 +62,7 @@ { WXAssertMainThread(); - NSString *templateType = component.templateType; + NSString *templateType = component.templateCaseType; WXAssert(templateType != nil, @"cell-slot:%@ must have a template id!", component); [_templateTypeMap setObject:component forKey:templateType]; @@ -91,4 +91,16 @@ [_collectionView registerClass:[WXReusableCollectionViewCell class] forCellWithReuseIdentifier:templateID]; } +- (WXCellSlotComponent *)topTemplate +{ + WXCellSlotComponent * cellTemplate = nil; + for (NSString *templateType in [_templateTypeMap.keyEnumerator.allObjects copy]) { + cellTemplate = [self templateWithType:templateType]; + if (!cellTemplate) { + break; + } + } + return cellTemplate; +} + @end http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m index cdeae05..d500895 100644 --- a/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m +++ b/ios/sdk/WeexSDK/Sources/Component/RecycleList/WXRecycleListUpdateManager.m @@ -208,11 +208,6 @@ NSMutableSet<NSIndexPath *> *deleteIndexPaths = [NSMutableSet set]; NSMutableSet<NSIndexPath *> *insertIndexPaths = [NSMutableSet set]; - for (WXDiffUpdateIndex *update in diffResult.updates) { - NSIndexPath *reloadIndexPath = [NSIndexPath indexPathForItem:update.oldIndex inSection:0]; - [reloadIndexPaths addObject:reloadIndexPath]; - } - [diffResult.updates enumerateObjectsUsingBlock:^(WXDiffUpdateIndex * _Nonnull update, NSUInteger idx, BOOL * _Nonnull stop) { NSIndexPath *reloadIndexPath = [NSIndexPath indexPathForItem:update.oldIndex inSection:0]; [reloadIndexPaths addObject:reloadIndexPath]; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerComponent.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerComponent.m b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerComponent.m index be4d7a6..aa4bf1a 100644 --- a/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerComponent.m +++ b/ios/sdk/WeexSDK/Sources/Component/Recycler/WXRecyclerComponent.m @@ -124,7 +124,6 @@ typedef enum : NSUInteger { if (self = [super initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:weexInstance]) { [self _fillPadding]; - if ([type isEqualToString:@"waterfall"] || (attributes[@"layout"] && [attributes[@"layout"] isEqualToString:@"multi-column"])) { // TODO: abstraction _layoutType = WXRecyclerLayoutTypeMultiColumn; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h index eddbfe7..c8c7b5b 100644 --- a/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h +++ b/ios/sdk/WeexSDK/Sources/Component/WXComponent_internal.h @@ -146,8 +146,10 @@ typedef id (^WXDataBindingBlock)(NSDictionary *data, BOOL *needUpdate); WXDataBindingBlock _bindingRepeat; NSString *_repeatIndexIdentify; NSString *_repeatLabelIdentify; + NSString *_virtualComponentId;// for recycleList subcomponent BOOL _isRepeating; BOOL _isSkipUpdate; + BOOL _dataBindOnce; NSMutableDictionary<NSString *, WXDataBindingBlock> *_bindingProps; NSMutableDictionary<NSString *, WXDataBindingBlock> *_bindingAttributes; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m index 5747fe4..621df21 100644 --- a/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m +++ b/ios/sdk/WeexSDK/Sources/Events/WXComponent+Events.m @@ -26,6 +26,10 @@ #import "WXUtility.h" #import "WXSDKManager.h" #import "WXSDKInstance_private.h" +#import "WXDefine.h" +#import "WXRecycleListComponent.h" +#import "WXRecycleListDataManager.h" + #import <objc/runtime.h> #import <UIKit/UIGestureRecognizerSubclass.h> #import "WXComponent+PseudoClassManagement.h" @@ -108,6 +112,15 @@ if (params) { [dict addEntriesFromDictionary:params]; } + WXRecycleListComponent * recyleListComponent = (WXRecycleListComponent*)[self getRecycleListComponent]; + if (recyleListComponent) { + NSIndexPath * indexPath = [((UICollectionView*)recyleListComponent.view) indexPathForItemAtPoint:[self.view.superview + convertPoint:self.view.center toView:recyleListComponent.view]]; + NSString * virtualComponentId = [recyleListComponent.dataManager virtualComponentIdWithIndexPath:indexPath]; + if (virtualComponentId) { + dict[@"componentId"] = virtualComponentId; + } + } NSArray *handlerArguments = [self _paramsForEvent:eventName]; NSString *ref = _templateComponent ? _templateComponent.ref : self.ref; @@ -714,6 +727,18 @@ if ([removeEventName isEqualToString:@#eventName]) {\ return resultTouch; } +// find virtual component's root component +- (WXComponent*)getRecycleListComponent +{ + if ([self isKindOfClass:[WXRecycleListComponent class]]) { + return self; + } + if ([self.ref isEqualToString:WX_SDK_ROOT_REF]) { + return nil; + } + return [self.supercomponent getRecycleListComponent]; +} + @end @implementation WXTouchGestureRecognizer http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h index 77fec46..9d7cece 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h +++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.h @@ -18,6 +18,7 @@ */ #import <Foundation/Foundation.h> +#import <JavaScriptCore/JavaScriptCore.h> @class WXBridgeMethod; @class WXSDKInstance; @@ -142,6 +143,14 @@ extern void WXPerformBlockOnBridgeThread(void (^block)(void)); - (void)fireEvent:(NSString *)instanceId ref:(NSString *)ref type:(NSString *)type params:(NSDictionary *)params domChanges:(NSDictionary *)domChanges handlerArguments:(NSArray *)handlerArguments; /** + * componentHook + * @param instanceId : instance id + * @param componentId : compoent id + * @param type : component hook Type, such as life-cycle + * @param hookPhase : hook phase + */ +- (void)callComponentHook:(NSString*)instanceId componentId:(NSString*)componentId type:(NSString*)type hook:(NSString*)hookPhase args:(NSArray*)args competion:(void (^)(JSValue * value))complection; +/** * callBack * * @param instanceId instanceId http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m index 896bed7..c77bdde 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXBridgeManager.m @@ -326,6 +326,20 @@ void WXPerformBlockOnBridgeThread(void (^block)(void)) [self callJsMethod:method]; } +- (void)callComponentHook:(NSString*)instanceId componentId:(NSString*)componentId type:(NSString*)type hook:(NSString*)hookPhase args:(NSArray*)args competion:(void (^)(JSValue * value))complection +{ + WXPerformBlockOnBridgeThread(^{ + if (!type || !instanceId || !hookPhase) { + WXLogError(@"type and instance id and hookPhase should not be nil"); + return; + } + NSArray *newArgs = @[componentId, type, hookPhase, args?:@[]]; + + WXCallJSMethod * method = [[WXCallJSMethod alloc] initWithModuleName:nil methodName:@"componentHook" arguments:newArgs instance:[WXSDKManager instanceForID:instanceId]]; + [self.bridgeCtx callJSMethod:@"callJS" args:@[instanceId, @[method.callJSTask]] onContext:nil completion:complection]; + }); +} + - (void)callBack:(NSString *)instanceId funcId:(NSString *)funcId params:(id)params keepAlive:(BOOL)keepAlive { NSArray *args = nil; http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m index 446e01c..1413402 100644 --- a/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m +++ b/ios/sdk/WeexSDK/Sources/Manager/WXComponentManager.m @@ -429,7 +429,6 @@ static css_node_t * rootNodeGetChild(void *context, int i) Class clazz = NSClassFromString(config.clazz);; WXComponent *component = [[clazz alloc] initWithRef:ref type:type styles:styles attributes:attributes events:events weexInstance:self.weexInstance]; - if (isTemplate) { component->_isTemplate = YES; [component _storeBindingsWithProps:bindingProps styles:bindingStyles attributes:bindingAttibutes events:bindingEvents]; @@ -460,7 +459,8 @@ static css_node_t * rootNodeGetChild(void *context, int i) [attributesOrStyles enumerateKeysAndObjectsUsingBlock:^(id _Nonnull attributeOrStyleName, id _Nonnull attributeOrStyle, BOOL * _Nonnull stop) { if ([WXBindingMatchIdentify isEqualToString:attributeOrStyleName] // match || [WXBindingRepeatIdentify isEqualToString:attributeOrStyleName] // repeat - || ([attributeOrStyle isKindOfClass:[NSDictionary class]] && attributeOrStyle[WXBindingIdentify])) { // {"attributeOrStyleName": {"@binding":"bindingExpression"} + || [WXBindingOnceIdentify isEqualToString:attributeOrStyleName] // once + ||([attributeOrStyle isKindOfClass:[NSDictionary class]] && attributeOrStyle[WXBindingIdentify])) { // {"attributeOrStyleName": {"@binding":"bindingExpression"} bindingAttributesOrStyles[attributeOrStyleName] = attributeOrStyle; [newAttributesOrStyles removeObjectForKey:attributeOrStyleName]; } else if ([attributeOrStyle isKindOfClass:[NSArray class]]) { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Model/WXComponent.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m index aaf04d1..3f4f1ce 100644 --- a/ios/sdk/WeexSDK/Sources/Model/WXComponent.m +++ b/ios/sdk/WeexSDK/Sources/Model/WXComponent.m @@ -199,6 +199,9 @@ // [self _removeAllEvents]; // remove all gesture and all + if (_isTemplate && self.attributes[@"@templateId"]) { + [[WXSDKManager bridgeMgr] callComponentHook:_weexInstance.instanceId componentId:self.attributes[@"@templateId"] type:@"lifecycle" hook:@"destroy" args:nil competion:nil]; + } if (_tapGesture) { [_tapGesture removeTarget:nil action:NULL]; } http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m b/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m index edb0597..3b22b84 100644 --- a/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m +++ b/ios/sdk/WeexSDK/Sources/Module/WXDomModule.m @@ -28,6 +28,8 @@ #import "WXRuleManager.h" #import "WXSDKInstance.h" #import "WXTracingManager.h" +#import "WXRecycleListComponent.h" +#import <objc/message.h> @interface WXDomModule () @@ -51,6 +53,7 @@ WX_EXPORT_METHOD(@selector(updateStyle:styles:)) WX_EXPORT_METHOD(@selector(updateAttrs:attrs:)) WX_EXPORT_METHOD(@selector(addRule:rule:)) WX_EXPORT_METHOD(@selector(getComponentRect:callback:)) +WX_EXPORT_METHOD(@selector(updateComponentData:componentData:callback:)) - (void)performBlockOnComponentManager:(void(^)(WXComponentManager *))block { @@ -223,6 +226,19 @@ WX_EXPORT_METHOD(@selector(getComponentRect:callback:)) }]; } +- (void)updateComponentData:(NSString*)componentDataId componentData:(NSDictionary*)componentData callback:(NSString*)callbackId +{ + NSString *recycleListComponentRef = [[componentDataId componentsSeparatedByString:@"@"] objectAtIndex:0]; + if (!recycleListComponentRef) { + return; + } + SEL selector = _cmd; + [self performBlockOnComponentManager:^(WXComponentManager * manager) { + WXRecycleListComponent * recycleListComponent = (WXRecycleListComponent*)[manager componentForRef:recycleListComponentRef]; + ((void*(*)(id,SEL,NSString*,NSDictionary*,NSString*))objc_msgSend)(recycleListComponent, selector, componentDataId, componentData,callbackId); + }]; +} + - (void)destroyInstance { [self performBlockOnComponentManager:^(WXComponentManager *manager) { http://git-wip-us.apache.org/repos/asf/incubator-weex/blob/e31458ac/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m ---------------------------------------------------------------------- diff --git a/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m b/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m index be27ae7..e066a14 100644 --- a/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m +++ b/ios/sdk/WeexSDK/Sources/View/WXComponent+ViewManagement.m @@ -25,6 +25,7 @@ #import "WXSDKInstance_private.h" #import "WXTransform.h" #import "WXTracingManager.h" +#import "WXSDKManager.h" #define WX_BOARD_RADIUS_RESET_ALL(key)\ do {\ @@ -329,6 +330,9 @@ do {\ } [_view removeFromSuperview]; + if (self->_isTemplate && self.attributes[@"@templateId"]) { + [[WXSDKManager bridgeMgr] callComponentHook:self.weexInstance.instanceId componentId:self.attributes[@"@templateId"] type:@"lifecycle" hook:@"detach" args:nil competion:nil]; + } _view = nil; [_layer removeFromSuperlayer]; _layer = nil;