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

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

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

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

        

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



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

    

dispatch_async(dispatch_get_main_queue(), ^{

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

});


有知道问题的小伙伴环境一起讨论..............
2018-04-11 11:09:01 niejinhao052011 阅读数 1152
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

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

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

11.3 问题是:

解决是:

---------------------------------------------------------------------------------------------

git上3.0引擎  以及4.0引擎



引擎3.0:


引擎4.0:


2018-05-22 18:10:49 kuangdacaikuang 阅读数 676
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

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

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

解决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 阅读数 5372
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

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

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

我们在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即使清除不了,也不是天塌下来的事。后续完善即可。这种前期画蛇添足的思维方式还是要多改变!!!

完!


2018-06-12 12:09:41 asuno_1 阅读数 1294
  • iOS开发-全面解析iOS蓝牙BLE4.0开发

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

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

Mach-O文件

官方介绍总共有11种格式! 是 Mach Object的缩写,是Mac\iOS 上用于存储程序,库的标准格式!
常见的格式:

  • 1.可执行文件
  • 2.objcet
    • .o 文件(目标文件)
    • .a 静态库文件.其实就是N个.o文件的集合
  • 3.DYLIB: 动态库文件
    • dylib
    • framework
  • 4.动态连接器
  • 5.DSYM (打包上架用于监测崩溃信息)

.o文件介绍

1.cmd+n创建一个c文件,c文件输入以下代码:

  #include "test.h"
  #include <stdio.h>

  int main()
  {
      printf("test\n");
      return 0;
  }

2.打开终端输入以下指令:

cd   ... //将目录cd到c文件创建的文件夹
ls   //查看列表 会看到test.c文件
clang -c test.c  //将c转化成.o目标文件
ls 
file test.o  //结果:test.o: Mach-O 64-bit object x86_64 即.o文件为Mach-O文件
file weChat  //则是微信的MachO文件 结果为:
//weChat: Mach-O universal binary with 2 architectures: [arm_v7:Mach-O executable arm_v7] [arm64]
//weChat (for architecture armv7):  Mach-O executable arm_v7
//weChat (for architecture arm64):  Mach-O 64-bit executable arm64
 clang test.o //将目标文件输出
ls  // 出现 a.out 输出执行文件
./a.out  //输出结果 test 跟代码执行结果一直
clang -o test1 test.o 
ls //  test1 出现test1可执行文件 
open .  //打开当前文件夹 可查看可执行文件
clang -o test2 test.c   //直接将c文件编译成可执行文件
ls //test2 出现test2可执行文件 跟.o文件编译结果一致

3.根据以上代码可以得出以下效果,如图:
.o文件为Mach-O文件

4.拓展 接上面环境 创建新的.c文件代码如下:

testSub.c //新文件名
void test()
{
    printf("testSub\n");
    return;
}

test.c //文件代码修改 如下
#include "test.h"
#include <stdio.h>

void test();

int main()
{
    printf("test\n");
    test();
    return 0;
}

5.解析从上面代码来看,两个.c文件是关联的,然后将两个文件编译成一个可执行文件如图:
.o文件集合
6.可以看出文件有关联在编译成可执行文件后会自动关联起来,并且关联顺序不影响程序执行结果。

.a文件介绍

1..a文件为.o文件的集合。
2.找到系统文件查看文件类型如下:
.a文件

动态库文件

.dylib

1.查找系统动态库查看其属性。
2.执行代码如下:

find /usr/lib -name "*.dylib" //查找动态库后缀
file /usr/lib/system/libunc.dylib //查看某一动态库属性

3.结果图:
.dylib文件属性

动态库共享缓存

为了提高性能,系统的动态库文件都存在了动态库共享缓存里面!
动态库是为了,节省内存提高性能。

位置

由于ios由于没有越狱是看不到动态共享缓存库的,但是mac是可以看到的:

 cd /var/db/dyld
ls //得到结果如下
//dyld_shared_cache_i386        dyld_shared_cache_x86_64h     
//shared_region_roots
//dyld_shared_cache_i386.map    dyld_shared_cache_x86_64h.map

动态库缓存在dyld_shared_cache_x86_64h 中。
**手机如果越狱找到了这个文件就能看见UIKit的框架在其中,然后用ida分析和Class-dump去导出就可以分析很多系统框架的源码了。
所以,越狱手机可以对系统做一些逆向。**

动态缓存库运行原理

如下图:
动态缓存库运行原理

动态加载器(动态链接器)(dyld)

  • dynamic linker
  • dynamic loader
    用于调用动态缓存库ios同理
  • 动态加载器位置 打开终端输入命令行:
cd /usr/lib
ls
open .

打开文件夹后看到dyld的可执行文件,查看属性:

file dyld

获得如下结果
动态链接器

可以看出动态链接器其实本质也是Mach-O文件。

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