2018-04-27 14:32:50 haochentao 阅读数 1383
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3668 人正在学习 去看看 许英俊

最近在混合开发过程中测试发现,当H5调用本地原生方法后 原生再次调用H5函数使用(jsContext evaluateScript)时候 H5执行网络请求会导致jsContext崩溃,崩溃日志也只是提示僵尸对象某个对象被释放,此问题目前就在11.3系统上有体现,目前我的解决方案是使用

        

[self.webViewstringByEvaluatingJavaScriptFromString:@"JS函数"];



在测试过程中还发现这样使用也会导致崩溃也是iOS11.3

    

dispatch_async(dispatch_get_main_queue(), ^{

     [self.jsContextevaluateScript:@"JS函数"];

});


有知道问题的小伙伴环境一起讨论..............
2018-05-22 18:10:49 kuangdacaikuang 阅读数 708
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3668 人正在学习 去看看 许英俊

解决UITableView的style为group时, 8.3系统崩溃的问题

tableView的懒加载
这里写图片描述

发生崩溃的地方
这里写图片描述

崩溃原因
这里写图片描述

提示cell没有注册,但是检查发现,cell是注册的,iOS11系统模拟器运行完全没问题,iOS8.3系统模拟器运行崩溃
这里写图片描述

这个崩溃是8.3系统的重大bug!!!!!
将tableView.separatorStyle = .none,放在register注册cell的方法后面就不崩溃了

这里写图片描述

iOS8.3系统,tableView的style为group是,总是崩溃

reason: ‘unable to dequeue a cell with identifier TopicTitleCellReuseIdentifier - must register a nib or a class for the identifier or connect a prototype cell in a storyboard’

检查cell都注册过了, 果然是这个问题,调整到注册cell后面就不崩溃了

2018-04-02 00:22:22 u012413955 阅读数 5835
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3668 人正在学习 去看看 许英俊

我们在iOS11.3上踩了一个大坑!这个坑表现在线上的版本只要用户升级到iOS11.3且退出登录,或者登录态过期,都会闪退。因为iOS11.3支持了两个超级一线城市的公交卡,引发了用户短时间集中更新。为了解决这个问题,整个团队发一个小版本来降级这个问题的影响。

问题的表现:

前面说过,只要退出登录,App就会闪退。这是因为我们在退出登录时清除WKWebView的cookie时引发了崩溃。

问题的原因:

苹果应该在iOS11.3上修改了nonPersistentDataStore创建的DataStore的实现。

问题复盘:

我们先回归一下WKWebView下cookie的前世今生。cookie本质上是h5用来保存登录、用户名、以及一些特定时间内有效的信息的机制。这个东西有几个显而易见的好处:

1、本地化的存储一些信息,可以减少h5请求的次数。提升h5的性能,降低服务端压力;

2、cookie作为h5请求request的一部分,会把一些客户端的固定信息直接传给服务端,避免h5因为某些信息又需要发送网络请求;

3、cookie是域名隔离的,有一定的安全性;

正因为有这么多的好处,所以,很多时候h5大量的依赖了cookie机制。甚至用它保存了一些敏感信息。这些信息的泄露会对用户的安全造成重大威胁。所以苹果在iOS8引入WKWebView时,没有给原生暴露任何操控cookie的API(事实上,不仅cookie,其他任何和缓存、持久化相关的接口都没有)。我的理解是:苹果有意识将cookie对开发者进行了屏蔽,就是不希望原生开发者对cookie进行干预。而cookie的安全性完全由h5来保证。讲道理这么做无可厚非。但是有个东西很可怕----那就是用户习惯。在原来老的UIWebView下,以及其他的浏览器中熟悉了各种cookie操作的开发者肯定不会就此罢休。各种携带cookie的“黑”操作层出不穷。所以,从iOS9开始,苹果暴露了WKWebView数据存储的类----WKWebsiteDataStore。顾名思义,这个类暴露了一些获取(清除)特定缓存的能力,这里包括了cookie。下面稍微介绍一下这些能力

+ (NSSet<NSString *> *)allWebsiteDataTypes;

可以获取dataStore中所有的数据类型。这里有:

    WKWebsiteDataTypeDiskCache,//硬盘缓存
    WKWebsiteDataTypeOfflineWebApplicationCache,//离线应用缓存
    WKWebsiteDataTypeMemoryCache,//内存缓存
    WKWebsiteDataTypeLocalStorage,//localStorage,cookie的一个兄弟
    WKWebsiteDataTypeCookies,//cookie
    WKWebsiteDataTypeSessionStorage,//session
    WKWebsiteDataTypeIndexedDBDatabases,//索引数据库
    WKWebsiteDataTypeWebSQLDatabases//数据库

这里可以看出,与h5相关的缓存都暴露给了原生。

-(void)fetchDataRecordsOfTypes:(NSSet<NSString*>*)dataTypes completionHandler:(void(^)(NSArray<WKWebsiteDataRecord *> *))completionHandler;
获取某些指定的数据类型。最后数据实例用一个统一的抽象的WKWebsiteDataRecord来表示。
-(void)removeDataOfTypes:(NSSet<NSString*>*)dataTypes forDataRecords:(NSArray<WKWebsiteDataRecord *> *)dataRecords completionHandler:(void (^)(void))completionHandler;

移除某些特定的数据类型。


- (void)removeDataOfTypes:(NSSet<NSString*> *)websiteDataTypes modifiedSince:(NSDate *)date completionHandler:(void (^)(void))completionHandler;

移除指定时期的特定的数据类型。


从以上可以看出,苹果暴露了各种缓存的获取方法和移除方法。但是没有给设置方法。而且cookie并不突出。和其他兄弟一样。所以苹果的本意还是不希望原生直接干预cookie的设置。


但是从iOS11开始,一切都变了。苹果彻底放开了cookie的操作权限。它在WKWebsiteDataStore中暴露了一个

WKHTTPCookieStore类型的属性。专门用来管理cookie。cookie摇身一变,从嫔妃变成了皇后。位置特殊了。通过这个属性,原生可以自由的移除cookie和设置cookie了(是不是和以前的NSHttpCookieStorage一样了?)。


这种设计带来了一个问题?现在在iOS8、9、10、11都存在的情况下,我们如何清除cookie。iOS8没有暴露接口,用户量也不大了,我们不做考虑。iOS9,10只有一种方式。iOS11有两种(注意苹果暴露了WKHTTPCookieStore的属性来操作cookie,但是老的API并没有废弃,哪怕是和cookie相关的那部分也没有废弃)。我想看到这个问题,脑子比较正常的人都会想:


iOS11采用新的API就行了啊。


但总有脑子不正常的人,比如我。我原本是想这么干的。但是后来一想,老的API没有废弃,那就肯定可以用,那我继续用它呗。但是有个问题,iOS11既然暴露了新的接口,这是不是意味着老的API可能清除cookie会失败呢?或者后续哪个版本万一失败呢?所以,我用了一种比较“保险”的方案。那就是先用老的API去清除,然后用新的API去校验。伪代码可以这么来看:


old api fetch cookie:
finish{
   old api remove cookie:
   finish{
        new api get cookie:
        finish{
           if cookie still exist
              new api clear cookie
        }
   }
}

逻辑上没有毛病!!!我到目前为止仍然认为逻辑上没有毛病。


下面开始清除。在清除的时候我们发现WKWebsiteDataStore有两个类方法:

/* @abstract Returns the default data store. */
+ (WKWebsiteDataStore *)defaultDataStore;

/** @abstract Returns a new non-persistent data store.
 @discussion If a WKWebView is associated with a non-persistent data store, no data will
 be written to the file system. This is useful for implementing "private browsing" in a web view.
*/
+ (WKWebsiteDataStore *)nonPersistentDataStore;

字面意思很清楚,第二个是非持久的dataStore, 那第一个就是持久的。我的做法是分别去清除这两类dataStore中的cookie。需求做完没有毛病,一直很健康,退出登录时cookie被清除的寸草不生。我暗自欣慰。

但是iOS11.3推出后,登陆的同事反馈,闪退。瞎了我的钛合金狗眼。为啥,再经历了mac系统升级、xcode升级、手机操作系统升级等一系列变态操作后,真相来了:

我们上述方法在清除nonPersistentDataStore时当执行到用iOS11的API去校验时就挂了。崩溃的栈显示WKWebsiteDataStore正在析构。WTF!!!!

问题的原因大概就清晰了:

defaultDataStore不挂,原因是它类似于单例,代码执行过程中不会析构!

nonPersistentDataStore 以前不挂,现在开始挂,说明以前苹果对它的实现也是单例,而现在它应该不是单例了。我们创建它的实例是在函数内部,当出了方法作用域后它就会析构了。执行iOS11 API检验时它正在析构,向一个正在析构的对象发消息它是会挂的。

现在我们回头来看nonPersistentDataStore的说明:

 @abstract Returns a new non-persistent data store.
 @discussion If a WKWebView is associated with a non-persistent data store, no data will
 be written to the file system. This is useful for implementing "private browsing" in a web view.

和前面持久化的dataStore不同的是,nonPersistentDataStore用于实现私密的浏览器,即该浏览器的数据与其他WebView不共享。苹果本质的意愿应该是一个WKWebView和一个nonPersistentDataStore的绑定。以前的策略应该是多个WKWebView可以和一个non-persistent的datastore绑定。只要它和普通的datastore隔离即可。(当然,以上都是通过现象的推测。如果有人有确定说明,欢迎指正)

至此,这个坑介绍完毕!我们来总结一下这里我们的失误:

第一、对nonPersistentDataStore缺少比较全面的理解,如果理解了它的用途,其实可以判定当前我们的App是没有使用场景的;

第二、iOS11和iOS9、10的API最好不要嵌套使用。其实我们当时做的时候就发现老的API的效果是ok的。只不过不放心,用一种莫须有的心态增加了一个逻辑。其实这个逻辑即使有必要,也要经过验证,证明老的API确实无法完成再去完善,毕竟cookie即使清除不了,也不是天塌下来的事。后续完善即可。这种前期画蛇添足的思维方式还是要多改变!!!

完!


2020-02-11 12:01:17 chengyang225 阅读数 531
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

    只要你会OC基础,会写HelloWorld,你就可以实现iOS的蓝牙通信功能,实现蓝牙小项目也不在话下,作者会带领大家详细分析BLE4.0原理,通过分析xcode使用的蓝牙API,让学者能够得心应手的实现蓝牙BLE4.0的开发

    3668 人正在学习 去看看 许英俊

今天在学习flutter时随手建了个入门项目,在安卓真机,ios13.3.1模拟器上运行没有什么问题,当运行在我ios版本为13.3.1的iPhone 11上时报

dyld: Library not loaded: @rpath/Flutter.framework/Flutter

  Referenced from: /private/var/containers/Bundle/Application/97C6EBE0-8C88-48D6-9370-58AB8F2EE273/Runner.app/Runner

  Reason: no suitable image found.  Did find:

/private/var/containers/Bundle/Application/97C6EBE0-8C88-48D6-9370-58AB8F2EE273/Runner.app/Frameworks/Flutter.framework/Flutter: code signature invalid for '/private/var/containers/Bundle/Application/97C6EBE0-8C88-48D6-9370-58AB8F2EE273/Runner.app/Frameworks/Flutter.framework/Flutter'

 

/private/var/containers/Bundle/Application/97C6EBE0-8C88-48D6-9370-58AB8F2EE273/Runner.app/Frameworks/Flutter.framework/Flutter: stat() failed with errno=25

(lldb) 

我的环境如下:

iOS 13.3.1
Flutter (Channel stable, v1.12.13+hotfix.7)
Xcode 11.3.1
MacOS Catalina 10.15.3

百度了下没找到答案,谷歌了下,看了几篇老外的帖子,好像找到问题了,貌似是最新ios13.3.1的问题,有几种解决办法可以试试:

1.建议运行在13.3或以下设备,

2.建议找个非个人证书试试

3.在13.3.1模拟器上运行

期待问题修复.

参考链接:https://github.com/flutter/flutter/issues/49504

没有更多推荐了,返回首页