mac osx 运行iOS模拟器时,nsurlsessiond不停地消耗宽带

解决办法1: 将xcode.app里面的nsurlsessiond程序重命名 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/libexec/nsurlsessiond 解决办法2: 建立防火墙规则,禁止xcode.app里面的nsurlsessiond联网 参考 https://developer.apple.com/forums/thread/114981

November 30, 2022 · 1 min · holdsky

iOS 无宿主App源码时,真机环境一键调试动态库

背景 合作项目,一方提供宿主App,一方提供动态库。双方囿于合规而不能为对方提供源码,所以双方提供的产物都是二进制产物。 运行时双方融合是没有问题的,但是对开发(尤其是动态库开发方)是不友好的。 当然,这场景要是在其他操作系统是没有什么大问题的。但对于iOS而言,因为苹果的硬性限制,真机环境调试是有些麻烦的。为解决开发阶段的调试需求,本文提供了一种思路并实践可行。 一些准备 开发者证书(调试)是必需的 Xcode ,本文成文时使用的是13.4.1 fastlane 工具,本文使用其重签名工具 手动调试 在介绍一键调试前,先大致介绍下如何手动调试。 若要在真机环境调试,需要先将部署到真机的所有可执行文件进行签名,这包括App主程序和动态framework 获取开发者证书列表 运行命令,获取可用的证书列表 security find-identity -v -p codesigning 结果一般是十六进制字符串和证书名字,例如 1) 十六进制串 "Apple Development: xxxxx(yyyyyyy)" 1 valid identities found 动态库重签名 codesign -f -s 证书标识(十六进制串) xxxx.framework ipa包重签名 本文使用fastlane工具 # 安装fastlane sudo gem install fastlane 安装成功后,执行重签名 fastlane sigh resign #然后安装提示输入ipa包文件路径、证书文件路径 #期间也可填写证书的十六进制串 特别注意:重签名证书必需使用 开发证书。 重签名成功后,获得同名的ipa包,使用Xcode提供的 Devices and Simulators 工具将ipa包安装到iPhone真机中 附加到进程 在真机上启动App 然后使用Xcode 提供的 Debug -> Attach to Process 工具,将动态库附加到App进程中,正常情况下是就可以了进行调试了。 一键调试 一键调试的原理和过程和手动调试是类似的,只不过把一些工作自动化了 ...

September 5, 2022 · 1 min · holdsky

macOS shell 打印所有环境变量

一个 set 命令就可以了

September 2, 2022 · 1 min · holdsky

Win7安装CocoaPods

安装准备 1、Windows7 64位 2、Cygwin 64位 安装Cygwin 在 https://www.cygwin.com/install.html 下载Cygwin的引导安装工具setup-x86_64.exe,打开后选择从网络安装(Install from Internet),国内的话选择mirrors.163.com镜像,之后选择默认配置,然后工具会自动从网络下载所需文件并安装。 安装Ruby 默认情况下,Cygwin不会自动安装Ruby环境。再次打开setup-x86_64.exe工具,选择Ruby安装包 安装gcc 、g++ 、make 因为Cocoapods的一些依赖是C/C++文件包,所以需要安装编译工具 安装git、curl 虽然安装Cocoapods时不需要这两个工具,但是运行时是需要的 安装CocoaPods 在Cygwin中运行 gem install cocoapods # 安装后运行,查看版本 pod --version

August 14, 2022 · 1 min · holdsky

git bundle 增量同步仓库数据

创建增量bundle 创建指定区间的增量bundle git bundle create 文件名.bundle commit_idA..commit_idB 将创建从节点《commit_idA(不含)到节点commit_idB(含)》的增量数据,并存储到 《文件名.bundle》中 验证bundle 验证bundle文件是否匹配当前仓库版本(可以理解为bundle和当前仓库是否有共同的父节点) git bundle verify 文件名.bundle 显示bundle中的引用 git bundle list-heads 文件名.bundle 从bundle中拉取更新 git pull 文件名.bundle bundle中的分支名:本地仓库中的分支名 其中,本地仓库中的分支名可以是《本地的远程分支》,也可以是《本地的本地分支》

August 11, 2022 · 1 min · holdsky

Python使用图片、音频等传输数据

近期因为一些原因,从内网传输数据到外网的行为受到限制,便研究了些非正常手段进行数据传输 使用二维码 原理是在内网系统的屏幕上生成二维码,每秒刷新一次;在外网用拍照或者截屏的方式读取二维码图片,解码为数据。 单个QR码国际标准二维码,二进制模式最多可存储2953字节,2KB多一点,所以使用二维码进行数据传输其速率应该在几KB/S。 生成二维码 需要使用 PIL(pillow) 图像库, qrcode 二维码生成库,以及 tkinter UI界面库。 tkinter 默认随Python一起安装。 from PIL import Image, ImageTk import qrcode import base64 import tkinter def generateTkImages(data): tkImgs = [] for i in range(4): # 单次生成4张二维码图片,这里需要自己根据屏幕适配 content = b'需要传输的数据' #理论上不需要base64编码,但是实际测试使用pyzbar解码字节流二维码时会乱码,所以使用base64将字节流转为字符串 bs = base64.b64encode(content) #创建二维码容器,指定单个区块尺寸和边框尺寸 qr = qrcode.QRCode(box_size = 2,border = 2) #添加数据 qr.add_data(bs) #生成二维码图片 img = qr.make_image() #转换成tkinter支持的图像 tkImg = ImageTk.PhotoImage(image = img) tkImgs.append(tkImg) # 使用数组存储,避免因为tkinter的bug只显示最后一张 return tkImgs class QrApp(tkinter.Frame): def __init__(self,master = None): super().__init__(master) self.master = master self.pack() self.labels = [] for i in range(4): lb = tkinter.Label(self) lb.grid(row = int(i /2) , column = i % 2 ) # 2行 2 列 self.labels.append(lb) def test(self): tkImgs = generateTkImages(需要传输的数据) for i in range(4): self.labels[i].configure(image=tkImgs[i]) self.master.update() #更新界面 self.master.after(1000) # 保持1000毫秒 root = tkinter.Tk() root.geometry('1030x550+0+0') app = QrApp(root) root.after(500,app.test) root.mainloop() 二维码解码 本文使用 pyzbar 解码,图片来自截屏 ...

August 10, 2022 · 2 min · holdsky

Windows 10 使用VirtualBox安装 MacOS Monterey

注意,本文的部分操作需要使用MacOSX操作系统,以用来将dmg文件转换为iso/cdr格式的光盘镜像 操作环境 Windows 10 macOS 12 下载工具 这里下载 https://mirrors.dtops.cc/ISO/MacOS/ dmg格式的安装包 这里下载 https://www.virtualbox.org/wiki/Downloads VirtualBox platform packages安装包和 和 Oracle VM VirtualBox Extension Pack扩展包 安装VirtualBox 在Windows 10中安装,过程略。 安装VirtualBox扩展 打开VirtualBox,按照以下操作路径安装扩展包 管理 -> 全局设定 -> 扩展 -> 右侧的添加新包按钮 创建ISO/CDR光盘镜像 本文在macOS 12环境中操作。 将dmg安装镜像复制到应用程序中 本文使用 macOS Monterey 12.4 21F79 Installer for CLOVER 5142 and FirPE.dmg 安装镜像,双击打开,找到 安装macOS Monterey,然后整体拖拽到应用程序路径(/Applications) 理论上这个步骤不是必须的,但是本文测试中发现不在/Applications路径时,后续操作出现异常。 创建 安装macOS Monterey 的可引导镜像 使用hdiutil命令(可参考 通过 macOS 安装器制作 macOS 安装镜像(可用虚拟机及黑苹果等)) //创建空白磁盘镜像 此处开辟了14G多的空白空间。空间大小可以自己调整 // monterey 为镜像名称 hdiutil create -o /tmp/monterey -size 14500m -volname monterey -layout SPUD -fs HFS+J //将monterey.dmg镜像挂载为monterey卷 hdiutil attach /tmp/monterey.dmg -noverify -mountpoint /Volumes/monterey //将应用程序(/Applications)内的安装包制作成可引导的安装盘 sudo /Applications/Install\ macOS\ Monterey\ beta.app/Contents/Resources/createinstallmedia --volume /Volumes/monterey --nointeraction //将安装盘数据刻录为iso/cdr光盘镜像 hdiutil convert /tmp/monterey.dmg -format UDTO -o ~/Desktop/monterey.cdr 创建macOS虚拟机 打开VirtualBox ,创建虚拟机 ...

July 18, 2022 · 1 min · holdsky

Objective-C 新老静态SDK共存方案

背景 ​ 本文将介绍一种在有源码的情况下,新老版本静态SDK共存于同一应用的方法实现。 ​ 静态SDK升级并上线后,可能会发现新版本SDK有问题而老版本SDK没有问题的现象,这时对于已经升级的应用将无法直接回退到老版本SDK,除非一开始就新老版本SDK同时存在于这个应用中。 ​ 对于Objiective-C这种没有命名空间的语言,当一份代码构建出两个静态库,且两个静态库同时链接于同一个应用时(同一个应用同时链接这个两个静态库),那么将会发生符号冲突问题—-符号重定义(duplicate symbol);而解决符号重定义的办法就是将符号重命名,当然删除符号也可以—-不过这样可能引起符号为定义错误。 ​ 就Objiective-C而言,符号重命名需要修改源码。对于静态SDK工程来说,第一步是需要先将类名、函数名、全局变量名这些符号列举出来,然后逐一添加前缀或者后缀, 对于影响业务逻辑的地方还需要斟酌修改,特别是Objiective-C的运行时反射更要注意。例如像NSClassFromString,相关代码添加前缀或者后缀要仔细。 模块化拆分 ​ 这步骤不是必须,但是强烈推荐的。 ​ 就双静态SDK共存这事来看,模块化拆分的唯一目的是减少需要修改的符号数量:例如,通常情况下像AFNetworking这种工具库是没有必要添加前缀或者后缀的。 ​ 所以,拆分的唯一原则:将长期不修改的代码拆分出来,这部分可以作为双SDK的公共库。 导出符号列表 ​ 常见的方法是使用 nm 工具,可以导出SDK里的符号列表。也可采用分析 linkmap 文件的方式,导出SDK里的符号列表。 ​ 需要导出的符号有: 类名 函数名—非类所属 全局变量名 导出的全局变量名如果是静态变量名,一般不需要添加前缀或者后缀。不一般的情况,非静态全局变量引用了静态变量,这时就要处理下。 添加前缀或者后缀 ​ 这里推荐使用预编译宏技术,定义一个宏并使用 ## 连接符 #define SUFX (x) x##_我是后缀 // 类 @interface SUFX(MyClass) ---> @interface MyClass_我是后缀 [SUFX(MyClass) method] ---> [MyClass_我是后缀 method] // 函数 void SUFX(MyFunc) ---> void MyFunc_我是后缀 //变量 int SUFX(MyVar) ---> int MyVar_我是后缀 给Objective-C添加命名空间? 最后,介绍下llvm编译插件,增加命名空间语法支持,从根本上解决问题。不过,尚未完成。。。 ...

June 17, 2022 · 1 min · holdsky

JavaScript兼容性检查(JavaScript compatibility check)

查阅资料,找到以下 使用https://caniuse.com/ 数据, 对应的在线工具为 https://seedmanc.github.io/jscc/ 。不过,这个在线工具还有待完善,检查结果漏了很多。 另外一个是,基于eslint的兼容性检查插件, https://github.com/amilajack/eslint-plugin-compat ,推荐使用这个,可以配置各种浏览器、语法版本、很灵活

May 26, 2022 · 1 min · holdsky

iOS关于音频焦点的资料整理

内容来自互联网,使用了google翻译。 简介 ​ 在iOS中,音频焦点是操作系统为了管理音频硬件而引入的概念,是指App对音频硬件在时间纬度上的使用控制(不是使用权限,使用权限需要App单独申请);App可以独占使用,也可以共享使用—-独占/共享音频焦点。 ​ 独占音频焦点,则只能有一个App使用音频硬件;共享音频焦点,则多个App可以同时使用音频硬件,通常共享音频焦点会导致多个App播放的音频被混音。 ​ iOS中还有个音频会话的概念,在一个App中只有一个音频会话。这里需要注意下,iOS系统只有一个音频焦点,所以App要想使用音频硬件,需要使用音频会话来抢占音频焦点。 ​ 抢占音频焦点示例: // 一个App内所有场景/任务都共享同一个音频会话 AVAudioSession *session = [AVAudioSession sharedInstance]; //获取共享单例 //设置音频硬件使用模式 NSError *error = nil; if ([session setCategory:AVAudioSessionCategoryAmbient error:&error] == NO) { NSLog(@"%@",error); //发生错误 return; } //抢占音频焦点 error = nil; if ([session setActive:YES error:&error] == NO) { NSLog(@"%@",error); //发生错误 return; } ​ 上述代码中,先设置 AVAudioSessionCategoryAmbient 模式,表示应用会随着静音键和屏幕关闭而静音,并且不会中止其它应用播放声音(可以和其它自带应用如iPod,safari等同时播放声音),然后再使用 setActive 抢占音频焦点。 释放音频焦点 ​ 我们的App抢占音频焦点后,可能会导致其他App失去音频焦点,所以当我们使用完音频硬件时,应将音频焦点释放出来。 // 一个App内所有场景/任务都共享同一个音频会话 AVAudioSession *session = [AVAudioSession sharedInstance]; //获取共享单例 //释放音频焦点 NSError *error = nil; if ([session setActive:NO error:&error] == NO) { NSLog(@"%@",error); //发生错误 return; } 释放音频焦点还可以这样: ...

March 28, 2022 · 2 min · holdsky