得物H5容器野指针疑难问题排查 & 解决
得物 iOS 4.9.x 版本 上线后,一些带有横向滚动内容的h5页面,有一个webkit 相关crash增加较快。通过Crash堆栈判断是UIScrollview执行滚动动画过程中内存野指针导致的崩溃。
2、前期排查通过页面浏览日志,发现发生崩溃时所在的页面都是在h5 web容器内,且都是在页面的生命周期方法viewDidDisappear方法调用后才发生崩溃,因此推测崩溃是在h5 页面返回时发生的。
【资料图】
刚好交易的同事复现了崩溃证实了我们的推测。因此可以基本确定:崩溃的原因是页面退出后,页面内存被释放,但是滚动动画继续执行,这时崩溃堆栈中scrollview的delegate没有置空,系统继续执行delegate的相关方法,访问了已经释放的对象的内存(野指针问题)。
同时发生crash h5 页面都存在一个特点,就是页面内存在可以左右横滑的tab视图。
操作手势侧滑存在体验问题,左右横滑的tab视图也会跟着滚动(见下面视频)。关联bugly用户行为日志,判断这个体验问题是和本文中的crash有相关性的。
3、不完美的解决方案经过上面的分析,修复思路是在h5页面手势侧滑返回时,将h5容器页面内tab的横滑手势禁掉(同时需要在 h5 web容器的viewWillAppear方法里将手势再打开,因为手势侧滑是可以取消在返回页面)。
具体代码如下(这样在操作页面侧滑返回时,页面的手势被禁掉,不会再滚动):
@objc dynamic func webViewCanScroll(enable:Bool) { let contentView = self.webView.scrollView.subviews.first { view in if let className = object_getClass(view), NSStringFromClass(className) == "WKContentView" { return true } return false } let webTouchEventsGestureRecognizer = contentView?.gestureRecognizers?.first(where: { gesture in if let className = object_getClass(gesture), NSStringFromClass(className) == "UIWebTouchEventsGestureRecognizer" { return true } return false }) webTouchEventsGestureRecognizer?.isEnabled = enable }@objc dynamic func webViewCanScroll(enable:Bool) { let contentView = self.webView.scrollView.subviews.first { view in if let className = object_getClass(view), NSStringFromClass(className) == "WKContentView" { return true } return false } let webTouchEventsGestureRecognizer = contentView?.gestureRecognizers?.first(where: { gesture in if let className = object_getClass(gesture), NSStringFromClass(className) == "UIWebTouchEventsGestureRecognizer" { return true } return false }) webTouchEventsGestureRecognizer?.isEnabled = enable }
经过测试,h5 web容器侧滑时出现的tab页面左右滚动的体验问题确实被解决。这样既可以解决体验问题,又可以解决侧滑离开页面导致的崩溃问题,但是这样并没有定位crash的根因。修复代码上线后,crash量确实下降,但是每天还是有一些crash出现,且收到了个别页面极端操作下偶现卡住的问题反馈。因此需要继续排查crash根因,将crash根本解决掉。
继续看文章开始的crash堆栈,通过Crash堆栈判断崩溃原因是UIScrollview执行滚动动画过程中回调代理方法(见上图)时访问被释放的内存。常规解决思路是在退出页面后,在页面生命周期的dealloc方法中,将UIScrollview的delegate置空即可。WKWebView确实有一个scrollVIew属性,我们在很早的版本就将其delegate属性置空,但是崩溃没有解决。
deinit { scrollView.delegate = nil scrollView.dataSource = nil }deinit { scrollView.delegate = nil scrollView.dataSource = nil }
因此崩溃堆栈里的Scrollview代理不是这里的WKWebView的scrollVIew的代理。那崩溃堆栈中的scrollView代理到底属于哪个UIScrollview呢?幸运的是苹果webkit 是开源的,我们可以将webkit源码下载下来看一下。
4、寻找崩溃堆栈中的ScrollViewDelegate崩溃堆栈中的ScrollViewDelegate是WKScrollingNodeScrollViewDelegate。首先看看WKWebView的scrollview的 delegate是如何实现的,因为我们猜想这个scrollview的delegate除了我们自己设置的,是否还有其他delegate(比如崩溃堆栈中的WKScrollingNodeScrollViewDelegate)。
通过对Webkit源码一番研究,发现scrollview的初始化方法:
- (void)_setupScrollAndContentViews{ CGRect bounds = self.bounds; _scrollView = adoptNS([[WKScrollView alloc] initWithFrame:bounds]); [_scrollView setInternalDelegate:self]; [_scrollView setBouncesZoom:YES];}- (void)_setupScrollAndContentViews{ CGRect bounds = self.bounds; _scrollView = adoptNS([[WKScrollView alloc] initWithFrame:bounds]); [_scrollView setInternalDelegate:self]; [_scrollView setBouncesZoom:YES];}
WKWebView的scrollVIew 是WKScrollView 类型。
4.1 WKScrollView 代理实现首先看到WKWebView的scrollview的类型其实是WKScrollView(UIScrollview的子类),他除了继承自父类的delegate属性,还有一个internalDelegate属性,那么这个internalDelegate属性是不是我们要找的WKScrollingNodeScrollViewDelegate 呢?
@interface WKScrollView : UIScrollView@property (nonatomic, assign) WKWebView *internalDelegate;@end@interface WKScrollView : UIScrollView@property (nonatomic, assign) WKWebView *internalDelegate;@end
通过阅读源码后发现不是这样的(代码有删减,感兴趣可自行阅读源码)。
- (void)setInternalDelegate:(WKWebView *)internalDelegate{ if (internalDelegate == _internalDelegate) return; _internalDelegate = internalDelegate; [self _updateDelegate];}- (void)setDelegate:(id )delegate{ if (_externalDelegate.get().get() == delegate) return; _externalDelegate = delegate; [self _updateDelegate];}- (id )delegate{ return _externalDelegate.getAutoreleased();}- (void)_updateDelegate{//...... if (!externalDelegate) else if (!_internalDelegate) else { _delegateForwarder = adoptNS([[WKScrollViewDelegateForwarder alloc] initWithInternalDelegate:_internalDelegate externalDelegate:externalDelegate.get()]); [super setDelegate:_delegateForwarder.get()]; }}- (void)setInternalDelegate:(WKWebView *)internalDelegate{ if (internalDelegate == _internalDelegate) return; _internalDelegate = internalDelegate; [self _updateDelegate];}- (void)setDelegate:(id )delegate{ if (_externalDelegate.get().get() == delegate) return; _externalDelegate = delegate; [self _updateDelegate];}- (id )delegate{ return _externalDelegate.getAutoreleased();}- (void)_updateDelegate{//...... if (!externalDelegate) else if (!_internalDelegate) else { _delegateForwarder = adoptNS([[WKScrollViewDelegateForwarder alloc] initWithInternalDelegate:_internalDelegate externalDelegate:externalDelegate.get()]); [super setDelegate:_delegateForwarder.get()]; }}
这个internalDelegate的作用是让WKWebView 监听scrollview的滚动回调,同时也可以让开发者在外部监听WKWebView的scrollview回调。如何实现的呢?可以查看WKScrollViewDelegateForwarder的实现。
- (void)forwardInvocation:(NSInvocation *)anInvocation{ //... if (internalDelegateWillRespond) [anInvocation invokeWithTarget:_internalDelegate]; if (externalDelegateWillRespond) [anInvocation invokeWithTarget:externalDelegate.get()];}- (void)forwardInvocation:(NSInvocation *)anInvocation{ //... if (internalDelegateWillRespond) [anInvocation invokeWithTarget:_internalDelegate]; if (externalDelegateWillRespond) [anInvocation invokeWithTarget:externalDelegate.get()];}
通过复写- (void)forwardInvocation:(NSInvocation *)anInvocation 方法,在消息转发时实现的。
4.2 猜想 & 验证既然WKScrollingNodeScrollViewDelegate 不是WKScrollview的属性,那说明崩溃堆栈中的scrollview不是WKScrollview,那页面上还有其他scrollview么。我们看源码WKScrollingNodeScrollViewDelegate 是在哪里设置的。
void ScrollingTreeScrollingNodeDelegateIOS::commitStateAfterChildren(const ScrollingStateScrollingNode& scrollingStateNode){ //...... if (scrollingStateNode.hasChangedProperty(ScrollingStateNode::Property::ScrollContainerLayer)) { if (!m_scrollViewDelegate) m_scrollViewDelegate = adoptNS([[WKScrollingNodeScrollViewDelegate alloc] initWithScrollingTreeNodeDelegate:this]); } }void ScrollingTreeScrollingNodeDelegateIOS::commitStateAfterChildren(const ScrollingStateScrollingNode& scrollingStateNode){ //...... if (scrollingStateNode.hasChangedProperty(ScrollingStateNode::Property::ScrollContainerLayer)) { if (!m_scrollViewDelegate) m_scrollViewDelegate = adoptNS([[WKScrollingNodeScrollViewDelegate alloc] initWithScrollingTreeNodeDelegate:this]); } }
搜索webkit的源码,发现创建WKScrollingNodeScrollViewDelegate的位置只有一处。但是webkit的源码太过于复杂,无法通过阅读源码的方式知道WKScrollingNodeScrollViewDelegate属于哪个scrollview。
为此我们只能换一种思路,我们通过xcode调试的方式查看当前webview加载的页面是否还有其他scrollview。
页面上刚好还有一个scrollview:WKChildScrollview
这个WKChildScrollview 是否是崩溃堆栈中的scrollview呢,如果我们能确定他的delegate是WKScrollingNodeScrollViewDelegate,那就说明这个WKChildScrollview 是崩溃堆栈中的scrollview。
为了验证这个猜想,我们首先找到源码,源码并没有太多,看不出其delegate类型。
@interface WKChildScrollView : UIScrollView @end@interface WKChildScrollView : UIScrollView @end
我们只能转换思路在运行时找到WKWebView的类型为WKChildScrollView的子view(通过OC runtime & 视图树遍历的方式),判断他的delegate是否为WKScrollingNodeScrollViewDelegate 。
我们运行时找到类型为 WKChildScrollView 的子view后,获取其delegate类型,确实是WKScrollingNodeScrollViewDelegate。至此我们找到了崩溃堆栈中的scrollview。
确定了崩溃堆栈中的scrollview的类型,那么修复起来也比较容易了。在页面生命周期的viewDidAppear方法里,获取类型为 WKChildScrollView的子view。然后在dealloc方法里,将其delegate置空即可。
deinit { if self.childScrollView != nil { if self.childScrollView?.delegate != nil { self.childScrollView?.delegate = nil } }}deinit { if self.childScrollView != nil { if self.childScrollView?.delegate != nil { self.childScrollView?.delegate = nil } }}
4.3 小程序同层渲染想完了解决方案,那么WKChildScrollView 是做啥用的呢?
WKWebView 在内部采用的是分层的方式进行渲染,它会将 WebKit 内核生成的 Compositing Layer(合成层)渲染成 iOS 上的一个 WKCompositingView,这是一个客户端原生的 View,不过可惜的是,内核一般会将多个 DOM 节点渲染到一个 Compositing Layer 上,因此合成层与 DOM 节点之间不存在一对一的映射关系。当把一个 DOM 节点的 CSS 属性设置为overflow: scroll(低版本需同时设置-webkit-overflow-scrolling: touch)之后,WKWebView 会为其生成一个WKChildScrollView,与 DOM 节点存在映射关系,这是一个原生的UIScrollView的子类,也就是说 WebView 里的滚动实际上是由真正的原生滚动组件来承载的。WKWebView 这么做是为了可以让 iOS 上的 WebView 滚动有更流畅的体验。虽说WKChildScrollView也是原生组件,但 WebKit 内核已经处理了它与其他 DOM 节点之间的层级关系,这一特性可以用来做小程序的同层渲染。(「同层渲染」顾名思义则是指通过一定的技术手段把原生组件直接渲染到 WebView 层级上,此时「原生组件层」已经不存在,原生组件此时已被直接挂载到 WebView 节点上。你几乎可以像使用非原生组件一样去使用「同层渲染」的原生组件,比如使用view、image覆盖原生组件、使用z-index指定原生组件的层级、把原生组件放置在scroll-view、swiper、movable-view等容器内等等)。
5、苹果的修复方案本着严谨的态度,我们想是什么导致了最开始的崩溃堆栈呢?是我们开发过程中的功能还是系统bug?如果是系统bug,其他公司也可能遇到,但是互联网上搜不到其他公司或开发者讨论崩溃相关信息。我们继续看一下崩溃堆栈的top 函数RemoteScrollingTree::scrollingTreeNodeDidScroll() 源码如下:
void RemoteScrollingTree::scrollingTreeNodeDidScroll(ScrollingTreeScrollingNode& node, ScrollingLayerPositionAction scrollingLayerPositionAction){ ASSERT(isMainRunLoop()); ScrollingTree::scrollingTreeNodeDidScroll(node, scrollingLayerPositionAction); if (!m_scrollingCoordinatorProxy) return; std::optional layoutViewportOrigin; if (is(node)) layoutViewportOrigin = downcast(node).layoutViewport().location(); m_scrollingCoordinatorProxy->scrollingTreeNodeDidScroll(node.scrollingNodeID(), node.currentScrollPosition(), layoutViewportOrigin, scrollingLayerPositionAction);}void RemoteScrollingTree::scrollingTreeNodeDidScroll(ScrollingTreeScrollingNode& node, ScrollingLayerPositionAction scrollingLayerPositionAction){ ASSERT(isMainRunLoop()); ScrollingTree::scrollingTreeNodeDidScroll(node, scrollingLayerPositionAction); if (!m_scrollingCoordinatorProxy) return; std::optional layoutViewportOrigin; if (is(node)) layoutViewportOrigin = downcast(node).layoutViewport().location(); m_scrollingCoordinatorProxy->scrollingTreeNodeDidScroll(node.scrollingNodeID(), node.currentScrollPosition(), layoutViewportOrigin, scrollingLayerPositionAction);}
崩溃在这个函数里,查看这个函数的commit记录:
简单描述一下就是scrollingTreeNodeDidScroll方法中使用的m_scrollingCoordinatorProxy 对象改成weak指针,并进行判空操作。这种改变,正是解决m_scrollingCoordinatorProxy 内存被释放后还在访问的方案。
这个commit是2023年2月28号提交的,commit log是:
[UI-side compositing] RemoteScrollingTree needs to hold a weak ref to the RemoteScrollingCoordinatorProxyhttps://bugs.webkit.org/show_bug.cgi?id=252963rdar://105949247Reviewed by Tim Horton.The scrolling thread can extend the lifetime of the RemoteScrollingTree via activity on that thread,so RemoteScrollingTree needs to hold a nullable reference to the RemoteScrollingCoordinatorProxy;use a WeakPtr.[UI-side compositing] RemoteScrollingTree needs to hold a weak ref to the RemoteScrollingCoordinatorProxyhttps://bugs.webkit.org/show_bug.cgi?id=252963rdar://105949247Reviewed by Tim Horton.The scrolling thread can extend the lifetime of the RemoteScrollingTree via activity on that thread,so RemoteScrollingTree needs to hold a nullable reference to the RemoteScrollingCoordinatorProxy;use a WeakPtr.
至此,我们基本确认,这个崩溃堆栈是webkit内部实现的一个bug,苹果内部开发者最终使用弱引用的方式解决。
同时修复上线后,这个crash的崩溃量也降为0。
6、总结本文中的crash从出现到解决历时近一年,一开始根据线上日志判断是h5 页面返回 & h5 页面滚动导致的问题,禁用手势后虽然几乎解决问题,但是线上还有零星crash上报,因此为了保证h5 离线功能的线上稳定性,需要完美解决问题。
本文的crash 似曾相识,但是经过验证和阅读源码后发现并不是想象的那样,继续通过猜想+阅读源码的方式寻找到了崩溃堆栈中的真正scrollview代理对象,从而在app 侧解决问题。最后发现是苹果webkit的bug。
本文中的崩溃问题本质上是野指针问题,那么野指针问题定位有没有通用的解决方案呢?
标签:
推荐
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
索尼全新PS掌机Q将问世:10年没更新这条产品线了 天天快资讯
2023-05-30 05:01:16 作者:人宝宝本周,索尼发布了一款名为“Project Q”的PlayStation掌上设备。不
来源: -
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
财富更多》
-
全球最资讯丨金碚:挖掘工业机器人产业潜力
金碚:挖掘工业机器人产业潜力---一段时...
-
最大“黑客帝国”非美莫属-头条
最大“黑客帝国”非美莫属---近日,有美...
-
“以我为主”释放市场化改革效能
“以我为主”释放市场化改革效能---作为...
-
一张精工“面膜”背后的“独门绝技”|当前快报
一张精工“面膜”背后的“独门绝技”---...
-
“白发姑苏”传承焕新——二千五百年古城的人文经济嬗变
“白发姑苏”传承焕新——二千五百年古...
动态更多》
热点
- realme10系列正式宣布 采用双曲面屏正面顶部居中挖孔
- 五菱全新微型电动车内饰官图发布 座椅采用星际形打孔工艺
- 努比亚Z40星空典藏版正式开售 采用微米级油画笔触纹理技术
- iQOO11系列正式官宣 首批搭载骁龙8Gen2机型之一
- 海信34英寸带鱼屏显示器发布 支持165Hz刷新率
- OPPO明年将商用240W超级闪充 新一代电芯支持更高倍率充电
- 第一款Android手机渲染图曝光 横向滑盖设计和全尺寸键盘
- 吉利首款纯电皮卡11月9日上市 车辆续航里程超过610公里
- 努比亚Z40SPro星空典藏版正式公布 堪称窄边框天花板
- vivo无线运动耳机2今日正式上市 首销只要119元
- 最强进化_对于最强进化简单介绍
- 互动 北汽蓝谷:目前SiC电机控制器已经处于研转产的阶段 正在进行第三轮可靠耐久测试_热推荐
- 【世界快播报】温暖“童”行,长寿这场培训教你如何赢得孩子的心!
- 环球快资讯丨旬月在古文是什么意思_古文的旬是什么意思
- 银魂哪一集是神威出场_银魂第三季神威出场了吗|全球快看点
- 恋爱恐惧症的症状_恋爱恐惧症的24个表现 恋爱恐惧症有什么表现
- 微动态丨力争突破100亿元!2023临沂实施水利项目工程数量及投资额均居全省第一
- 证明信的格式及范文调职_证明信的格式及范文
- 快消息!讲历史的节目谁讲得好(讲历史的节目)
- 后摇音乐代表作_后摇音乐
- “杭州伞” “玉琮馆” 这些亚运场馆科技感爆棚_天天微资讯
- 焦点消息!中国信通院“OSCAR合规治理沙龙”在京召开 腾讯、阿里等企业共话开源生态建设
- 当前动态:基金调研丨Harding Loevner基金调研汉钟精机
- 当前观点:最新!河南要求:优先保住小麦种子、落实跨区机收免费通行......
- 中超:深圳胜梅州客家
- 天天时讯:情感与现实:探秘斯皮尔伯格如何通过电影让人深思人生
- 北京检察机关依法对周茂非涉嫌贪污、受贿案提起公诉
- 直播预告:今日中午专家教你居家推拿治疗颈腰椎病?|环球快播
- 福建进一步加强房地产项目预售资金监管 违规企业将暂停销售
- 泸水县气象台发布高温橙色预警信号【Ⅱ级/严重】【2023-05-29】 天天滚动
- 皇社十年的等待!久保建英发文庆祝:欧冠,我们来啦!
- 天孚通信:控股股东拟减持公司不超0.75%股份
- 迎接赛末冲刺阶段!
- 天天百事通!栖霞建设: 栖霞建设持股5%以上股东集中竞价减持股份计划时间届满暨结果公告
- 小舞成神造型终于来了,头发完全散开,身穿白色蕾丝样子仙哭|视焦点讯
- 世界热文:海贼王:收视率最高的一集,只因娜美这这位侍女的迷之走光!
- 环球热推荐:海水环境质量总体保持稳定 2022年我国海洋生态环境状况稳中趋好
- 618职场福利!华为HarmonyOS 3 double职场生产力|环球播报
- 世界快资讯:一饿就心慌浑身无力发抖需要治疗吗(一饿就心慌浑身无力发抖)
- 当虹科技与三六零集团签约:开展内容审核项目合作|全球时讯
- 土耳其第一次举办总统选举第二轮投票 充满了不确定性 全球聚看点
- 最新快讯!36氪晚报丨波音将在零部件供应链等领域与越南合作;渣打与普华永道中国联合发布白皮书;五粮液参股创投企业投资新能源公司
- 经济日报:为农机跨区作业提供有温度的服务|当前讯息
- 无人驾驶矿山运输机器人"载山CarMo"正式投入使用|焦点滚动
- 天天热点评!吉林省前4月规上工业快速增长
- 波士顿咨询公司报告:中国时尚行业将呈现量稳质升趋势
- eFishery 完成规模为1.08亿美元的D轮融资,软银等参投
- 讲述“这一届”职场人的故事
- 新增多项实用功能,广汽传祺影酷迎新版本OTA升级-全球资讯
- 环球新消息丨V观财报|张家界收年报问询函:为何净利润连续三年亏损?
- 隆基5月单晶硅片价格公示 平均价格下调约30%
- 深圳时尚家居设计周圆满闭幕,德国 88 年品牌乐德飞翼
- 工业富联涨6.6% 机构净卖出7.15亿元
- 环球观速讯丨两部门:推动大企业加强计量引领带动,促大中小企业融通发展
- 华电国际涨停 机构净买入1.76亿元
- 戴威美国二次创业项目陷入困境:资金链受阻 扩张彻底停滞 天天速读
- 焦点滚动:布吉人民医院妇科怎么样 布吉妇科医院
- 焦点快看:报告称2025年中国分布式存储市场规模将超200亿元
- 台湾5月消费者信心指数回升 学者指“反映短期效应”
- iPhone16Pro机型为6.3和6.9英寸,屏幕加大只因这个组件 焦点播报
- 每日热文:18元一斤?消费者大呼西瓜贵了 一小块瓜要5元
- 废钢跌势趋缓,跟随成材运行
- 硅动力6月5日上交所首发上会 拟募资6.9亿元|速递
- 全球快播:少年中国问丨量子计算如何改变我们的生活?
- 江西移动与南昌市人民政府深化战略合作
- 思密达全新剂型蒙脱石混悬液上市
- 微信:治理个人帐号发布违禁品营销信息行为 世界观速讯
- 东方通跌15.64% 机构净卖出7416万元_天天即时看
- 航锦科技跌9.57% 机构净卖出9469万元 短讯
- 全球视点!光子芯片温控耗能减至目前的百万分之一 可用于未来数据中心和超级计算机通信网络
- 2023中关村论坛|精彩继续 中关村国际技术交易大会不落幕 天天看热讯
- 工行淮安城北支行贯彻学习二十大“四轮驱动”推进网点竞争力提升_实时焦点
- 生态环境部:稳步扩大火电、钢铁等行业碳监测评估
- 北京海淀区20所中小学授牌“非遗传承基地校”
- 科技部火炬中心党委书记吕先志:去年177家国家高新区园区生产总值占国内GDP比重13.9%_全球信息
- 观热点:文远知行获ISO/SAE 21434汽车网络安全流程认证
- 工信部:1-4月份我国软件业务收入33166亿元,同比增长12.8%
- 北京米扬丽格夏正义院长:关于舒铂材料的临床实践 暨纤铂新品上市
- 为什么现在的演唱会都不能选位置?|全球讯息
- 清肺排毒汤_清肺
- 切瓦特·埃加福特加盟《毒液3》 漫威再就业 天天资讯
- 米兰锁定前四,皮奥利用人释放信号:有人急需挽留,有人放弃治疗
- 不屑,姆巴佩突爆争议采访!皇马底蕴成笑话,佛爷知道C罗多好了
- HKC惠科发布首款QHD 500Hz显示器:40-500Hz可变高刷、双百色域 全球简讯
- 天合光能跌16.34% 机构净卖出4.52亿元
- 环球热门:Patient21获得1.08亿美元C轮融资
- 天津港集团与ABB公司签署战略合作协议|环球热文
- 世界简讯:渝北双凤桥街道:做好燃气自闭阀安装工作 筑牢群众生命安全防线
- 特斯拉声明:目前没有与任何第三方进行招聘活动-每日讯息
- 观天下·美债危机|媒体和业内人士:美国债务上限协议达成未必是“好消息”_天天简讯
- 观天下!通富微电涨10% 机构净买入3.3亿元
- 华为开发者大会2023 ( Cloud ) 将于7月7日正式揭幕-微动态
- 高三备考好兄弟Brother DCP-T426W打印机
- 最高法、全国妇联发布保护未成年人权益司法救助典型案例 环球报道
- 鹏都农牧跌9.95% 机构净卖出5105万元
- 教师办公必备好物Brother DCP-B7535DW打印机
- 花旗银行开户条件门槛_花旗银行开户条件
- 荣耀90系列全新发布,全系标配2亿像素写真相机影像升维_当前热门
- 每日精选:开发“在线预约”,创新旅游业服务 在家“动动手”,出游更省心
- 台北电脑展上英伟达(NVDA.US)公布了哪些产品和服务?-天天视点
- 滚动:18年前失踪儿子,线索断裂
- 荣耀90系列全新发布,全系标配2亿像素写真相机影像升维_焦点快播
- 百度地图2023年第一季度中国城市交通报告:广东人通勤出行最幸福|环球速看
- 全球今亮点!吴若曼新任兴银基金董事长兼法定代表人 张贵云离任
- 每日精选:电影《长空之王》香港票房超11万美元
- 两部门联合印发《关于实施中小企业计量伙伴计划的通知》
- 第25届上海国际电影节金爵奖入围影片名单揭晓 速读
- 当前视点!现代和起亚宣布与FIFA的合作伙伴关系延长至2030年
- 天天新动态:平安基金成钧离任2只ETF
- 国投瑞银瑞盛混合(LOF)增聘基金经理贺明之 全球热头条
- 中微电科技完成新一轮融资-全球速讯
- 每日看点!Checkmate.获得1500万美元A轮融资
- 汇丰晋信基金副总经理兼首席运营官赵琳离任|实时
- 当前快看:医疗冷链有哪些股票?医疗冷链概念股票一览
- 世界今日讯!光伏组件概念股名单一览(2023A股光伏组件概念上市公司)
- 光伏发电投资额同比大增 机构看好光伏设备高景气
- 环球动态:神舟十五号乘组即将返回 创出舱次数最多等多项纪录
- 世界今日报丨海洛创新获千万元Pre-A轮融资
- 视频解析工具Video-ChatGPT上线 可用文本描述视频内容 世界新动态
- Sabi Am获得3800万美元B轮融资
- 竞赛聚英才 第二届"长江杯"动力电池技术挑战赛决赛开幕
- 租房难?一德国男子使用ChatGPT 找到满意的房子 全球微资讯
- 业界:提升农业社会化服务水平 让小农户融入大产业大市场_世界关注
- 【环球时快讯】收评:创业板指跌1.14% 电力板块全天强势
- 【当前热闻】全国首个无人岛岛主成“老赖” 名下海岛起价2785万流拍
- 天天快看:种地吧出品方申请后陡门商标 种地吧出品方申请十个勤天商标
- 天天观热点:次北固山下的意思简短一点_次北固山下的意思简介介绍
- 全球看点:议论“校园碾压案”家长妆容,这是无聊更是残忍
- 当前快播:豆瓣8.1,这世界也容不下男孩的亲密友谊
- 搞了半天,高德打车无证却变相从事网约车经营,一喂等平台吃瓜了
- 华为发布商业市场新品,助力数字化转型_每日播报
- 宝馨科技携新能源领域多项最新研发和应用成果亮相SNEC展会 每日热点
- 外媒:特斯拉数据或“大规模”泄露,涉及马斯克信息-全球消息
- Orbofi AI获得280万美元战略投资-全球聚看点
- 润贝航科(001316):该股换手率大于8%(05-29)-聚看点