Feature/fix npe exception (#566)

* android: add exception catch for list flowlayout scroller  type

* iOS: add exception catch for list flowlayout scroller  type
This commit is contained in:
osborn 2023-01-03 16:42:52 +08:00 committed by GitHub
parent 37d2df9eea
commit 4eeebf6118
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
8 changed files with 220 additions and 186 deletions

View File

@ -20,16 +20,15 @@ import android.util.SparseArray;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import com.github.pengfeizhou.jscore.JSArray; import com.github.pengfeizhou.jscore.JSArray;
import com.github.pengfeizhou.jscore.JSDecoder; import com.github.pengfeizhou.jscore.JSDecoder;
import com.github.pengfeizhou.jscore.JSNull; import com.github.pengfeizhou.jscore.JSNull;
import com.github.pengfeizhou.jscore.JSObject; import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue; import com.github.pengfeizhou.jscore.JSValue;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import androidx.recyclerview.widget.StaggeredGridLayoutManager;
import pub.doric.async.AsyncResult; import pub.doric.async.AsyncResult;
import pub.doric.shader.ViewNode; import pub.doric.shader.ViewNode;
@ -62,33 +61,37 @@ class FlowAdapter extends RecyclerView.Adapter<FlowAdapter.DoricViewHolder> {
@Override @Override
public void onBindViewHolder(@NonNull DoricViewHolder holder, int position) { public void onBindViewHolder(@NonNull DoricViewHolder holder, int position) {
JSValue jsValue = getItemModel(position); try {
boolean fullSpan = this.loadMore && position >= this.itemCount; JSValue jsValue = getItemModel(position);
if (jsValue != null && jsValue.isObject()) { boolean fullSpan = this.loadMore && position >= this.itemCount;
JSObject jsObject = jsValue.asObject(); if (jsValue != null && jsValue.isObject()) {
holder.flowLayoutItemNode.setId(jsObject.getProperty("id").asString().value()); JSObject jsObject = jsValue.asObject();
JSObject props = jsObject.getProperty("props").asObject(); holder.flowLayoutItemNode.setId(jsObject.getProperty("id").asString().value());
holder.flowLayoutItemNode.reset(); JSObject props = jsObject.getProperty("props").asObject();
holder.flowLayoutItemNode.blend(props); holder.flowLayoutItemNode.reset();
JSValue fullSpanValue = props.getProperty("fullSpan"); holder.flowLayoutItemNode.blend(props);
if (fullSpanValue.isBoolean()) { JSValue fullSpanValue = props.getProperty("fullSpan");
fullSpan = fullSpanValue.asBoolean().value(); if (fullSpanValue.isBoolean()) {
fullSpan = fullSpanValue.asBoolean().value();
}
} }
} if (holder.itemView.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams) {
if (holder.itemView.getLayoutParams() instanceof StaggeredGridLayoutManager.LayoutParams) { ((StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams()).setFullSpan(fullSpan);
((StaggeredGridLayoutManager.LayoutParams) holder.itemView.getLayoutParams()).setFullSpan(fullSpan); } else if (fullSpan) {
} else if (fullSpan) { StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams(
StaggeredGridLayoutManager.LayoutParams layoutParams = new StaggeredGridLayoutManager.LayoutParams( ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT, holder.itemView.getLayoutParams().height
holder.itemView.getLayoutParams().height );
); layoutParams.setFullSpan(true);
layoutParams.setFullSpan(true); holder.itemView.setLayoutParams(layoutParams);
holder.itemView.setLayoutParams(layoutParams); }
} if (this.loadMore
if (this.loadMore && position >= this.itemCount
&& position >= this.itemCount && !TextUtils.isEmpty(this.flowLayoutNode.onLoadMoreFuncId)) {
&& !TextUtils.isEmpty(this.flowLayoutNode.onLoadMoreFuncId)) { callLoadMore();
callLoadMore(); }
} catch (Exception e) {
flowLayoutNode.getDoricContext().getDriver().getRegistry().onException(flowLayoutNode.getDoricContext(), e);
} }
} }

View File

@ -21,15 +21,14 @@ import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.github.pengfeizhou.jscore.JSArray; import com.github.pengfeizhou.jscore.JSArray;
import com.github.pengfeizhou.jscore.JSDecoder; import com.github.pengfeizhou.jscore.JSDecoder;
import com.github.pengfeizhou.jscore.JSNull; import com.github.pengfeizhou.jscore.JSNull;
import com.github.pengfeizhou.jscore.JSObject; import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue; import com.github.pengfeizhou.jscore.JSValue;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import pub.doric.async.AsyncResult; import pub.doric.async.AsyncResult;
import pub.doric.shader.ViewNode; import pub.doric.shader.ViewNode;
@ -49,6 +48,7 @@ class HorizontalListAdapter extends RecyclerView.Adapter<HorizontalListAdapter.D
int itemCount = 0; int itemCount = 0;
int loadAnchor = -1; int loadAnchor = -1;
boolean loadMore = false; boolean loadMore = false;
@NonNull @NonNull
@Override @Override
public DoricViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public DoricViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@ -59,17 +59,21 @@ class HorizontalListAdapter extends RecyclerView.Adapter<HorizontalListAdapter.D
@Override @Override
public void onBindViewHolder(@NonNull DoricViewHolder holder, int position) { public void onBindViewHolder(@NonNull DoricViewHolder holder, int position) {
JSValue jsValue = getItemModel(position); try {
if (jsValue != null && jsValue.isObject()) { JSValue jsValue = getItemModel(position);
JSObject jsObject = jsValue.asObject(); if (jsValue != null && jsValue.isObject()) {
holder.horizontalListItemNode.setId(jsObject.getProperty("id").asString().value()); JSObject jsObject = jsValue.asObject();
holder.horizontalListItemNode.reset(); holder.horizontalListItemNode.setId(jsObject.getProperty("id").asString().value());
holder.horizontalListItemNode.blend(jsObject.getProperty("props").asObject()); holder.horizontalListItemNode.reset();
} holder.horizontalListItemNode.blend(jsObject.getProperty("props").asObject());
if (this.loadMore }
&& position >= this.itemCount if (this.loadMore
&& !TextUtils.isEmpty(this.horizontalListNode.onLoadMoreFuncId)) { && position >= this.itemCount
callLoadMore(); && !TextUtils.isEmpty(this.horizontalListNode.onLoadMoreFuncId)) {
callLoadMore();
}
} catch (Exception e) {
horizontalListNode.getDoricContext().getDriver().getRegistry().onException(horizontalListNode.getDoricContext(), e);
} }
} }

View File

@ -21,15 +21,14 @@ import android.text.TextUtils;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.github.pengfeizhou.jscore.JSArray; import com.github.pengfeizhou.jscore.JSArray;
import com.github.pengfeizhou.jscore.JSDecoder; import com.github.pengfeizhou.jscore.JSDecoder;
import com.github.pengfeizhou.jscore.JSNull; import com.github.pengfeizhou.jscore.JSNull;
import com.github.pengfeizhou.jscore.JSObject; import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue; import com.github.pengfeizhou.jscore.JSValue;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import pub.doric.async.AsyncResult; import pub.doric.async.AsyncResult;
import pub.doric.shader.ViewNode; import pub.doric.shader.ViewNode;
@ -49,6 +48,7 @@ class ListAdapter extends RecyclerView.Adapter<ListAdapter.DoricViewHolder> {
int itemCount = 0; int itemCount = 0;
int loadAnchor = -1; int loadAnchor = -1;
boolean loadMore = false; boolean loadMore = false;
@NonNull @NonNull
@Override @Override
public DoricViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) { public DoricViewHolder onCreateViewHolder(@NonNull ViewGroup parent, int viewType) {
@ -59,17 +59,21 @@ class ListAdapter extends RecyclerView.Adapter<ListAdapter.DoricViewHolder> {
@Override @Override
public void onBindViewHolder(@NonNull DoricViewHolder holder, int position) { public void onBindViewHolder(@NonNull DoricViewHolder holder, int position) {
JSValue jsValue = getItemModel(position); try {
if (jsValue != null && jsValue.isObject()) { JSValue jsValue = getItemModel(position);
JSObject jsObject = jsValue.asObject(); if (jsValue != null && jsValue.isObject()) {
holder.listItemNode.setId(jsObject.getProperty("id").asString().value()); JSObject jsObject = jsValue.asObject();
holder.listItemNode.reset(); holder.listItemNode.setId(jsObject.getProperty("id").asString().value());
holder.listItemNode.blend(jsObject.getProperty("props").asObject()); holder.listItemNode.reset();
} holder.listItemNode.blend(jsObject.getProperty("props").asObject());
if (this.loadMore }
&& position >= this.itemCount if (this.loadMore
&& !TextUtils.isEmpty(this.listNode.onLoadMoreFuncId)) { && position >= this.itemCount
callLoadMore(); && !TextUtils.isEmpty(this.listNode.onLoadMoreFuncId)) {
callLoadMore();
}
} catch (Exception e) {
listNode.getDoricContext().getDriver().getRegistry().onException(listNode.getDoricContext(), e);
} }
} }

View File

@ -20,15 +20,14 @@ import android.util.SparseArray;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import com.github.pengfeizhou.jscore.JSArray; import com.github.pengfeizhou.jscore.JSArray;
import com.github.pengfeizhou.jscore.JSDecoder; import com.github.pengfeizhou.jscore.JSDecoder;
import com.github.pengfeizhou.jscore.JSNull; import com.github.pengfeizhou.jscore.JSNull;
import com.github.pengfeizhou.jscore.JSObject; import com.github.pengfeizhou.jscore.JSObject;
import com.github.pengfeizhou.jscore.JSValue; import com.github.pengfeizhou.jscore.JSValue;
import androidx.annotation.NonNull;
import androidx.recyclerview.widget.RecyclerView;
import pub.doric.async.AsyncResult; import pub.doric.async.AsyncResult;
import pub.doric.shader.ViewNode; import pub.doric.shader.ViewNode;
@ -61,12 +60,16 @@ class SlideAdapter extends RecyclerView.Adapter<SlideAdapter.DoricViewHolder> {
@Override @Override
public void onBindViewHolder(@NonNull DoricViewHolder holder, int position) { public void onBindViewHolder(@NonNull DoricViewHolder holder, int position) {
JSValue jsValue = getItemModel(position); try {
if (jsValue != null && jsValue.isObject()) { JSValue jsValue = getItemModel(position);
JSObject jsObject = jsValue.asObject(); if (jsValue != null && jsValue.isObject()) {
holder.slideItemNode.setId(jsObject.getProperty("id").asString().value()); JSObject jsObject = jsValue.asObject();
holder.slideItemNode.reset(); holder.slideItemNode.setId(jsObject.getProperty("id").asString().value());
holder.slideItemNode.blend(jsObject.getProperty("props").asObject()); holder.slideItemNode.reset();
holder.slideItemNode.blend(jsObject.getProperty("props").asObject());
}
} catch (Exception e) {
sliderNode.getDoricContext().getDriver().getRegistry().onException(sliderNode.getDoricContext(), e);
} }
} }

View File

@ -399,11 +399,11 @@ - (void)blendSubNode:(NSDictionary *)subModel {
NSString *viewId = subModel[@"id"]; NSString *viewId = subModel[@"id"];
DoricViewNode *viewNode = [self subNodeWithViewId:viewId]; DoricViewNode *viewNode = [self subNodeWithViewId:viewId];
BOOL skipReload = NO; BOOL skipReload = NO;
NSMutableDictionary *model = [[self subModelOf:viewId] mutableCopy]; NSMutableDictionary *model = [[self subModelOf:viewId] mutableCopy];
[self recursiveMixin:subModel to:model]; [self recursiveMixin:subModel to:model];
[self setSubModel:model in:viewId]; [self setSubModel:model in:viewId];
if (viewNode) { if (viewNode) {
CGSize originSize = viewNode.view.frame.size; CGSize originSize = viewNode.view.frame.size;
[viewNode blend:subModel[@"props"]]; [viewNode blend:subModel[@"props"]];
@ -413,7 +413,7 @@ - (void)blendSubNode:(NSDictionary *)subModel {
skipReload = YES; skipReload = YES;
} }
} }
if (skipReload) { if (skipReload) {
return; return;
} }
@ -459,41 +459,46 @@ - (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSe
} }
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger position = (NSUInteger) indexPath.row; @try {
NSDictionary *model = [self itemModelAt:position]; NSUInteger position = (NSUInteger) indexPath.row;
NSDictionary *props = model[@"props"]; NSDictionary *model = [self itemModelAt:position];
NSString *identifier = props[@"identifier"] ?: @"doricCell"; NSDictionary *props = model[@"props"];
if (self.loadMore NSString *identifier = props[@"identifier"] ?: @"doricCell";
&& position >= self.itemCount if (self.loadMore
&& self.onLoadMoreFuncId) { && position >= self.itemCount
identifier = @"doricLoadMoreCell"; && self.onLoadMoreFuncId) {
[self callLoadMore]; identifier = @"doricLoadMoreCell";
} [self callLoadMore];
[collectionView registerClass:[DoricFlowLayoutViewCell class] forCellWithReuseIdentifier:identifier]; }
DoricFlowLayoutViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath]; [collectionView registerClass:[DoricFlowLayoutViewCell class] forCellWithReuseIdentifier:identifier];
if (!cell.viewNode) { DoricFlowLayoutViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
DoricFlowLayoutItemNode *itemNode = (DoricFlowLayoutItemNode *) [DoricViewNode create:self.doricContext withType:@"FlowLayoutItem"]; if (!cell.viewNode) {
[itemNode initWithSuperNode:self]; DoricFlowLayoutItemNode *itemNode = (DoricFlowLayoutItemNode *) [DoricViewNode create:self.doricContext withType:@"FlowLayoutItem"];
cell.viewNode = itemNode; [itemNode initWithSuperNode:self];
[cell.contentView addSubview:itemNode.view]; cell.viewNode = itemNode;
} else { [cell.contentView addSubview:itemNode.view];
[cell.viewNode reset]; } else {
} [cell.viewNode reset];
}
DoricFlowLayoutItemNode *node = cell.viewNode; DoricFlowLayoutItemNode *node = cell.viewNode;
node.viewId = model[@"id"]; node.viewId = model[@"id"];
[node blend:props]; [node blend:props];
BOOL fullSpan = self.loadMore && position >= self.itemCount; BOOL fullSpan = self.loadMore && position >= self.itemCount;
if (props[@"fullSpan"]) { if (props[@"fullSpan"]) {
fullSpan = [props[@"fullSpan"] boolValue]; fullSpan = [props[@"fullSpan"] boolValue];
}
CGFloat width = fullSpan ? collectionView.width : (collectionView.width - (self.columnCount - 1) * self.columnSpace) / self.columnCount;
CGFloat height = node.view.doricLayout.heightSpec == DoricLayoutFit ? CGFLOAT_MAX : collectionView.height;
[node.view.doricLayout apply:CGSizeMake(width, height)];
[node requestLayout];
[self callItem:position size:node.view.frame.size];
return cell;
} @catch (NSException *exception) {
[self.doricContext.driver.registry onException:exception inContext:self.doricContext];
return nil;
} }
CGFloat width = fullSpan ? collectionView.width : (collectionView.width - (self.columnCount - 1) * self.columnSpace) / self.columnCount;
CGFloat height = node.view.doricLayout.heightSpec == DoricLayoutFit ? CGFLOAT_MAX : collectionView.height;
[node.view.doricLayout apply:CGSizeMake(width, height)];
[node requestLayout];
[self callItem:position size:node.view.frame.size];
return cell;
} }
- (NSIndexPath *)collectionView:(UICollectionView *)collectionView targetIndexPathForMoveFromItemAtIndexPath:(NSIndexPath *)currentIndexPath toProposedIndexPath:(NSIndexPath *)proposedIndexPath { - (NSIndexPath *)collectionView:(UICollectionView *)collectionView targetIndexPathForMoveFromItemAtIndexPath:(NSIndexPath *)currentIndexPath toProposedIndexPath:(NSIndexPath *)proposedIndexPath {

View File

@ -240,37 +240,42 @@ - (void)callLoadMore {
} }
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger position = (NSUInteger) indexPath.row; @try {
NSDictionary *model = [self itemModelAt:position]; NSUInteger position = (NSUInteger) indexPath.row;
NSDictionary *props = model[@"props"]; NSDictionary *model = [self itemModelAt:position];
NSString *identifier = props[@"identifier"] ?: @"doricCell"; NSDictionary *props = model[@"props"];
self.itemActions[@(position)] = props[@"actions"]; NSString *identifier = props[@"identifier"] ?: @"doricCell";
if (self.loadMore self.itemActions[@(position)] = props[@"actions"];
&& position >= self.rowCount - 1 if (self.loadMore
&& self.onLoadMoreFuncId) { && position >= self.rowCount - 1
identifier = @"doricLoadMoreCell"; && self.onLoadMoreFuncId) {
[self callLoadMore]; identifier = @"doricLoadMoreCell";
[self callLoadMore];
}
[collectionView registerClass:[DoricHorizontalTableViewCell class] forCellWithReuseIdentifier:identifier];
DoricHorizontalTableViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
if (!cell.doricHorizontalListItemNode) {
DoricHorizontalListItemNode *itemNode = (DoricHorizontalListItemNode *) [DoricViewNode create:self.doricContext withType:@"HorizontalListItem"];
[itemNode initWithSuperNode:self];
cell.doricHorizontalListItemNode = itemNode;
cell.backgroundColor = [UIColor clearColor];
itemNode.view.height = collectionView.height;
[cell.contentView addSubview:itemNode.view];
} else {
[cell.doricHorizontalListItemNode reset];
}
DoricHorizontalListItemNode *node = cell.doricHorizontalListItemNode;
node.viewId = model[@"id"];
[node blend:props];
CGFloat width = node.view.doricLayout.widthSpec == DoricLayoutFit ? CGFLOAT_MAX : collectionView.width;
[node.view.doricLayout apply:CGSizeMake(width, collectionView.height)];
[node requestLayout];
[self callItem:position width:node.view.width];
return cell;
} @catch (NSException *exception) {
[self.doricContext.driver.registry onException:exception inContext:self.doricContext];
return nil;
} }
[collectionView registerClass:[DoricHorizontalTableViewCell class] forCellWithReuseIdentifier:identifier];
DoricHorizontalTableViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:identifier forIndexPath:indexPath];
if (!cell.doricHorizontalListItemNode) {
DoricHorizontalListItemNode *itemNode = (DoricHorizontalListItemNode *) [DoricViewNode create:self.doricContext withType:@"HorizontalListItem"];
[itemNode initWithSuperNode:self];
cell.doricHorizontalListItemNode = itemNode;
cell.backgroundColor = [UIColor clearColor];
itemNode.view.height = collectionView.height;
[cell.contentView addSubview:itemNode.view];
} else {
[cell.doricHorizontalListItemNode reset];
}
DoricHorizontalListItemNode *node = cell.doricHorizontalListItemNode;
node.viewId = model[@"id"];
[node blend:props];
CGFloat width = node.view.doricLayout.widthSpec == DoricLayoutFit ? CGFLOAT_MAX : collectionView.width;
[node.view.doricLayout apply:CGSizeMake(width, collectionView.height)];
[node requestLayout];
[self callItem:position width:node.view.width];
return cell;
} }
- (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section { - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectionViewLayout *)collectionViewLayout minimumInteritemSpacingForSectionAtIndex:(NSInteger)section {
@ -337,11 +342,11 @@ - (void)blendSubNode:(NSDictionary *)subModel {
NSString *viewId = subModel[@"id"]; NSString *viewId = subModel[@"id"];
DoricViewNode *viewNode = [self subNodeWithViewId:viewId]; DoricViewNode *viewNode = [self subNodeWithViewId:viewId];
BOOL skipReload = NO; BOOL skipReload = NO;
NSMutableDictionary *model = [[self subModelOf:viewId] mutableCopy]; NSMutableDictionary *model = [[self subModelOf:viewId] mutableCopy];
[self recursiveMixin:subModel to:model]; [self recursiveMixin:subModel to:model];
[self setSubModel:model in:viewId]; [self setSubModel:model in:viewId];
if (viewNode) { if (viewNode) {
CGSize originSize = viewNode.view.frame.size; CGSize originSize = viewNode.view.frame.size;
[viewNode blend:subModel[@"props"]]; [viewNode blend:subModel[@"props"]];
@ -351,7 +356,7 @@ - (void)blendSubNode:(NSDictionary *)subModel {
skipReload = YES; skipReload = YES;
} }
} }
if (skipReload) { if (skipReload) {
return; return;
} }

View File

@ -242,37 +242,42 @@ - (void)callLoadMore {
} }
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger position = (NSUInteger) indexPath.row; @try {
NSDictionary *model = [self itemModelAt:position]; NSUInteger position = (NSUInteger) indexPath.row;
NSDictionary *props = model[@"props"]; NSDictionary *model = [self itemModelAt:position];
NSString *reuseId = props[@"identifier"]; NSDictionary *props = model[@"props"];
self.itemActions[@(position)] = props[@"actions"]; NSString *reuseId = props[@"identifier"];
if (self.loadMore self.itemActions[@(position)] = props[@"actions"];
&& position >= self.rowCount - 1 if (self.loadMore
&& self.onLoadMoreFuncId) { && position >= self.rowCount - 1
reuseId = @"doricLoadMoreCell"; && self.onLoadMoreFuncId) {
[self callLoadMore]; reuseId = @"doricLoadMoreCell";
[self callLoadMore];
}
DoricTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId ?: @"doricCell"];
if (!cell) {
cell = [[DoricTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseId ?: @"doricCell"];
DoricListItemNode *listItemNode = (DoricListItemNode *) [DoricViewNode create:self.doricContext withType:@"ListItem"];
[listItemNode initWithSuperNode:self];
cell.doricListItemNode = listItemNode;
cell.backgroundColor = [UIColor clearColor];
listItemNode.view.width = tableView.width;
[cell.contentView addSubview:listItemNode.view];
} else {
[cell.doricListItemNode reset];
}
DoricListItemNode *node = cell.doricListItemNode;
node.viewId = model[@"id"];
[node blend:props];
CGFloat height = node.view.doricLayout.heightSpec == DoricLayoutFit ? CGFLOAT_MAX : tableView.height;
[node.view.doricLayout apply:CGSizeMake(tableView.width, height)];
[node requestLayout];
[self callItem:position height:node.view.height];
return cell;
} @catch (NSException *exception) {
[self.doricContext.driver.registry onException:exception inContext:self.doricContext];
return nil;
} }
DoricTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuseId ?: @"doricCell"];
if (!cell) {
cell = [[DoricTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:reuseId ?: @"doricCell"];
DoricListItemNode *listItemNode = (DoricListItemNode *) [DoricViewNode create:self.doricContext withType:@"ListItem"];
[listItemNode initWithSuperNode:self];
cell.doricListItemNode = listItemNode;
cell.backgroundColor = [UIColor clearColor];
listItemNode.view.width = tableView.width;
[cell.contentView addSubview:listItemNode.view];
} else {
[cell.doricListItemNode reset];
}
DoricListItemNode *node = cell.doricListItemNode;
node.viewId = model[@"id"];
[node blend:props];
CGFloat height = node.view.doricLayout.heightSpec == DoricLayoutFit ? CGFLOAT_MAX : tableView.height;
[node.view.doricLayout apply:CGSizeMake(tableView.width, height)];
[node requestLayout];
[self callItem:position height:node.view.height];
return cell;
} }
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath { - (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
@ -381,11 +386,11 @@ - (void)blendSubNode:(NSDictionary *)subModel {
NSString *viewId = subModel[@"id"]; NSString *viewId = subModel[@"id"];
DoricViewNode *viewNode = [self subNodeWithViewId:viewId]; DoricViewNode *viewNode = [self subNodeWithViewId:viewId];
BOOL skipReload = NO; BOOL skipReload = NO;
NSMutableDictionary *model = [[self subModelOf:viewId] mutableCopy]; NSMutableDictionary *model = [[self subModelOf:viewId] mutableCopy];
[self recursiveMixin:subModel to:model]; [self recursiveMixin:subModel to:model];
[self setSubModel:model in:viewId]; [self setSubModel:model in:viewId];
if (viewNode) { if (viewNode) {
CGSize originSize = viewNode.view.frame.size; CGSize originSize = viewNode.view.frame.size;
[viewNode blend:subModel[@"props"]]; [viewNode blend:subModel[@"props"]];

View File

@ -177,24 +177,29 @@ - (CGFloat)collectionView:(UICollectionView *)collectionView layout:(UICollectio
} }
- (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath { - (__kindof UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath {
NSUInteger position = (NSUInteger) indexPath.row; @try {
NSDictionary *model = [self itemModelAt:position]; NSUInteger position = (NSUInteger) indexPath.row;
NSDictionary *props = model[@"props"]; NSDictionary *model = [self itemModelAt:position];
DoricSliderViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"doricCell" forIndexPath:indexPath]; NSDictionary *props = model[@"props"];
if (!cell.doricSlideItemNode) { DoricSliderViewCell *cell = [collectionView dequeueReusableCellWithReuseIdentifier:@"doricCell" forIndexPath:indexPath];
DoricSlideItemNode *slideItemNode = (DoricSlideItemNode *) [DoricViewNode create:self.doricContext withType:@"SlideItem"]; if (!cell.doricSlideItemNode) {
[slideItemNode initWithSuperNode:self]; DoricSlideItemNode *slideItemNode = (DoricSlideItemNode *) [DoricViewNode create:self.doricContext withType:@"SlideItem"];
cell.doricSlideItemNode = slideItemNode; [slideItemNode initWithSuperNode:self];
[cell.contentView addSubview:slideItemNode.view]; cell.doricSlideItemNode = slideItemNode;
} else { [cell.contentView addSubview:slideItemNode.view];
[cell.doricSlideItemNode reset]; } else {
[cell.doricSlideItemNode reset];
}
DoricSlideItemNode *node = cell.doricSlideItemNode;
node.viewId = model[@"id"];
[node blend:props];
[node.view.doricLayout apply:CGSizeMake(collectionView.width, collectionView.height)];
[node requestLayout];
return cell;
} @catch (NSException *exception) {
[self.doricContext.driver.registry onException:exception inContext:self.doricContext];
return nil;
} }
DoricSlideItemNode *node = cell.doricSlideItemNode;
node.viewId = model[@"id"];
[node blend:props];
[node.view.doricLayout apply:CGSizeMake(collectionView.width, collectionView.height)];
[node requestLayout];
return cell;
} }
- (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath { - (BOOL)collectionView:(UICollectionView *)collectionView shouldSelectItemAtIndexPath:(NSIndexPath *)indexPath {
@ -253,11 +258,11 @@ - (void)blendSubNode:(NSDictionary *)subModel {
NSString *viewId = subModel[@"id"]; NSString *viewId = subModel[@"id"];
DoricViewNode *viewNode = [self subNodeWithViewId:viewId]; DoricViewNode *viewNode = [self subNodeWithViewId:viewId];
BOOL skipReload = NO; BOOL skipReload = NO;
NSMutableDictionary *model = [[self subModelOf:viewId] mutableCopy]; NSMutableDictionary *model = [[self subModelOf:viewId] mutableCopy];
[self recursiveMixin:subModel to:model]; [self recursiveMixin:subModel to:model];
[self setSubModel:model in:viewId]; [self setSubModel:model in:viewId];
if (viewNode) { if (viewNode) {
CGSize originSize = viewNode.view.frame.size; CGSize originSize = viewNode.view.frame.size;
[viewNode blend:subModel[@"props"]]; [viewNode blend:subModel[@"props"]];