[{"content":"配置网站 创建 apple-app-site-association 在网站根目录或者 .well-known目录下创建 apple-app-site-association 文件。注意，文件没有后缀名。 文件是一个json文件，内容如下：\n{ \u0026#34;applinks\u0026#34;: { \u0026#34;apps\u0026#34;: [], \u0026#34;details\u0026#34;: [ { \u0026#34;appID\u0026#34;: \u0026#34;团队ID.应用BundleID\u0026#34; \u0026#34;paths\u0026#34;: [\u0026#34;/路径/*\u0026#34;] } ] } } 团队ID，和应用签名证书上的TeamId保存一致 路径 ，遵循url对应的规范，建议每一个App应用都使用独立的路径，便于管理 配置MIME 因为apple-app-site-association 的数据格式是json，所有对应MIME类型：application/json。\n在对应的站点配置文件里设置，以nginx为例:\n# 如果文件在根目录 location /apple-app-site-association { default_type application/json; } # 如果文件在.well-known目录 location /.well-known/apple-app-site-association { default_type application/json; } 验证网站配置 打开 https://branch.io/resources/aasa-validator/ , 输入网站域名并验证配置是否正确。\n关于缓存 Apple会缓存apple-app-site-association文件内容，缓存未必及时更新（一般不超过48小时），所以有时候通过Universal Links打开App会失败。\n打开 https://app-site-association.cdn-apple.com/a/v1/你的网站域名可以查看缓存内容\n创建 Universal Links网页 还需要在网站部署一个 Universal Links网页。网页的访问路径需要和apple-app-site-association文件中配置的路径一致。 当使用 Safari 浏览器打开Universal Links网页时，可唤起App。\n网页内容如下：\n\u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html lang=\u0026#34;zh-CN\u0026#34;\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;UTF-8\u0026#34;\u0026gt; \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width, initial-scale=1.0\u0026#34;\u0026gt; \u0026lt;!-- 苹果 Universal Links 标记 --\u0026gt; \u0026lt;meta name=\u0026#34;apple-mobile-web-app-capable\u0026#34; content=\u0026#34;yes\u0026#34;\u0026gt; \u0026lt;title\u0026gt;打开应用\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;div\u0026gt; \u0026lt;!-- 替换为你的 App 图标 --\u0026gt; \u0026lt;img src=\u0026#34;app-icon.png\u0026#34; alt=\u0026#34;应用图标\u0026#34; class=\u0026#34;app-icon\u0026#34;\u0026gt; \u0026lt;h1 class=\u0026#34;title\u0026#34;\u0026gt;在应用中打开\u0026lt;/h1\u0026gt; \u0026lt;p class=\u0026#34;desc\u0026#34;\u0026gt;即将为你跳转到对应的应用\u0026lt;br\u0026gt;如果未跳转，请点击下方按钮\u0026lt;/p\u0026gt; \u0026lt;!-- Universal Links 跳转按钮（直接访问当前页面即可触发） --\u0026gt; \u0026lt;a href=\u0026#34;javascript:void(0)\u0026#34; class=\u0026#34;open-btn\u0026#34; id=\u0026#34;openBtn\u0026#34;\u0026gt;打开应用\u0026lt;/a\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;script\u0026gt; // 页面加载自动触发 Universal Links 跳转 window.onload = function() { document.getElementById(\u0026#39;openBtn\u0026#39;).addEventListener(\u0026#39;click\u0026#39;, function() { // 苹果会自动处理 Universal Links 跳转 window.location.reload(); }); }; \u0026lt;/script\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; 配置 App 配置App的Associated Domains 项目名称 → Target → Signing \u0026amp; Capabilities，点击左上角 + Capability，搜索并添加 Associated Domains。\n在Associated Domains里添加：applinks:你的网站域名\n加入 Universal Links网页地址为 https://a.b.c/x/y/z ，那么Associated Domains需要配置 applinks:a.b.c App的处理代码 在 SceneDelegate 添加\nfunc scene(_ scene: UIScene, continue userActivity: NSUserActivity) { guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, let url = userActivity.webpageURL else { return } print(\u0026#34;Universal Link 跳转成功：\\(url)\u0026#34;) // 在这里处理跳转逻辑，如打开特定页面 } （老工程）在 AppDelegate 添加\nfunc application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: @escaping ([UIUserActivityRestoring]?) -\u0026gt; Void) -\u0026gt; Bool { if userActivity.activityType == NSUserActivityTypeBrowsingWeb { let url = userActivity.webpageURL print(\u0026#34;跳转链接：\\(url)\u0026#34;) } return true } ","permalink":"https://blog.z6z8.cn/posts/ios/%E9%85%8D%E7%BD%AEapple-universal-links/","summary":"\u003ch1 id=\"配置网站\"\u003e配置网站\u003c/h1\u003e\n\u003ch2 id=\"创建-apple-app-site-association\"\u003e创建 apple-app-site-association\u003c/h2\u003e\n\u003cp\u003e在网站根目录或者 .well-known目录下创建 \u003ccode\u003eapple-app-site-association\u003c/code\u003e 文件。\u003ccode\u003e注意，文件没有后缀名\u003c/code\u003e。\n文件是一个json文件，内容如下：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;applinks\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;apps\u0026#34;\u003c/span\u003e: [],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;details\u0026#34;\u003c/span\u003e: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e\u0026#34;appID\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;团队ID.应用BundleID\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;paths\u0026#34;\u003c/span\u003e: [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/路径/*\u0026#34;\u003c/span\u003e] \n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e团队ID，和应用签名证书上的TeamId保存一致\u003c/li\u003e\n\u003cli\u003e路径 ，遵循url对应的规范，建议每一个App应用都使用独立的路径，便于管理\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"配置mime\"\u003e配置MIME\u003c/h2\u003e\n\u003cp\u003e因为apple-app-site-association 的数据格式是json，所有对应MIME类型：\u003ccode\u003eapplication/json\u003c/code\u003e。\u003c/p\u003e\n\u003cp\u003e在对应的站点配置文件里设置，以nginx为例:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-ini\" data-lang=\"ini\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 如果文件在根目录\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003elocation /apple-app-site-association {\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003edefault_type application/json;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 如果文件在.well-known目录\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003elocation /.well-known/apple-app-site-association {\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003edefault_type application/json;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"验证网站配置\"\u003e验证网站配置\u003c/h2\u003e\n\u003cp\u003e打开 \u003ca href=\"https://branch.io/resources/aasa-validator/\"\u003ehttps://branch.io/resources/aasa-validator/\u003c/a\u003e  ,  输入网站域名并验证配置是否正确。\u003c/p\u003e\n\u003ch2 id=\"关于缓存\"\u003e关于缓存\u003c/h2\u003e\n\u003cp\u003eApple会缓存apple-app-site-association文件内容，缓存未必及时更新（一般不超过48小时），所以有时候通过Universal Links打开App会失败。\u003c/p\u003e\n\u003cp\u003e打开 \u003ccode\u003ehttps://app-site-association.cdn-apple.com/a/v1/你的网站域名\u003c/code\u003e可以查看缓存内容\u003c/p\u003e\n\u003ch2 id=\"创建-universal-links网页\"\u003e创建 Universal Links网页\u003c/h2\u003e\n\u003cp\u003e还需要在网站部署一个 Universal Links网页。\u003cstrong\u003e网页的访问路径需要和apple-app-site-association文件中配置的路径一致\u003c/strong\u003e。\n当使用 Safari 浏览器打开Universal Links网页时，可唤起App。\u003c/p\u003e","title":"配置Apple Universal Links"},{"content":"一个因为swift name mangled符号不一致导致的错误：\ndispatch thunk of Alamofire.MultipartFormData.append(_: Foundation.Data, withName: Swift.String, fileName: Swift.String?, mimeType: Swift.String?) -\u0026gt; ()\u0026quot;, referenced from:\n先说工程结构 工程A有一个静态framework target a，通过cocoapods以源码方式集成了封装Alamofire，封装Alamofire的一些能力。\nworkspace A |____ a (源码) |____Alamofire （源码） 构建输出静态framework a。\n工程B有一个App Target，通过cocoapods以源码方式集成封装Alamofire，以静态库方式集成了 a。\nworkspace B ｜___App |____ a (静态库) |____ Alamofire （源码） ``` 在同一电脑，用同一个Xcode，设置了相同的swift version，结果App构建失败，找不到Alamofire里的符号。 经过一番观察，发现 \u0026#34;dispatch thunk of Alamofire.MultipartFormData.append(...)\u0026#34;是 Swift 编译器为带有默认参数、可变签名或需要方法桥接的函数生成的“thunk”符号。也就是说静态库a引用了这些由 Alamofire 生成的编译器私有符号，但最终链接器没有在任何被链接的库/框架中找到对应实现。 检查工程配置，首先排除Alamofire 的实现没有被链接到最终可执行文件（常见：静态库a引用但 App 没把 Alamofire 链接上）。 那么，最有可能的情况就是：工程B的Alamofire 与 工程A 使用不同的 Swift 编译环境/选项，导致 thunk 的名称/生成方式不一致，最终没有可匹配的符号。虽然Alamofire代码一摸一样，但是编译后的符号修饰方式不一样。 示意例子，例如同样是方法 test， 工程A中被修饰为 _$s12Alamofire4test tKF 工程B中被修饰为 $s12Alamofire4test_tKj\n有了排查方向，经过对比工程A和工程B的配置，最终发现cocoapods自动生成target Alamofire的配置有些许不一致 Build Libraries for Distribution 这个配置不一样，一个是YES，一个是NO。 又经实验，发现如果依赖Alamofire的target的 Build Libraries for Distribution 配置为YES，那么cocoapods自动生成的Alamofire对应的配置也是YES。 最后，只要将Alamofire对应Build Libraries for Distribution设置为NO（保持一致）就解决了Undefined symbols问题。 ","permalink":"https://blog.z6z8.cn/2026/01/23/undefined-symbols-dispatch-thunk/","summary":"\u003cp\u003e一个因为swift name mangled符号不一致导致的错误：\u003c/p\u003e\n\u003cp\u003edispatch thunk of Alamofire.MultipartFormData.append(_: Foundation.Data, withName: Swift.String, fileName: Swift.String?, mimeType: Swift.String?) -\u0026gt; ()\u0026quot;, referenced from:\u003c/p\u003e\n\u003cp\u003e先说工程结构\n工程A有一个静态framework target a，通过cocoapods以源码方式集成了封装Alamofire，封装Alamofire的一些能力。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e workspace A\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e              |____ a (源码)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e              |____Alamofire （源码）\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e构建输出静态framework a。\u003c/p\u003e\n\u003cp\u003e工程B有一个App Target，通过cocoapods以源码方式集成封装Alamofire，以静态库方式集成了 a。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e workspace B\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e             ｜___App\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                      |____ a (静态库)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                      |____ Alamofire （源码）\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e ```\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e 在同一电脑，用同一个Xcode，设置了相同的swift version，结果App构建失败，找不到Alamofire里的符号。\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e经过一番观察，发现 \u0026#34;dispatch thunk of Alamofire.MultipartFormData.append(...)\u0026#34;是 Swift 编译器为带有默认参数、可变签名或需要方法桥接的函数生成的“thunk”符号。也就是说静态库a引用了这些由 Alamofire 生成的编译器私有符号，但最终链接器没有在任何被链接的库/框架中找到对应实现。\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e 检查工程配置，首先排除Alamofire 的实现没有被链接到最终可执行文件（常见：静态库a引用但 App 没把 Alamofire 链接上）。\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e那么，最有可能的情况就是：工程B的Alamofire 与 工程A  使用不同的 Swift 编译环境/选项，导致 thunk 的名称/生成方式不一致，最终没有可匹配的符号。虽然Alamofire代码一摸一样，但是编译后的符号修饰方式不一样。\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e示意例子，例如同样是方法 test，\n工程A中被修饰为 _$s12Alamofire4test \u003cem\u003etKF\u003c/em\u003e\n\u003cem\u003e工程B中被修饰为\u003c/em\u003e $s12Alamofire4test_tKj\u003c/p\u003e","title":"Undefined symbols ... dispatch thunk"},{"content":"签发类型 根据签发机构类型，TLS证书签发可以划分为两种：\n公信CA（Certificate Authority）签发的证书（如DigiCert、Let’s Encrypt、Sectigo等） 企业内部私有CA签发的证书。 公信CA签发与企业内部私有CA签发，两者的区别是公信力不同。一般情况下，互联网环境不应信任企业内部私有CA签发的证书。\n下面主要详细说明最常见的 公信CA签发域名验证（DV）、组织验证（OV）、扩展验证（EV）证书的过程，以及全网最流行的免费证书Let’s Encrypt为例的自动化流程。\n公信CA签发证书的通用流程（DV/OV/EV） 生成CSR（Certificate Signing Request，证书签名请求）\n在你的服务器上首先生成一对密钥：私钥（private key）和公钥（public key）。\n使用私钥生成CSR文件，CSR里包含了：\n域名（Common Name 或 SAN 列表） 组织信息（OV/EV证书需要） 公钥 国家、省份、城市、公司名称等（OV/EV需要） 常用命令（OpenSSL）：\nopenssl req -new -newkey rsa:2048 -nodes -keyout domain.key -out domain.csr 选择CA并提交申请\n登录CA官网（或通过ACME协议自动化），选择证书类型（DV/OV/EV）、有效期。 上传CSR（或者有些CA让你直接在网页填写信息后帮你生成）。 域名控制权验证（DCV，Domain Control Validation）\n这是所有公信证书都必须完成的步骤，证明你确实控制这个域名。常见三种方式：\nHTTP验证（最常见）：CA给你一段随机token，你需要在域名下 .well-known/acme-challenge/ 路径放一个特定文件\n示例： http://yourdomain.com/.well-known/acme-challenge/xxxxxx\nDNS验证：CA给你一段TXT记录，你需要在域名DNS管理面板添加 _acme-challenge.yourdomain.com TXT \u0026ldquo;xxxxxx\u0026rdquo;\nEmail验证（较少用）：给域名whois邮箱或管理员邮箱（如admin@、webmaster@）发邮件，点链接确认\nDV证书只做这一步；OV/EV还要额外验证组织合法性。\n（OV/EV专属）组织信息验证 核实公司工商注册信息（通过第三方数据库如Dun \u0026amp; Bradstreet） 核实营业执照、法人身份 电话回访确认申请人身份和授权 验证域名管理权归属公司（whois + 额外证明文件） CA签发证书 CA用自己的中间证书或根证书的私钥，对你的公钥+域名+有效期等信息进行签名，生成证书文件（.crt 或 .pem） 同时会下发CA链证书（中间证书 bundle,参考下面附录） 下载并安装证书 你把证书、公钥、私钥安装到Web服务器（Nginx/Apache/IIS等） 重启服务，以使证书生效 最常见的自动化签发：Let’s Encrypt（ACME协议） Let’s Encrypt是目前全球使用量最大的免费CA，90天有效期，完全自动化。\n常用客户端：Certbot、acme.sh、win-acme、lego 等。以acme.sh为例的全自动流程：\n# 1. 安装acme.sh curl https://get.acme.sh | sh # 2. 切换到Let’s Encrypt（默认就是） acme.sh --set-default-ca --server letsencrypt # 3. 签发证书（两种主流验证方式任选其一） # 方法A：HTTP验证（需要80端口开放） acme.sh --issue -d example.com -d www.example.com --webroot /var/www/html # 方法B：DNS验证（推荐，停机也可续期） acme.sh --issue -d example.com --dns dns_cf # 以Cloudflare为例，会自动调用API添加TXT记录 # 4. 安装证书到Nginx/Apache acme.sh --install-cert -d example.com \\ --key-file /etc/nginx/ssl/example.key \\ --fullchain-file /etc/nginx/ssl/example.cer \\ --reloadcmd \u0026#34;nginx -s reload\u0026#34; 整个过程几秒到几十秒完成，无需人工干预，每60天自动续期。\n证书签发后链路示意 用户浏览器 ←HTTPS→ 你的服务器（证书+私钥） ↑ 验证链： 你的证书 → CA中间证书 → 根证书（已预装在操作系统/浏览器中） 总结对比表 类型验证内容签发时间有效期价格典型用途DV证书仅域名控制权几秒几分钟90天1年免费几百元普通网站、博客OV证书域名+组织合法性15个工作日12年几百几千元企业官网、电商EV证书域名+严格组织验证510个工作日12年千元以上银行、金融、大型电商Let’s Encrypt域名控制权（DV）几秒~1分钟90天完全免费绝大多数互联网网站\n附录：CA链证书 简单来说： CA链证书就是“中间证书”，它是连接你的网站证书和浏览器信任的根证书之间的“桥梁”。如果没有正确安装链证书，用户访问你的HTTPS网站时就会报错（最常见的是“NET::ERR_CERT_AUTHORITY_INVALID”或“证书不受信任”）。\n为什么需要链证书？（信任链原理） 为什么公信CA（包括Let’s Encrypt、DigiCert、GlobalSign等） 坚决不直接用根证书私钥（Root Private Key）去签发终端用户证书？原因非常明确，一共就这几条，但每一条都是致命的：\n理由如果直接用根私钥签发终端证书，后果会怎样？真实案例（已经发生过）1. 根私钥一旦泄露，整个生态瞬间崩塌攻击者可以随意给自己或任何人签发 看起来100%合法 的证书，伪造全球任意网站（银行、Google、苹果等），MITM攻击无法被发现。全球数亿网站同时不安全。2011年 DigiNotar（荷兰CA）根私钥被伊朗黑客盗取 → 伪造了Google、Yahoo、WordPress等500+证书 → 整个CA直接破产，被所有浏览器永久拉黑。\n2015年 Symantec不当签发测试证书 → 根信任被Chrome逐步移除。2. 根私钥必须永久离线，日常无法使用根私钥通常保存在 物理保险柜 + HSM硬件安全模块 + 多方仪式 中，启动一次需要多位高管同时到场、插多把实体钥匙。根本不可能每天拿来签发几十万张证书。Let’s Encrypt的根ISRG Root X1从2015年生成后，私钥就再也没有在联网设备上出现过。3. 根证书撤销几乎不可能如果根被污染，唯一办法是让所有浏览器和操作系统 永久移除这个根，代价极其高昂（用户需要升级系统/浏览器）。而中间证书被污染，只需要撤销那一个中间证书就行，影响面小1000倍。2024年有人发现某个小CA的中间证书被滥用，浏览器只撤销了那张中间证书，用户几乎无感知。4. 可以灵活撤销和轮换中间证书可以15年更换一次（Let’s Encrypt中间证书就换过好几次），根证书却要用2030年。出了问题只换中间就行，不影响根的长期信任。DigiCert、GlobalSign每年都会轮换若干中间证书，就是为了降低风险。5. 符合国际标准和浏览器强制要求Baseline Requirements（CA/Browser Forum规定）和所有主流浏览器（Chrome、Firefox、Safari、Edge） 明确禁止 根私钥直接签发终端实体证书，违反者直接除根。任何被发现直接用根签终端证书的CA，会在几天内被所有浏览器除根（等于商业死亡）。\n所以现代公信CA为了安全， 绝不直接用根证书私钥去签发终端用户证书，而是采用分层结构：\n根证书（Root CA） └── 中间证书1（Intermediate CA） ← CA用根私钥签发 └── 中间证书2（Intermediate CA） ← 用中间1签发 └── 你的网站证书（Leaf Certificate） ← 用中间2签发 根证书：预装在操作系统和浏览器里（DigiCert、GlobalSign、Let’s Encrypt的根叫ISRG Root X1等），数量很少，私钥离线保存在保险柜里，几乎永不使用。 中间证书：CA用根私钥签发的证书，中间证书的私钥才真正用来签发你的网站证书。 你的网站证书（叶子证书）：只包含你的域名和公钥。 浏览器验证证书时会沿着这条链一层层往上验证，直到找到自己信任的根证书为止。\n实际拿到的证书文件通常有这几种 你的网站证书（也叫leaf证书、end-entity证书）\n文件名通常是： yourdomain.crt、 yourdomain.pem、 certificate.crt\n链证书 / 中间证书（最重要的就是这个）\n可能有1~3个中间证书串在一起，常见文件名：\nchain.crt、 ca-bundle.crt、 intermediate.crt、 fullchain.pem 根证书（一般不需要你提供）\n浏览器自己有，不需要放在服务器上。\n如何撤销中间证书 中间证书（Intermediate CA）一旦被发现有安全问题、被滥用、私钥泄露、CA违规等，必须立即撤销。\n谁有权力、谁来执行撤销？ 角色职责发行该中间证书的根CA决定是否撤销、生成CRL或OCSP浏览器/操作系统厂商Chrome、Firefox、Microsoft、Apple、Mozilla 决定是否接受并强制执行CA/Browser Forum制定最晚撤销期限（通常5~7天）\n实际撤销的技术方式（都必须同时做） CRL（Certificate Revocation List，证书吊销列表） 根CA或上一级中间CA用自己的私钥签名一个列表，里面列出被撤销的证书序列号 文件通常放在 http://crl.exampleca.com/xxx.crl 缺点：体积大，浏览器很少真正下载检查（基本被淘汰） OCSP（Online Certificate Status Protocol，在线证书状态协议） 实时查询：浏览器问 OCSP Responder：“序列号为12345的证书还好吗？” 回应：Good / Revoked / Unknown 现在是主流，所有正规CA都必须提供OCSP服务 OCSP Must-Staple（强制 stapling） 证书签发时就加上一个扩展，要求服务器必须在TLS握手中附带OCSP响应 Let’s Encrypt、DigiCert 等主流CA默认都开启 一旦中间证书被撤销，所有使用该中间证书签发的网站都会立刻变红锁（几小时内） ","permalink":"https://blog.z6z8.cn/2025/12/10/tls%E8%AF%81%E4%B9%A6%E7%AD%BE%E5%8F%91%E6%B5%81%E7%A8%8B/","summary":"\u003ch1 id=\"签发类型\"\u003e签发类型\u003c/h1\u003e\n\u003cp\u003e根据签发机构类型，TLS证书签发可以划分为两种：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003cstrong\u003e公信CA（Certificate Authority）签发的证书\u003c/strong\u003e（如DigiCert、Let’s Encrypt、Sectigo等）\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e企业内部私有CA签发的证书\u003c/strong\u003e。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e公信CA签发与企业内部私有CA签发，两者的区别是公信力不同。一般情况下，互联网环境不应信任企业内部私有CA签发的证书。\u003c/p\u003e\n\u003cp\u003e下面主要详细说明最常见的 \u003cstrong\u003e公信CA签发域名验证（DV）、组织验证（OV）、扩展验证（EV）证书的过程\u003c/strong\u003e，以及全网最流行的免费证书Let’s Encrypt为例的自动化流程。\u003c/p\u003e\n\u003ch1 id=\"公信ca签发证书的通用流程dvovev\"\u003e公信CA签发证书的通用流程（DV/OV/EV）\u003c/h1\u003e\n\u003col\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e生成CSR（Certificate Signing Request，证书签名请求）\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e在你的服务器上首先生成一对密钥：私钥（private key）和公钥（public key）。\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e使用私钥生成CSR文件，CSR里包含了：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e域名（Common Name 或 SAN 列表）\u003c/li\u003e\n\u003cli\u003e组织信息（OV/EV证书需要）\u003c/li\u003e\n\u003cli\u003e公钥\u003c/li\u003e\n\u003cli\u003e国家、省份、城市、公司名称等（OV/EV需要）\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e常用命令（OpenSSL）：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eopenssl req -new -newkey rsa:2048 -nodes -keyout domain.key -out domain.csr\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e选择CA并提交申请\u003c/strong\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e登录CA官网（或通过ACME协议自动化），选择证书类型（DV/OV/EV）、有效期。\u003c/li\u003e\n\u003cli\u003e上传CSR（或者有些CA让你直接在网页填写信息后帮你生成）。\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003e域名控制权验证（DCV，Domain Control Validation）\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e这是所有公信证书都必须完成的步骤，证明你确实控制这个域名。常见三种方式：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eHTTP验证\u003c/strong\u003e（最常见）：CA给你一段随机token，你需要在域名下 \u003ccode\u003e.well-known/acme-challenge/\u003c/code\u003e 路径放一个特定文件\u003c/p\u003e\n\u003cp\u003e示例： \u003ca href=\"http://yourdomain.com/.well-known/acme-challenge/xxxxxx\"\u003ehttp://yourdomain.com/.well-known/acme-challenge/xxxxxx\u003c/a\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eDNS验证\u003c/strong\u003e：CA给你一段TXT记录，你需要在域名DNS管理面板添加 _acme-challenge.yourdomain.com TXT \u0026ldquo;xxxxxx\u0026rdquo;\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003cstrong\u003eEmail验证\u003c/strong\u003e（较少用）：给域名whois邮箱或管理员邮箱（如admin@、webmaster@）发邮件，点链接确认\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003cp\u003eDV证书只做这一步；OV/EV还要额外验证组织合法性。\u003c/p\u003e\n\u003col\u003e\n\u003cli\u003e\u003cstrong\u003e（OV/EV专属）组织信息验证\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003e核实公司工商注册信息（通过第三方数据库如Dun \u0026amp; Bradstreet）\u003c/li\u003e\n\u003cli\u003e核实营业执照、法人身份\u003c/li\u003e\n\u003cli\u003e电话回访确认申请人身份和授权\u003c/li\u003e\n\u003cli\u003e验证域名管理权归属公司（whois + 额外证明文件）\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003eCA签发证书\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003eCA用自己的中间证书或根证书的私钥，对你的公钥+域名+有效期等信息进行签名，生成证书文件（.crt 或 .pem）\u003c/li\u003e\n\u003cli\u003e同时会下发CA链证书（中间证书 bundle,参考下面附录）\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003cli\u003e\u003cstrong\u003e下载并安装证书\u003c/strong\u003e\n\u003cul\u003e\n\u003cli\u003e你把证书、公钥、私钥安装到Web服务器（Nginx/Apache/IIS等）\u003c/li\u003e\n\u003cli\u003e重启服务，以使证书生效\u003c/li\u003e\n\u003c/ul\u003e\n\u003c/li\u003e\n\u003c/ol\u003e\n\u003ch2 id=\"最常见的自动化签发lets-encryptacme协议\"\u003e最常见的自动化签发：Let’s Encrypt（ACME协议）\u003c/h2\u003e\n\u003cp\u003eLet’s Encrypt是目前全球使用量最大的免费CA，90天有效期，完全自动化。\u003c/p\u003e","title":"TLS证书签发流程"},{"content":"后端登录模块常见的校验策略（以安全为首要目标），从输入校验到风控防御，通常会分多层实现，以下是生产环境中广泛采用的实战校验策略汇总：\n1. 基础参数校验（最基本的一道防线） 用户名/手机号/邮箱：非空、格式正则、长度限制、防注入（预编译语句或ORM自动处理） 密码：非空、长度（通常8-32位）、不能包含用户名等 验证码（图片/短信/邮箱）：非空、长度固定、是否过期（通常60-300秒） 请求必传字段完整性（deviceId、timestamp、sign等） 2. 账号状态校验 账号是否存在 账号是否被禁用/冻结/注销 账号是否需要强制修改密码（首次登录、密码过期） 账号是否被加入黑名单 3. 密码相关安全校验 密码明文传输 → 必须强制HTTPS 密码加密传输（前端通常用RSA或SM2加密，后端私钥解密） 后端密码存储：bcrypt、scrypt、Argon2（加盐，绝不用MD5/SHA1明盐） 密码输错次数限制（单账号5-10次后锁定30分钟~永久，需要人工解封） 密码复杂度策略（可选：大小写+数字+特殊字符） 4. 验证码多重校验（防止暴力破解） 图片验证码：防自动化脚本 短信/邮箱验证码：限流（同一手机号/IP/设备1分钟1条，1小时5条，24小时10条） 验证码有效期 + 只能使用一次 验证码输错次数限制（3-5次后需要重新获取） 5. 登录风控与异常检测（核心防爆破、防薅羊毛） 同一账号短时间内多次登录失败次数超限 → 锁定 同一IP短时间内大量不同账号登录失败 → IP封禁 同一设备（deviceId/deviceFingerprint）短时大量账号尝试 → 设备封禁 异地登录检测（根据IP归属地，与历史登录地对比，差距\u0026gt;1000km触发二次验证） 短时间内大规模登录请求 → 触发全局限流或人工介入 用户代理（User-Agent）异常或频繁切换 无头浏览器、模拟器、爬虫特征检测 6. 会话安全策略 登录成功后颁发token（推荐无状态JWT，或服务端Session+Redis） JWT需设置合理过期时间（accessToken 15min ~ 2h，refreshToken 7 ~ 30天） 支持单点登录（同账号新登录踢掉旧设备） 支持多端互踢配置（Web端登录踢掉App等） 敏感操作二次验证（修改密码、支付等需重新输入密码或验证码） 7. 常见辅助安全措施 登录接口全局限流（令牌桶/漏桶算法，如QPS\u0026gt;500触发降级） 关键日志记录安全审计日志（登录IP、设备、时间、结果等） 登录成功后下发设备绑定关系（可用于后续风控） 支持可信设备管理（记住设备30天免二次验证） 密码传输前端可使用RSA/SM2非对称加密，或使用SRP协议（密码永不离客户端） 8. 特殊场景校验 第三方登录（微信、QQ、Apple）：校验state防CSRF，校验code是否已被使用 无密码登录（短信登录）：必须绑定手机号 + 短信验证码 + 设备风控 扫码登录：防钓鱼站点、心跳保活、状态机严格校验 推荐的实战分层校验伪代码结构（Java/SpringBoot示例） @PostMapping(\u0026#34;/login\u0026#34;) public Result login(@RequestBody LoginDTO dto) { // 1. 基础参数校验 validateParams(dto); // 2. 验证码校验 captchaService.check(dto.getCaptchaId(), dto.getCode()); // 3. 风控预检（IP、设备、全球限流） riskControl.preCheck(dto); // 4. 账号状态与密码校验 User user = userService.checkAccountAndPassword(dto); // 5. 登录风控后置（异地、异常检测） riskControl.afterLogin(user, request); // 6. 生成token并记录登录日志 String token = jwtUtil.createToken(user); loginLogService.asyncSave(user, request, true); return Result.ok(token); } 总结：现代后端登录模块已远不止“用户名+密码正确就放行”，而是一整套“参数→验证码→风控→账号状态→密码→二次验证→会话管理→日志”的立体防御体系。缺任何一层都可能被拖库、撞库、短信轰炸、羊毛党攻破。\n如果你的项目体量较大，强烈建议引入专业的风控系统（如阿里云滑块验证码、网易易盾、同盾、ThreatBook等）或自研设备指纹+行为分析能力。\n","permalink":"https://blog.z6z8.cn/2025/12/08/%E5%90%8E%E7%AB%AF%E7%99%BB%E9%99%86%E6%A8%A1%E5%9D%97%E5%B8%B8%E8%A7%81%E7%9A%84%E6%A0%A1%E9%AA%8C%E7%AD%96%E7%95%A5/","summary":"\u003cp\u003e后端登录模块常见的校验策略（以安全为首要目标），从输入校验到风控防御，通常会分多层实现，以下是生产环境中广泛采用的实战校验策略汇总：\u003c/p\u003e\n\u003ch3 id=\"1-基础参数校验最基本的一道防线\"\u003e1. 基础参数校验（最基本的一道防线）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e用户名/手机号/邮箱：非空、格式正则、长度限制、防注入（预编译语句或ORM自动处理）\u003c/li\u003e\n\u003cli\u003e密码：非空、长度（通常8-32位）、不能包含用户名等\u003c/li\u003e\n\u003cli\u003e验证码（图片/短信/邮箱）：非空、长度固定、是否过期（通常60-300秒）\u003c/li\u003e\n\u003cli\u003e请求必传字段完整性（deviceId、timestamp、sign等）\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"2-账号状态校验\"\u003e2. 账号状态校验\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e账号是否存在\u003c/li\u003e\n\u003cli\u003e账号是否被禁用/冻结/注销\u003c/li\u003e\n\u003cli\u003e账号是否需要强制修改密码（首次登录、密码过期）\u003c/li\u003e\n\u003cli\u003e账号是否被加入黑名单\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"3-密码相关安全校验\"\u003e3. 密码相关安全校验\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e密码明文传输 → 必须强制HTTPS\u003c/li\u003e\n\u003cli\u003e密码加密传输（前端通常用RSA或SM2加密，后端私钥解密）\u003c/li\u003e\n\u003cli\u003e后端密码存储：bcrypt、scrypt、Argon2（加盐，绝不用MD5/SHA1明盐）\u003c/li\u003e\n\u003cli\u003e密码输错次数限制（单账号5-10次后锁定30分钟~永久，需要人工解封）\u003c/li\u003e\n\u003cli\u003e密码复杂度策略（可选：大小写+数字+特殊字符）\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"4-验证码多重校验防止暴力破解\"\u003e4. 验证码多重校验（防止暴力破解）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e图片验证码：防自动化脚本\u003c/li\u003e\n\u003cli\u003e短信/邮箱验证码：限流（同一手机号/IP/设备1分钟1条，1小时5条，24小时10条）\u003c/li\u003e\n\u003cli\u003e验证码有效期 + 只能使用一次\u003c/li\u003e\n\u003cli\u003e验证码输错次数限制（3-5次后需要重新获取）\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"5-登录风控与异常检测核心防爆破防薅羊毛\"\u003e5. 登录风控与异常检测（核心防爆破、防薅羊毛）\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e同一账号短时间内多次登录失败次数超限 → 锁定\u003c/li\u003e\n\u003cli\u003e同一IP短时间内大量不同账号登录失败 → IP封禁\u003c/li\u003e\n\u003cli\u003e同一设备（deviceId/deviceFingerprint）短时大量账号尝试 → 设备封禁\u003c/li\u003e\n\u003cli\u003e异地登录检测（根据IP归属地，与历史登录地对比，差距\u0026gt;1000km触发二次验证）\u003c/li\u003e\n\u003cli\u003e短时间内大规模登录请求 → 触发全局限流或人工介入\u003c/li\u003e\n\u003cli\u003e用户代理（User-Agent）异常或频繁切换\u003c/li\u003e\n\u003cli\u003e无头浏览器、模拟器、爬虫特征检测\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"6-会话安全策略\"\u003e6. 会话安全策略\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e登录成功后颁发token（推荐无状态JWT，或服务端Session+Redis）\u003c/li\u003e\n\u003cli\u003eJWT需设置合理过期时间（accessToken 15min ~ 2h，refreshToken 7 ~ 30天）\u003c/li\u003e\n\u003cli\u003e支持单点登录（同账号新登录踢掉旧设备）\u003c/li\u003e\n\u003cli\u003e支持多端互踢配置（Web端登录踢掉App等）\u003c/li\u003e\n\u003cli\u003e敏感操作二次验证（修改密码、支付等需重新输入密码或验证码）\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"7-常见辅助安全措施\"\u003e7. 常见辅助安全措施\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e登录接口全局限流（令牌桶/漏桶算法，如QPS\u0026gt;500触发降级）\u003c/li\u003e\n\u003cli\u003e关键日志记录安全审计日志（登录IP、设备、时间、结果等）\u003c/li\u003e\n\u003cli\u003e登录成功后下发设备绑定关系（可用于后续风控）\u003c/li\u003e\n\u003cli\u003e支持可信设备管理（记住设备30天免二次验证）\u003c/li\u003e\n\u003cli\u003e密码传输前端可使用RSA/SM2非对称加密，或使用SRP协议（密码永不离客户端）\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"8-特殊场景校验\"\u003e8. 特殊场景校验\u003c/h3\u003e\n\u003cul\u003e\n\u003cli\u003e第三方登录（微信、QQ、Apple）：校验state防CSRF，校验code是否已被使用\u003c/li\u003e\n\u003cli\u003e无密码登录（短信登录）：必须绑定手机号 + 短信验证码 + 设备风控\u003c/li\u003e\n\u003cli\u003e扫码登录：防钓鱼站点、心跳保活、状态机严格校验\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch3 id=\"推荐的实战分层校验伪代码结构javaspringboot示例\"\u003e推荐的实战分层校验伪代码结构（Java/SpringBoot示例）\u003c/h3\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@PostMapping\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/login\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e Result \u003cspan style=\"color:#a6e22e\"\u003elogin\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003e@RequestBody\u003c/span\u003e LoginDTO dto) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 1. 基础参数校验\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    validateParams(dto);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 2. 验证码校验\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    captchaService.\u003cspan style=\"color:#a6e22e\"\u003echeck\u003c/span\u003e(dto.\u003cspan style=\"color:#a6e22e\"\u003egetCaptchaId\u003c/span\u003e(), dto.\u003cspan style=\"color:#a6e22e\"\u003egetCode\u003c/span\u003e());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 3. 风控预检（IP、设备、全球限流）\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    riskControl.\u003cspan style=\"color:#a6e22e\"\u003epreCheck\u003c/span\u003e(dto);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 4. 账号状态与密码校验\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    User user \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e userService.\u003cspan style=\"color:#a6e22e\"\u003echeckAccountAndPassword\u003c/span\u003e(dto);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 5. 登录风控后置（异地、异常检测）\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    riskControl.\u003cspan style=\"color:#a6e22e\"\u003eafterLogin\u003c/span\u003e(user, request);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 6. 生成token并记录登录日志\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    String token \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e jwtUtil.\u003cspan style=\"color:#a6e22e\"\u003ecreateToken\u003c/span\u003e(user);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    loginLogService.\u003cspan style=\"color:#a6e22e\"\u003easyncSave\u003c/span\u003e(user, request, \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e Result.\u003cspan style=\"color:#a6e22e\"\u003eok\u003c/span\u003e(token);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e总结：现代后端登录模块已远不止“用户名+密码正确就放行”，而是一整套“参数→验证码→风控→账号状态→密码→二次验证→会话管理→日志”的立体防御体系。缺任何一层都可能被拖库、撞库、短信轰炸、羊毛党攻破。\u003c/p\u003e","title":"后端登陆模块常见的校验策略"},{"content":"本文环境： hugo v0.152.2+extended+withdeploy darwin/amd64 BuildDate=2025-10-24T15:31:49Z VendorInfo=Homebrew\n一般使用了hugo主题的话，默认是集成了mermaid图。 若不使用hugo主题，那么就需要自己手动集成了。 步骤如下：\n创建 layouts/_markup/render-codeblock-mermaid.html 负责开启一个mermaid图的html区块，内容如下：\n\u0026lt;pre class=\u0026#34;mermaid\u0026#34;\u0026gt; {{- .Inner | safeHTML }} \u0026lt;/pre\u0026gt; {{ .Page.Store.Set \u0026#34;hasMermaid\u0026#34; true }} 修改 layouts/_default/baseof.html 如果没有该文件就创建一个。默认情况下，所有html页面的主体结构和内容由这个文件渲染。和mermaid图相关的内容如下:\n\u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html lang=\u0026#34;zh-CN\u0026#34;\u0026gt; \u0026lt;body\u0026gt; ...... ...... ...... \u0026lt;!-- 必须放到最后在 （.Content 之下），因为这渲染钩子直到执行 .Content 之后才会被处理），否则.Page.Store.Get \u0026#34;hasMermaid\u0026#34;永远为false --\u0026gt; {{ if .Page.Store.Get \u0026#34;hasMermaid\u0026#34; }} \u0026lt;!-- 只有文章里写了 mermaid 才加载下面这些资源，节省性能 --\u0026gt; \u0026lt;script type=\u0026#34;module\u0026#34;\u0026gt; import mermaid from \u0026#39;https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs\u0026#39;; mermaid.initialize({ startOnLoad: true }); \u0026lt;/script\u0026gt; {{ end }} \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; 添加一个mermaid图看看效果 在网站的任意一个markdown文件里添加样例，看下效果\n```mermaid flowchart LR %% 左右布局（TD=上下，LR=左右，TB=上下，BT=下上） Start[开始] --\u0026gt; Stop[结束] A[矩形节点] --\u0026gt; B(圆角矩形) C{菱形判断} --\u0026gt;|是| D[操作1] C --\u0026gt;|否| E[操作2] ","permalink":"https://blog.z6z8.cn/2025/12/01/%E5%9C%A8hugo%E9%87%8C%E9%9B%86%E6%88%90mermaid%E5%9B%BE%E6%94%AF%E6%8C%81/","summary":"\u003cp\u003e本文环境：\nhugo v0.152.2+extended+withdeploy darwin/amd64 BuildDate=2025-10-24T15:31:49Z VendorInfo=Homebrew\u003c/p\u003e\n\u003cp\u003e一般使用了hugo主题的话，默认是集成了mermaid图。\n若不使用hugo主题，那么就需要自己手动集成了。\n步骤如下：\u003c/p\u003e\n\u003ch2 id=\"创建-layouts_markuprender-codeblock-mermaidhtml\"\u003e创建 layouts/_markup/render-codeblock-mermaid.html\u003c/h2\u003e\n\u003cp\u003e负责开启一个mermaid图的html区块，内容如下：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003epre\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;mermaid\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {{- .Inner | safeHTML }}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;/\u003cspan style=\"color:#f92672\"\u003epre\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  {{ .Page.Store.Set \u0026#34;hasMermaid\u0026#34; true }}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"修改-layouts_defaultbaseofhtml\"\u003e修改 layouts/_default/baseof.html\u003c/h2\u003e\n\u003cp\u003e如果没有该文件就创建一个。默认情况下，所有html页面的主体结构和内容由这个文件渲染。和mermaid图相关的内容如下:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u0026lt;!DOCTYPE html\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003ehtml\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003elang\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;zh-CN\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   ......\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   ......\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   ......\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#75715e\"\u003e\u0026lt;!-- 必须放到最后在 （.Content 之下），因为这渲染钩子直到执行 .Content 之后才会被处理），否则.Page.Store.Get \u0026#34;hasMermaid\u0026#34;永远为false --\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       {{ if .Page.Store.Get \u0026#34;hasMermaid\u0026#34; }}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e\u0026lt;!-- 只有文章里写了 mermaid 才加载下面这些资源，节省性能 --\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;module\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emermaid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;https://cdn.jsdelivr.net/npm/mermaid/dist/mermaid.esm.min.mjs\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003emermaid\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003einitialize\u003c/span\u003e({ \u003cspan style=\"color:#a6e22e\"\u003estartOnLoad\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;/\u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {{ end }}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ehtml\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"添加一个mermaid图看看效果\"\u003e添加一个mermaid图看看效果\u003c/h2\u003e\n\u003cp\u003e在网站的任意一个markdown文件里添加样例，看下效果\u003c/p\u003e","title":"在hugo里集成mermaid图支持"},{"content":"前向安全 前向安全（Forward Secrecy，简称 PFS）是 TLS（以及其他加密协议）中一个非常重要的安全属性，简单来说： “即使攻击者将来拿到了服务器的长期私钥（即证书私钥），也无法解密之前已经完成的所有 TLS 会话” 这就是前向安全的核心意义：过去的通信记录永远是安全的，即使私钥彻底泄露。\n前向安全在TLS 1.3中强制开启的，安全性由 椭圆曲线离散对数问题（ECDLP） 保障\nECDH（椭圆曲线 Diffie-Hellman）最核心的数学原理 一句话就能说清楚： “乘法可以随便做，除法几乎做不出来”\n我们用最常用、最直观的曲线 X25519 / Curve25519 来解释（TLS 1.3 里 90% 以上用的就是它）。\n1. 公共参数（全世界都一样） 选定一个安全的椭圆曲线：y² = x³ + 486662x² + x（模 2²⁵⁵-19） 选定一个基点（base point）G，一个固定的点，坐标是已知的： G = (9, 447…)（具体数字不重要，只要大家用同一个就行） 2. 双方各自生成临时私钥（就是随机数） 爱丽丝（Alice，客户端）随机选一个 256 bit 的整数作为私钥：\na = 随机数（比如 3f1a…c2，绝对保密！）\n鲍勃（Bob，服务器）也随机选一个 256 bit 的整数：\nb = 随机数（比如 7d2b…e9，绝对保密！）\n3. 计算并公开“公钥”（其实就是把私钥乘以基点 G） 爱丽丝算出自己的临时公钥：\nA = a × G\n鲍勃算出自己的临时公钥：\nB = b × G\n这一步叫 标量乘法（scalar multiplication），很快就能算。\n4. 双方互换公钥（在网络上明文发送，没关系！） 爱丽丝把 A 发给鲍勃\n鲍勃把 B 发给爱丽丝\n5. 双方各自再做一次标量乘法，得到共享秘密 Z 爱丽丝算：Z = a × B 鲍勃算： Z = b × A 奇迹发生了：\na × B = a × (b × G) = (a × b) × G\nb × A = b × (a × G) = (b × a) × G\n因为乘法交换律，a×b = b×a，所以两个 Z 完全相等！\n这就是共享秘密 Z（32 字节）， 网络上从来没有传输过 Z，攻击者只看到 A 和 B。\n6. 为什么攻击者算不出 Z？（数学陷阱） 攻击者看到：\nG（公开） A = a × G（公开） B = b × G（公开） 他想求 Z = a × b × G\n→ 必须先从 A 求出 a，或者从 B 求出 b\n→ 这就是 椭圆曲线离散对数问题（ECDLP）\n目前人类最好的算法要花大约 2¹²⁸ 次运算才能破解 X25519（相当于 300 亿亿亿年），完全不可能。\n这就是“乘法容易，除法几乎做不出来”的本质。\n超级简化的数字比喻（虽然现实不是素数乘法，但帮助理解） 把椭圆曲线上的“点加”想象成普通乘法：\nG = 5（基点） 爱丽丝私钥 a = 7 鲍勃私钥 b = 13 爱丽丝发：A = 5⁷ = 78125\n鲍勃发：B = 5¹³ = 1220703125\n爱丽丝算：78125¹³ = 4038967834731580443708050254247865495926816947758197784423828125 鲍勃算：1220703125⁷ = 4038967834731580443708050254247865495926816947758197784423828125\n攻击者看到 78125 和 1220703125，想求出 7 或 13 ，也不容易。\n椭圆曲线只是把“指数”换成了“点加”，但数学难度被做得更高。\n总结：ECDH 全过程一句话 大家约定一个起点 G 各自用自己的私钥（随机数）把 G “乘”很多次得到公钥，公开交换 再把对方的公钥乘上自己的私钥，得到同一个共享秘密 Z 因为离散对数难题，谁也反推不出对方的私钥 → Z 永远安全 这就是 TLS 1.3 里每一次握手都能实现完美前向安全的数学根基。\n","permalink":"https://blog.z6z8.cn/2025/11/26/tls-1-3%E5%89%8D%E5%90%91%E5%AE%89%E5%85%A8%E7%9A%84%E9%80%9A%E4%BF%97%E8%A7%A3%E9%87%8A/","summary":"\u003ch1 id=\"前向安全\"\u003e前向安全\u003c/h1\u003e\n\u003cp\u003e前向安全（Forward Secrecy，简称 PFS）是 TLS（以及其他加密协议）中一个非常重要的安全属性，简单来说：\n“即使攻击者将来拿到了服务器的长期私钥（即证书私钥），也无法解密之前已经完成的所有 TLS 会话”\n这就是前向安全的核心意义：过去的通信记录永远是安全的，即使私钥彻底泄露。\u003c/p\u003e\n\u003cp\u003e前向安全在TLS 1.3中强制开启的，安全性由 \u003cstrong\u003e椭圆曲线离散对数问题（ECDLP）\u003c/strong\u003e 保障\u003c/p\u003e\n\u003ch1 id=\"ecdh椭圆曲线-diffie-hellman最核心的数学原理\"\u003eECDH（椭圆曲线 Diffie-Hellman）最核心的数学原理\u003c/h1\u003e\n\u003cp\u003e一句话就能说清楚： \u003cstrong\u003e“乘法可以随便做，除法几乎做不出来”\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e我们用最常用、最直观的曲线 \u003cstrong\u003eX25519 / Curve25519\u003c/strong\u003e 来解释（TLS 1.3 里 90% 以上用的就是它）。\u003c/p\u003e\n\u003ch4 id=\"1-公共参数全世界都一样\"\u003e1. 公共参数（全世界都一样）\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e选定一个安全的椭圆曲线：y² = x³ + 486662x² + x（模 2²⁵⁵-19）\u003c/li\u003e\n\u003cli\u003e选定一个基点（base point）G，一个固定的点，坐标是已知的：\nG = (9, 447…)（具体数字不重要，只要大家用同一个就行）\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"2-双方各自生成临时私钥就是随机数\"\u003e2. 双方各自生成临时私钥（就是随机数）\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e爱丽丝（Alice，客户端）随机选一个 256 bit 的整数作为私钥：\u003c/p\u003e\n\u003cp\u003ea = 随机数（比如 3f1a…c2，绝对保密！）\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e鲍勃（Bob，服务器）也随机选一个 256 bit 的整数：\u003c/p\u003e\n\u003cp\u003eb = 随机数（比如 7d2b…e9，绝对保密！）\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch4 id=\"3-计算并公开公钥其实就是把私钥乘以基点-g\"\u003e3. 计算并公开“公钥”（其实就是把私钥乘以基点 G）\u003c/h4\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e爱丽丝算出自己的临时公钥：\u003c/p\u003e\n\u003cp\u003eA = a × G\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e鲍勃算出自己的临时公钥：\u003c/p\u003e\n\u003cp\u003eB = b × G\u003c/p\u003e","title":"TLS 1.3前向安全的通俗解释"},{"content":"Xcode创建framework，选择语言Swift。在使用Swift语言编写framework时，如果要引入Objective-C的代码或者其他Objective-C的库，可能会报错“using bridging headers with module interfaces is unsupported”。这通常是因为在模块接口中使用了桥接头文件(bridging-header)，而这是不被支持的，\n一般有两种解决办法：\n一、如果这个framework不需要对外发布，那么将Build Setting里的Build Library For Distrubution 设置为NO，则可以继续使用桥接头文件(bridging-header)。\n二、使用module map文件替换桥接头文件(bridging-header)，具体操作如下：\n1、在framework工程里创建一个头文件，如 Test.h 在Build Setting里设置User Header Search Paths，如 $(SRCROOT)/$(PRODUCT_NAME)。设置的路径需要能找到 Test.h 文件\n2、在 Test.h 文件里引入需要引用的Objective-C头文件\n#import \u0026lt;MyLib/MyLib.h\u0026gt; 3、创建一个module map文件, module.modulemap，内容如下\nmodule TestModule (名字自定义) { header \u0026#34;Test.h\u0026#34; export * } 4、在Swift文件里，使用import指令，然后就可以调用Objective-C的方法了\nimport TestModule ","permalink":"https://blog.z6z8.cn/2025/09/26/using-bridging-headers-with-module-interfaces-is-unsupported/","summary":"\u003cp\u003eXcode创建framework，选择语言Swift。在使用Swift语言编写framework时，如果要引入Objective-C的代码或者其他Objective-C的库，可能会报错“using bridging headers with module interfaces is unsupported”。这通常是因为在模块接口中使用了桥接头文件(bridging-header)，而这是不被支持的，\u003c/p\u003e\n\u003cp\u003e一般有两种解决办法：\u003c/p\u003e\n\u003cp\u003e一、如果这个framework不需要对外发布，那么将Build Setting里的Build Library For Distrubution 设置为NO，则可以继续使用桥接头文件(bridging-header)。\u003c/p\u003e\n\u003cp\u003e二、使用module map文件替换桥接头文件(bridging-header)，具体操作如下：\u003c/p\u003e\n\u003cp\u003e1、在framework工程里创建一个头文件，如 \u003ccode\u003eTest.h\u003c/code\u003e\n在Build Setting里设置User Header Search Paths，如 \u003ccode\u003e$(SRCROOT)/$(PRODUCT_NAME)\u003c/code\u003e。设置的路径需要能找到 \u003ccode\u003eTest.h\u003c/code\u003e 文件\u003c/p\u003e\n\u003cp\u003e2、在 \u003ccode\u003eTest.h\u003c/code\u003e 文件里引入需要引用的Objective-C头文件\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#import \u0026lt;MyLib/MyLib.h\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e3、创建一个module map文件, \u003ccode\u003emodule.modulemap\u003c/code\u003e，内容如下\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emodule  TestModule (\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e名字自定义\u003c/span\u003e)  {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    header \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Test.h\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e4、在Swift文件里，使用import指令，然后就可以调用Objective-C的方法了\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eimport  TestModule\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"using bridging headers with module interfaces is unsupported"},{"content":"默认创建的使用Swift语言编写的framework是没有头文件的，如果另一个使用Objective-C语言编写的target想用引入swift framework，则需要在swift framework的工程上打开一些配置\n同时使用public 和 @objc标记 要给Objective-C暴露swift编写的api，则需要使用public 和 @objc标记\n@objc public class MySwiftClass: NSObject { @objc public func doSomething() { print(\u0026#34;Doing something in Swift\u0026#34;) } } 生成 Objective-C 兼容头文件 Swift Framework 的 Build Settings 中：\nDefines Module 设置为 YES。 Install Generated Header 设置为 YES。 这会生成一个 FrameworkName-Swift.h 头文件，包含 Swift 代码的 Objective-C 接口。 在 Objective-C 项目中导入导入 Swift Framework 的头文件 #import \u0026lt;FrameworkName/FrameworkName-Swift.h\u0026gt; MySwiftClass *swiftObject = [[MySwiftClass alloc] init]; [swiftObject doSomething]; ","permalink":"https://blog.z6z8.cn/2025/09/24/%E5%88%9B%E5%BB%BAobjective-c%E5%8F%AF%E4%BD%BF%E7%94%A8%E7%9A%84swift-framework/","summary":"\u003cp\u003e默认创建的使用Swift语言编写的framework是没有头文件的，如果另一个使用Objective-C语言编写的target想用引入swift framework，则需要在swift framework的工程上打开一些配置\u003c/p\u003e\n\u003ch1 id=\"同时使用public-和-objc标记\"\u003e同时使用public 和 @objc标记\u003c/h1\u003e\n\u003cp\u003e要给Objective-C暴露swift编写的api，则需要使用public 和 @objc标记\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-swift\" data-lang=\"swift\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@objc\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMySwiftClass\u003c/span\u003e: NSObject {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003e@objc\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edoSomething\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        print(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Doing something in Swift\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"生成-objective-c-兼容头文件\"\u003e生成 Objective-C 兼容头文件\u003c/h1\u003e\n\u003cp\u003eSwift Framework 的 Build Settings 中：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eDefines Module 设置为 YES。\u003c/li\u003e\n\u003cli\u003eInstall Generated Header 设置为 YES。\n这会生成一个 FrameworkName-Swift.h 头文件，包含 Swift 代码的 Objective-C 接口。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"在-objective-c-项目中导入导入-swift-framework-的头文件\"\u003e在 Objective-C 项目中导入导入 Swift Framework 的头文件\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#import \u0026lt;FrameworkName/FrameworkName-Swift.h\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eMySwiftClass \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eswiftObject \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[MySwiftClass alloc] init];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[swiftObject doSomething];\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"创建Objective-C可使用的Swift Framework"},{"content":"前言 本文成文环境：\nmacOS 26 Xcode 26 以及 iOS SDK Android Studio MeerKat Feature Drop 以及 Android SDK、NDK JDK 17 Gradle 8.11.1 Kotlin Multiplatfrom 通过Cinterop工具调用C/C++方法，也可以通过JNI规范调用C/C++方法。\n本质上，都是调用C方法，C++方法需要通过 extern \u0026quot;C\u0026quot; 修饰为C方法。\n本文将介绍Kotlin/Native在Android和iOS环境，如何调用C/C++方法。\nAndroid Studio 推荐使用 Android Studio 开发Kotlin/Native （Kotlin更像是一款Android开发语言）\nGradle Android Studio的御用构建工具（相比其构建工具，复杂且难用）\nCMake 一个事实上的C/C++构建标准工具，在Android和iOS环境调用各自平台的工具链构建C/C++。\n创建 Kotlin Multiplatfrom 工程 如果Android Studio没有 Kotlin Multiplatfrom 工程模版，则需要先安装 Kotlin Multiplatfrom插件。 安装完成后，使用 Kotlin Multiplatfrom 工程模版创建一个工程（创建过程中，需要选择iOS的包管理方式，选择cocoapods）\n镜像 因为环大陆的网络墙问题，可能需要配置下镜像仓库\n1、找到工程根目录下的 settings.gradle.kts,添加下镜像仓库（下面配置的是阿里云的maven仓库）\n// settings.gradle.kts pluginManagement { repositories { maven{ setUrl(\u0026#34;https://maven.aliyun.com/repository/public\u0026#34;) } maven{ setUrl(\u0026#34;https://maven.aliyun.com/repository/central\u0026#34;) } maven{ setUrl(\u0026#34;https://maven.aliyun.com/repository/gradle-plugin\u0026#34;) } ... ... ... } } dependencyResolutionManagement { repositories { maven{ setUrl(\u0026#34;https://maven.aliyun.com/repository/public\u0026#34;) } maven{ setUrl(\u0026#34;https://maven.aliyun.com/repository/central\u0026#34;) } maven{ setUrl(\u0026#34;https://maven.aliyun.com/repository/gradle-plugin\u0026#34;) } ... ... ... } } 2、找到根目录下 gradle/wrapper/gradle-wrapper.properties，替换为distributionUrl\n#gradle/wrapper/gradle-wrapper.properties #distributionUrl=https\\://services.gradle.org/distributions/gradle-8.11.1-bin.zip distributionUrl=https\\://mirrors.cloud.tencent.com/gradle/gradle-8.11.1-all.zip bin是二进制工具，all包含二进制和源码，gradle工具构建时可能会下载源码。\n修改shared模块 默认情况下，创建的工程会有一个shared模块 展开后，可以看到src目录下有androidMain、commonMain、iosMain\n使用Android Studio在shared模块中添加C/C++（鼠标右键选中shared模块，Add C/C++ to Module），这样就添加了Android Native相关代码,目录如下:\nshared |_src |_commonMain (通用方法) |_kotlin |_com.example.kmpapptest(包名) |_Platform.kt |_androidMain (android平台相关的方法) |_kotlin |_com.example.kmpapptest(包名) |_Platform.android.kt |_iosMain (ios平台相关的方法) |_kotlin |_com.example.kmpapptest(包名) |_Platform.ios.kt |_main (C/C++方法) |_cpp |_CMakeLists.txt (Android so构建配置) |_main.cpp 因为我们使用的Android Studio的 Add C/C++ to Module 菜单创建的C/C++目录，所以在shared模块的build.gradle.kts里会自动添加Android平台的JNI构建任务\nandroid { ... defaultConfig { ... externalNativeBuild { cmake { cppFlags += \u0026#34;\u0026#34; } } ... } ... externalNativeBuild { cmake { path = file(\u0026#34;src/main/cpp/CMakeLists.txt\u0026#34;) version = \u0026#34;3.22.1\u0026#34; } } ... } expect/actual kotlin关键字 expect 用来声明方法， actul 标记实现方法。\n我们在commonMain 中的 Platform.kt 声明(expect)一个 get_native_message() 方法\n// shared/src/commonMain/kotlin/com/example/kmpapptest/Platform.kt package com.example.kmpapptest expect fun get_native_message(): string 在androidMain和iOSmain各自实现(actual)这个 get_native_message 方法\n// shared/src/androidMain/kotlin/com/example/kmpapptest/Platform.kt package com.example.kmpapptest actual fun get_native_message(): String{ return AndroidNativeLib.stringFromJNI() } class AndroidNativeLib { companion object { external fun stringFromJNI() : String init { System.loadLibrary(\u0026#34;android-native-lib\u0026#34;) } } } // shared/src/iosMain/kotlin/com/example/kmpapptest/Platform.kt package com.example.kmpapptest import kotlinx.cinterop.toKString @kotlinx.cinterop.ExperimentalForeignApi actual fun get_native_message(): String{ return iosNativeLib.get_message()?.toKString().toString() } Kotlin通过JNI在Android环境调用C/C++方法 再来回顾下 AndroidNativeLib 的 stringFromJNI 方法\npackage com.example.kmpapptest class AndroidNativeLib { companion object { external fun stringFromJNI() : String init { System.loadLibrary(\u0026#34;android-native-lib\u0026#34;) } } } 在C/C++侧，对应的方法名为 Java_com_example_kmpapptest_AndroidNativeLib_00024Companion_stringFromJNI\nkotlin方法名和C/C++方法的对应规则: 1、Java_包名_类名_方法名 2、Java_包名_方法名 3、Java_包名_类名_00024Companion_方法名\n\u0026ldquo;00024Companion\u0026rdquo; 是 \u0026ldquo;$Companion\u0026rdquo; 的转译字符串\n在 shared//src/main/cpp/main.cpp 中添加对应方法\n//shared/src/main/cpp/main.cpp #include \u0026lt;jni.h\u0026gt; extern \u0026#34;C\u0026#34; JNIEXPORT jstring JNICALL Java_com_example_kmpapptest_NativeLib_00024Companion_stringFromJNI(JNIEnv * env , jobject thiz) { return env-\u0026gt;NewStringUTF(\u0026#34;test_kotlin_call_android_native\u0026#34;); } 修改 shared/src/main/cpp/CMakeLists.txt\n... project(\u0026#34;android-native-lib\u0026#34;) # 这里的名字要和AndroidNativeLib类加载的lib库名对应 ... 到这里，可以运行 androidApp 看下效果\nKotlin通过Cinterop在iOS环境调用C/C++方法 在 shared/main/ 创建 cinterop/CMakeLists.txt, cinterop/ios_cmake.sh， cinterop/ios.cpp, cinterop/ios.h， cinterop/ios.def\nshared |_src |_main (C/C++方法) |_cinterop |_CMakeLists.txt (ios lib 构建配置) |_ios_cmake.sh (cmake构建具体命令) |_ios.h (方法声明) |_ios.cpp (方法实现) |_ios.def (暴露给kotlin的方法定义文件) 方法声明和实现 //shared/src/main/cinterop/ios.h #ifndef TEST_SHARED_IOS_H #define TEST_SHARED_IOS_H #if defined(__cplusplus) extern \u0026#34;C\u0026#34; { #endif const char *get_message(void); #if defined(__cplusplus) } #endif #endif //TEST_SHARED_IOS_H //shared/src/main/cinterop/ios.cpp #include \u0026#34;ios.h\u0026#34; extern \u0026#34;C\u0026#34; const char *get_message(void) { return \u0026#34;cinterop_test_kotlin_call_ios_native\u0026#34;; } CMakeLists.txt 和 ios_cmake.sh 编辑 shared/src/main/cinterop/CMakeLists.txt\n# shared/src/main/cinterop/CMakeLists.txt # Sets the minimum CMake version required for this project. cmake_minimum_required(VERSION 3.22.1) # 编译模块名 产物为libnative-lib project(\u0026#34;native-lib\u0026#34;) # 设置系统环境 set(CMAKE_SYSTEM_NAME iOS) # 设置cpu arch set(CMAKE_OSX_ARCHITECTURES arm64 x86_64) # 指定头文件目录 include_directories(${CMAKE_SOURCE_DIR}) # 收集所有 源文件 file(GLOB SOURCES ${CMAKE_SOURCE_DIR}/*.cpp ) add_library(${CMAKE_PROJECT_NAME} STATIC # List C/C++ source files with relative paths to this CMakeLists.txt. ${SOURCES}) 编辑 shared/src/main/cinterop/ios_cmake.sh\n# 产物输出目录 (外面传入参数) build_output_dir=$1 # 根据CMakeLists.txt生产构建配置信息，如makefile cmake . -B $build_output_dir cd $build_output_dir #执行构建 cmake --build . 可以手动执行 ios_cmake.sh 看下效果，执行后记得清理输出物\ncd ios_cmake.sh目录 ./ios_cmake.sh ./buildout .def文件 暴露给kotlin的方法定义文件 内容如下：\n# shared/src/main/cinterop/ios.def # 暴露给kotlin的包名 package = iosNativeLib # 暴露给kotlin的头文件，kotlin侧可以看到里面的方法名 # 这里的路径是相对于.def文件的路径 headers = ios.h # 构建过程中，链接库的搜索目录 # 这里的路径是相对于projectdir（gradle的这个设定是不是bug？） # 也可以使用绝对路径，从工程管理角度不建议用绝对路径 libraryPaths = build/cmake # 需要链接的库文件，这里需要链接上面的iOS nativle lib # 查找libraryPaths目录下的库文件 staticLibraries = libnative-lib.a 修改Gradle脚本 上面已经完成了ios native lib的构建，以及native lib需要暴露的方法配置，现需要使用Gradle脚本将这些工作串起来。\n// shared/build.gradle.kts fun org.jetbrains.kotlin.gradle.plugin.mpp.KotlinNativeTarget.addCInterop_sharedCC() { val main by compilations.getting // target name : main or test val iosNativeLib by main.cinterops.creating { // .def 定位文件 defFile(\u0026#34;src/main/cinterop/ios.def\u0026#34;) // kotlin侧需要搜索的头文件目录 includeDirs(\u0026#34;src/main/cinterop\u0026#34;) } } kotlin { ... iosX64() { addCInterop_sharedCC() } iosArm64() { addCInterop_sharedCC() } iosSimulatorArm64() { addCInterop_sharedCC() } ... } ... // 创建ios_buildCmake任务 val ios_buildCmake by tasks.registering(Exec::class) { val ios_cmakebuildDir = File(projectDir ,\u0026#34;build/cmake\u0026#34;) val ios_cmakeSourceDir = File(projectDir,\u0026#34;src/main/cinterop\u0026#34;) description = \u0026#34;Build native C/C++ with CMake\u0026#34; workingDir = ios_cmakeSourceDir commandLine = listOf(\u0026#34;sh\u0026#34;, \u0026#34;ios_cmake.sh\u0026#34; , ios_cmakebuildDir.absolutePath) } # 设置cinterop的ios构建任务依赖ios_buildCmake任务 tasks.matching { it.name.startsWith(\u0026#34;cinterop\u0026#34;) \u0026amp;\u0026amp; it.name.contains(\u0026#34;Ios\u0026#34;) }.all { dependsOn(ios_buildCmake) } 至此，可以执行iOSApp看看效果\n总结 在无法摆脱C/C++生态的情况下，使用Kotlin Multiplatfrom实现跨平台，维护成本比较高，不如直接使用C/C++。\n","permalink":"https://blog.z6z8.cn/2025/07/18/%E7%A7%BB%E5%8A%A8%E7%AB%AF%E7%8E%AF%E5%A2%83%EF%BC%8Ckotlin-multiplatfrom-%E8%B0%83%E7%94%A8c-c%E6%96%B9%E6%B3%95/","summary":"\u003ch1 id=\"前言\"\u003e前言\u003c/h1\u003e\n\u003cp\u003e本文成文环境：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003emacOS 26\u003c/li\u003e\n\u003cli\u003eXcode 26 以及 iOS SDK\u003c/li\u003e\n\u003cli\u003eAndroid Studio MeerKat Feature Drop 以及 Android SDK、NDK\u003c/li\u003e\n\u003cli\u003eJDK 17\u003c/li\u003e\n\u003cli\u003eGradle 8.11.1\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eKotlin Multiplatfrom 通过Cinterop工具调用C/C++方法，也可以通过JNI规范调用C/C++方法。\u003c/p\u003e\n\u003cp\u003e本质上，都是调用C方法，C++方法需要通过 \u003ccode\u003eextern \u0026quot;C\u0026quot;\u003c/code\u003e 修饰为C方法。\u003c/p\u003e\n\u003cp\u003e本文将介绍Kotlin/Native在Android和iOS环境，如何调用C/C++方法。\u003c/p\u003e\n\u003ch1 id=\"android-studio\"\u003eAndroid Studio\u003c/h1\u003e\n\u003cp\u003e推荐使用 Android Studio 开发Kotlin/Native （Kotlin更像是一款Android开发语言）\u003c/p\u003e\n\u003ch1 id=\"gradle\"\u003eGradle\u003c/h1\u003e\n\u003cp\u003eAndroid Studio的御用构建工具（相比其构建工具，复杂且难用）\u003c/p\u003e\n\u003ch1 id=\"cmake\"\u003eCMake\u003c/h1\u003e\n\u003cp\u003e一个事实上的C/C++构建标准工具，在Android和iOS环境调用各自平台的工具链构建C/C++。\u003c/p\u003e\n\u003ch1 id=\"创建-kotlin-multiplatfrom-工程\"\u003e创建 Kotlin Multiplatfrom 工程\u003c/h1\u003e\n\u003cp\u003e如果Android Studio没有 Kotlin Multiplatfrom 工程模版，则需要先安装 Kotlin Multiplatfrom插件。\n安装完成后，使用 Kotlin Multiplatfrom 工程模版创建一个工程（创建过程中，需要选择iOS的包管理方式，选择cocoapods）\u003c/p\u003e\n\u003ch1 id=\"镜像\"\u003e镜像\u003c/h1\u003e\n\u003cp\u003e因为环大陆的网络墙问题，可能需要配置下镜像仓库\u003c/p\u003e\n\u003cp\u003e1、找到工程根目录下的 \u003ccode\u003esettings.gradle.kts\u003c/code\u003e,添加下镜像仓库（下面配置的是阿里云的maven仓库）\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gradle\" data-lang=\"gradle\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// settings.gradle.kts\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epluginManagement \u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    repositories \u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        maven\u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e setUrl\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;https://maven.aliyun.com/repository/public\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        maven\u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e setUrl\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;https://maven.aliyun.com/repository/central\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        maven\u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e setUrl\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;https://maven.aliyun.com/repository/gradle-plugin\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edependencyResolutionManagement \u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    repositories \u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        maven\u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e setUrl\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;https://maven.aliyun.com/repository/public\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        maven\u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e setUrl\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;https://maven.aliyun.com/repository/central\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        maven\u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e setUrl\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;https://maven.aliyun.com/repository/gradle-plugin\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e2、找到根目录下 \u003ccode\u003egradle/wrapper/gradle-wrapper.properties\u003c/code\u003e，替换为distributionUrl\u003c/p\u003e","title":"移动端环境，Kotlin Multiplatfrom 调用C/C++方法"},{"content":"先解决的墙的问题，建立高速且稳定的梯子，可以解决更新失败的问题。\n还有一种原因是http协议导致的，切换到ssh协议成功率会更高。需要注意，使用ssh协议，需要有github账号，并配置好ssh 公钥信息。\n使用ssh协议更新成功后，还要记得再将本地的cocoapods git仓库设置为http协议.\ncd ~/.cocoapods/repos/cocoapods // ssh git remote set-url origin https://github.com/CocoaPods/Specs.git // http git remote set-url origin git@github.com:CocoaPods/Specs.git 最后，首次初始化cocoapods repo仓库，也可以使用ssh协议\ncd 一个临时文件夹 // 克隆到tmpRepo文件夹 git clone git@github.com:CocoaPods/Specs.git tmpRepo // 添加repo pod repo add trunk /xxx/yyy/tmpRepo // 修改远程地址 cd ~/.cocoapods/repos/cocoapods git remote set-url origin https://github.com/CocoaPods/Specs.git ","permalink":"https://blog.z6z8.cn/2024/11/01/cocoapods-repo%E6%9B%B4%E6%96%B0%E7%BB%8F%E5%B8%B8%E5%A4%B1%E8%B4%A5/","summary":"\u003cp\u003e先解决的墙的问题，建立高速且稳定的梯子，可以解决更新失败的问题。\u003c/p\u003e\n\u003cp\u003e还有一种原因是http协议导致的，切换到ssh协议成功率会更高。需要注意，使用ssh协议，需要有github账号，并配置好ssh 公钥信息。\u003c/p\u003e\n\u003cp\u003e使用ssh协议更新成功后，还要记得再将本地的cocoapods git仓库设置为http协议.\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd ~/.cocoapods/repos/cocoapods\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// ssh\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit remote set-url origin https://github.com/CocoaPods/Specs.git\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// http\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit remote set-url origin git@github.com:CocoaPods/Specs.git\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e最后，首次初始化cocoapods repo仓库，也可以使用ssh协议\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd 一个临时文件夹\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// 克隆到tmpRepo文件夹\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone  git@github.com:CocoaPods/Specs.git tmpRepo\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// 添加repo\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epod repo add trunk /xxx/yyy/tmpRepo\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// 修改远程地址\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd ~/.cocoapods/repos/cocoapods\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit remote set-url origin https://github.com/CocoaPods/Specs.git\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"CocoaPods Repo更新经常失败"},{"content":"两个命令可以解决，otool和install_name_tool\notool和install_name_tool # 显示依赖库列表 otool -L \u0026lt;mach-o文件路径\u0026gt; # 添加新的依赖库路径 install_name_tool -add_rpath \u0026lt;rpath\u0026gt; \u0026lt;mach-o文件路径\u0026gt; # 删除依赖库路径 install_name_tool -delete_rpath \u0026lt;rpath\u0026gt; \u0026lt;mach-o文件路径\u0026gt; # 替换依赖库路径 install_name_tool -change \u0026lt;old_rpath\u0026gt; \u0026lt;new_rpath\u0026gt; \u0026lt;mach-o文件路径\u0026gt; yololib 和ios App 对于iOS App，install_name_tool的-add_rpath、 -delete_rpath总是执行失败，需要借助yololib工具添加依赖\n# 删除iOS App 的依赖 install_name_tool -change 需要删除的依赖 替换的空依赖 #变相实现删除 # 排序iOS App 的依赖 # 不断执行 install_name_tool -change ，实现排序 ","permalink":"https://blog.z6z8.cn/2024/10/29/%E8%A7%A3%E6%9E%90mach-o%E6%96%87%E4%BB%B6%E7%9A%84%E4%BE%9D%E8%B5%96%E5%BA%93%E5%88%97%E8%A1%A8%EF%BC%8C%E4%BF%AE%E6%94%B9%E5%8A%A0%E8%BD%BD%E9%A1%BA%E5%BA%8F/","summary":"\u003cp\u003e两个命令可以解决，otool和install_name_tool\u003c/p\u003e\n\u003ch1 id=\"otool和install_name_tool\"\u003eotool和install_name_tool\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 显示依赖库列表\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eotool \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eL  \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003emach\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eo文件路径\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 添加新的依赖库路径\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003einstall_name_tool  \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eadd_rpath  \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003erpath\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e   \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003emach\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eo文件路径\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 删除依赖库路径\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003einstall_name_tool \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003edelete_rpath  \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003erpath\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003emach\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eo文件路径\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 替换依赖库路径\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003einstall_name_tool \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003echange  \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eold_rpath\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003enew_rpath\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e   \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003emach\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eo文件路径\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"yololib-和ios-app\"\u003eyololib 和ios App\u003c/h1\u003e\n\u003cp\u003e对于iOS App，install_name_tool的-add_rpath、 -delete_rpath总是执行失败，需要借助yololib工具添加依赖\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 删除iOS App 的依赖\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003einstall_name_tool \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003echange \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e需要删除的依赖\u003c/span\u003e   \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e替换的空依赖\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e#变相实现删除\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 排序iOS App 的依赖\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 不断执行 install_name_tool -change  ，实现排序\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"解析mach-o文件的依赖库列表，修改加载顺序"},{"content":"运行命令，sudo killall -9 com.apple.CoreSimulator.CoreSimulatorService 然后重启Xcode\nhttps://forums.developer.apple.com/forums/thread/751049\n","permalink":"https://blog.z6z8.cn/2024/09/10/%E3%80%90%E8%BD%AC%E3%80%91xcode-ios-17-x-not-installed/","summary":"\u003cp\u003e运行命令，sudo killall -9 com.apple.CoreSimulator.CoreSimulatorService\n然后重启Xcode\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://forums.developer.apple.com/forums/thread/751049\"\u003ehttps://forums.developer.apple.com/forums/thread/751049\u003c/a\u003e\u003c/p\u003e","title":"【转】xcode: iOS 17.x not installed"},{"content":"引用 libarchive源码 https://github.com/libarchive/libarchive/tree/v3.7.4\ncmake工具手册 https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-ios-tvos-visionos-or-watchos\n基本操作 需要安装cmake（brew install cmake）\n然后使用cmake为libarchive配置xcode工程\ncd 源码目录 cmake -S. -B_builds -GXcode -DCMAKE_SYSTEM_NAME=iOS #结果输出到_builds文件夹 一般会遇到以下错误\nCMake Error at cat/CMakeLists.txt:33 (INSTALL): INSTALL TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE executable target \u0026#34;bsdcat\u0026#34;. CMake Error at tar/CMakeLists.txt:46 (INSTALL): INSTALL TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE executable target \u0026#34;bsdtar\u0026#34;. CMake Error at cpio/CMakeLists.txt:42 (INSTALL): INSTALL TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE executable target \u0026#34;bsdcpio\u0026#34;. CMake Error at unzip/CMakeLists.txt:37 (INSTALL): INSTALL TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE executable target \u0026#34;bsdunzip\u0026#34;. 以上错误的原因是iOS App并不支持MACOSX_BUNDLE，在CMakeLists.txt中注释对应的INSTALL动作就可以了\n例如对于bsdtar ,打开tar/CMakeLists.txt ，搜索以下两行，加上 # 注释 # INSTALL(TARGETS bsdtar RUNTIME DESTINATION bin) # INSTALL_MAN(${bsdtar_MANS}) 最后，删除输出文件夹（_builds文件夹），重新执行cmake命令\n","permalink":"https://blog.z6z8.cn/2024/08/05/%E4%B8%BAios%E6%9E%84%E5%BB%BAlibarchive/","summary":"\u003ch1 id=\"引用\"\u003e引用\u003c/h1\u003e\n\u003cp\u003elibarchive源码 \u003ca href=\"https://github.com/libarchive/libarchive/tree/v3.7.4\"\u003ehttps://github.com/libarchive/libarchive/tree/v3.7.4\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003ecmake工具手册\n\u003ca href=\"https://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-ios-tvos-visionos-or-watchos\"\u003ehttps://cmake.org/cmake/help/latest/manual/cmake-toolchains.7.html#cross-compiling-for-ios-tvos-visionos-or-watchos\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"基本操作\"\u003e基本操作\u003c/h1\u003e\n\u003cp\u003e需要安装cmake（brew install cmake）\u003c/p\u003e\n\u003cp\u003e然后使用cmake为libarchive配置xcode工程\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd 源码目录\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecmake -S. -B_builds -GXcode -DCMAKE_SYSTEM_NAME=iOS #结果输出到_builds文件夹\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e一般会遇到以下错误\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCMake Error at cat/CMakeLists.txt:33 (INSTALL):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  INSTALL TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE executable\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  target \u0026#34;bsdcat\u0026#34;.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCMake Error at tar/CMakeLists.txt:46 (INSTALL):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  INSTALL TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE executable\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  target \u0026#34;bsdtar\u0026#34;.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCMake Error at cpio/CMakeLists.txt:42 (INSTALL):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  INSTALL TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE executable\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  target \u0026#34;bsdcpio\u0026#34;.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCMake Error at unzip/CMakeLists.txt:37 (INSTALL):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  INSTALL TARGETS given no BUNDLE DESTINATION for MACOSX_BUNDLE executable\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  target \u0026#34;bsdunzip\u0026#34;.\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e以上错误的原因是iOS App并不支持MACOSX_BUNDLE，在CMakeLists.txt中注释对应的INSTALL动作就可以了\u003c/p\u003e","title":"为iOS构建libarchive"},{"content":"本文内容来自 Llama-3-70B-T 的问答\n知识蒸馏（Knowledge Distillation） 知识蒸馏（Knowledge Distillation）是一种模型压缩技术，旨在将大型模型（teacher model）的知识转移到小型模型（student model）中，以便小型模型可以学习到大型模型的特征表示和知识。\n知识蒸馏的优点包括： 模型压缩：小型模型可以部署在资源有限的设备上，减少计算复杂度和存储空间需求。 提高性能：小型模型可以学习到大型模型的知识，提高其性能。 转移学习：知识蒸馏可以用于转移学习，例如将大型模型的知识转移到新的任务或数据集上。 知识蒸馏的应用包括： 模型部署：将大型模型部署在资源有限的设备上，例如移动设备或嵌入式系统。 模型压缩：压缩大型模型，以减少计算复杂度和存储空间需求。 转移学习：将大型模型的知识转移到新的任务或数据集上，以提高性能。 知识蒸馏的过程: 1. 训练教师模型（Teacher Model）\n首先，需要训练一个大型的教师模型，该模型通常是一个复杂的神经网络，具有许多层和参数。教师模型需要在大量的数据上进行训练，以学习到丰富的特征表示。\n2. 定义学生模型（Student Model）\n其次，需要定义一个小型的学生模型，该模型通常是一个简单的神经网络，具有较少的层和参数。学生模型的目的是学习到教师模型的知识，并将其应用于实际问题中。\n3. 蒸馏损失函数（Distillation Loss Function）\n然后，需要定义一个蒸馏损失函数，该函数用于衡量学生模型和教师模型之间的差异。常见的蒸馏损失函数包括：\nKL 散度（Kullback-Leibler Divergence）：衡量两个概率分布之间的差异。 MSE（Mean Squared Error）：衡量两个模型的输出之间的差异。 4. 训练学生模型\n接着，需要使用蒸馏损失函数来训练学生模型。训练过程中，学生模型需要学习到教师模型的知识，并将其应用于实际问题中。\n5.soft目标（Soft Targets）\n在训练学生模型时，通常使用soft目标来指导学生模型的学习。soft目标是教师模型的输出概率分布，经过softmax函数处理后的结果。soft目标可以帮助学生模型学习到教师模型的知识。\n6.温度参数（Temperature Parameter）\n在蒸馏损失函数中，通常引入一个温度参数（Temperature Parameter），该参数用于控制soft目标的softmax函数的温度。温度参数可以影响学生模型的学习过程。\n7. 训练完成\n最后，学生模型的训练完成后，可以将其应用于实际问题中。学生模型通常具有较小的计算复杂度和存储空间需求，因此可以部署在资源有限的设备上。\n总的来说，知识蒸馏的过程是将教师模型的知识转移到学生模型中，以便学生模型可以学习到教师模型的特征表示和知识。\n代码示意 import torch import torch.nn as nn import torch.optim as optim # Define the teacher model class TeacherModel(nn.Module): def __init__(self): super(TeacherModel, self).__init__() self.fc1 = nn.Linear(784, 128) self.fc2 = nn.Linear(128, 10) def forward(self, x): x = torch.relu(self.fc1(x)) x = self.fc2(x) return x # Define the student model class StudentModel(nn.Module): def __init__(self): super(StudentModel, self).__init__() self.fc1 = nn.Linear(784, 64) self.fc2 = nn.Linear(64, 10) def forward(self, x): x = torch.relu(self.fc1(x)) x = self.fc2(x) return x # Load the pre-trained teacher model teacher_model = TeacherModel() teacher_model.load_state_dict(torch.load(\u0026#39;teacher_model.pth\u0026#39;)) # Initialize the student model student_model = StudentModel() # Define the distillation loss function def distillation_loss(student_output, teacher_output, T): return nn.KLDivLoss()(nn.functional.log_softmax(student_output / T, dim=1), nn.functional.softmax(teacher_output / T, dim=1)) # Define the optimizer and temperature parameter optimizer = optim.Adam(student_model.parameters(), lr=0.001) T = 5.0 # Train the student model for epoch in range(10): for x, y in train_loader: # Forward pass teacher_output = teacher_model(x) student_output = student_model(x) # Calculate the distillation loss loss = distillation_loss(student_output, teacher_output, T) # Backward pass optimizer.zero_grad() loss.backward() optimizer.step() print(f\u0026#39;Epoch {epoch+1}, Loss: {loss.item()}\u0026#39;) # Save the student model torch.save(student_model.state_dict(), \u0026#39;tudent_model.pth\u0026#39;) ","permalink":"https://blog.z6z8.cn/2024/05/30/%E7%9F%A5%E8%AF%86%E8%92%B8%E9%A6%8F%EF%BC%88%E5%A4%A7%E6%A8%A1%E5%9E%8B%E8%92%B8%E9%A6%8F%EF%BC%89/","summary":"\u003cp\u003e本文内容来自 Llama-3-70B-T 的问答\u003c/p\u003e\n\u003ch1 id=\"知识蒸馏knowledge-distillation\"\u003e知识蒸馏（Knowledge Distillation）\u003c/h1\u003e\n\u003cp\u003e知识蒸馏（Knowledge Distillation）是一种模型压缩技术，旨在将大型模型（teacher model）的知识转移到小型模型（student model）中，以便小型模型可以学习到大型模型的特征表示和知识。\u003c/p\u003e\n\u003ch1 id=\"知识蒸馏的优点包括\"\u003e知识蒸馏的优点包括：\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e模型压缩：小型模型可以部署在资源有限的设备上，减少计算复杂度和存储空间需求。\u003c/li\u003e\n\u003cli\u003e提高性能：小型模型可以学习到大型模型的知识，提高其性能。\u003c/li\u003e\n\u003cli\u003e转移学习：知识蒸馏可以用于转移学习，例如将大型模型的知识转移到新的任务或数据集上。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"知识蒸馏的应用包括\"\u003e知识蒸馏的应用包括：\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e模型部署：将大型模型部署在资源有限的设备上，例如移动设备或嵌入式系统。\u003c/li\u003e\n\u003cli\u003e模型压缩：压缩大型模型，以减少计算复杂度和存储空间需求。\u003c/li\u003e\n\u003cli\u003e转移学习：将大型模型的知识转移到新的任务或数据集上，以提高性能。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"知识蒸馏的过程\"\u003e知识蒸馏的过程:\u003c/h1\u003e\n\u003cp\u003e\u003cstrong\u003e1. 训练教师模型（Teacher Model）\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e首先，需要训练一个大型的教师模型，该模型通常是一个复杂的神经网络，具有许多层和参数。教师模型需要在大量的数据上进行训练，以学习到丰富的特征表示。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e2. 定义学生模型（Student Model）\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e其次，需要定义一个小型的学生模型，该模型通常是一个简单的神经网络，具有较少的层和参数。学生模型的目的是学习到教师模型的知识，并将其应用于实际问题中。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e3. 蒸馏损失函数（Distillation Loss Function）\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e然后，需要定义一个蒸馏损失函数，该函数用于衡量学生模型和教师模型之间的差异。常见的蒸馏损失函数包括：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eKL 散度（Kullback-Leibler Divergence）：衡量两个概率分布之间的差异。\u003c/li\u003e\n\u003cli\u003eMSE（Mean Squared Error）：衡量两个模型的输出之间的差异。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cstrong\u003e4. 训练学生模型\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e接着，需要使用蒸馏损失函数来训练学生模型。训练过程中，学生模型需要学习到教师模型的知识，并将其应用于实际问题中。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e5.soft目标（Soft Targets）\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e在训练学生模型时，通常使用soft目标来指导学生模型的学习。soft目标是教师模型的输出概率分布，经过softmax函数处理后的结果。soft目标可以帮助学生模型学习到教师模型的知识。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e6.温度参数（Temperature Parameter）\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e在蒸馏损失函数中，通常引入一个温度参数（Temperature Parameter），该参数用于控制soft目标的softmax函数的温度。温度参数可以影响学生模型的学习过程。\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e7. 训练完成\u003c/strong\u003e\u003c/p\u003e\n\u003cp\u003e最后，学生模型的训练完成后，可以将其应用于实际问题中。学生模型通常具有较小的计算复杂度和存储空间需求，因此可以部署在资源有限的设备上。\u003c/p\u003e\n\u003cp\u003e总的来说，知识蒸馏的过程是将教师模型的知识转移到学生模型中，以便学生模型可以学习到教师模型的特征表示和知识。\u003c/p\u003e\n\u003ch1 id=\"代码示意\"\u003e代码示意\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e torch\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e torch.nn \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e nn\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e torch.optim \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e optim\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Define the teacher model\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eTeacherModel\u003c/span\u003e(nn\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eModule):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__init__\u003c/span\u003e(self):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        super(TeacherModel, self)\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003e__init__\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003efc1 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e nn\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eLinear(\u003cspan style=\"color:#ae81ff\"\u003e784\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e128\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003efc2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e nn\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eLinear(\u003cspan style=\"color:#ae81ff\"\u003e128\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eforward\u003c/span\u003e(self, x):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e torch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003erelu(self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003efc1(x))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003efc2(x)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e x\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Define the student model\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eStudentModel\u003c/span\u003e(nn\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eModule):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__init__\u003c/span\u003e(self):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        super(StudentModel, self)\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003e__init__\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003efc1 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e nn\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eLinear(\u003cspan style=\"color:#ae81ff\"\u003e784\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e64\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003efc2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e nn\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eLinear(\u003cspan style=\"color:#ae81ff\"\u003e64\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eforward\u003c/span\u003e(self, x):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e torch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003erelu(self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003efc1(x))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003efc2(x)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e x\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Load the pre-trained teacher model\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eteacher_model \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e TeacherModel()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eteacher_model\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eload_state_dict(torch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eload(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;teacher_model.pth\u0026#39;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Initialize the student model\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003estudent_model \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e StudentModel()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Define the distillation loss function\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edistillation_loss\u003c/span\u003e(student_output, teacher_output, T):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e nn\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eKLDivLoss()(nn\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003efunctional\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003elog_softmax(student_output \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e T, dim\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                          nn\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003efunctional\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esoftmax(teacher_output \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e T, dim\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Define the optimizer and temperature parameter\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eoptimizer \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e optim\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eAdam(student_model\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eparameters(), lr\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0.001\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eT \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e5.0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Train the student model\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e epoch \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e range(\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e x, y \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e train_loader:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e# Forward pass\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        teacher_output \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e teacher_model(x)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        student_output \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e student_model(x)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e# Calculate the distillation loss\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        loss \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e distillation_loss(student_output, teacher_output, T)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e# Backward pass\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        optimizer\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ezero_grad()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        loss\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ebackward()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        optimizer\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003estep()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    print(\u003cspan style=\"color:#e6db74\"\u003ef\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Epoch \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{\u003c/span\u003eepoch\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e, Loss: \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{\u003c/span\u003eloss\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eitem()\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# Save the student model\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etorch\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esave(student_model\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003estate_dict(), \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;tudent_model.pth\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"知识蒸馏（大模型蒸馏）"},{"content":"各个平台的安装过程请参考\n安装依赖 // 更新系统 sudo apt-get update sudo apt-get upgrade // 安装依赖 sudo apt-get install -y make build-essential libssl-dev zlib1g-dev \\ libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \\ libncurses5-dev libncursesw5-dev xz-utils tk-dev 下载源码 // 需要自己确定对应版本的下载地址，下面连接是3.8.4版本 wget https://www.python.org/ftp/python/3.8.4/Python-3.8.4.tgz // 解压缩 tar xvf Python-3.8.4.tgz // 进入目录 cd Python-3.8.4 编译构建和安装 //配置环境 ./configure --enable-optimizations --with-ensurepip=install // -j 8标识 使用8个并行编译。量力而为，并行编译很是消耗资源 make //或者 make -j 8 // 安装到/usr/bin等目录（具体目录和版本有关） sudo make altinstall ","permalink":"https://blog.z6z8.cn/2024/04/12/ubuntu-%E4%BB%8E%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91python3/","summary":"\u003cp\u003e\u003ca href=\"https://realpython.com/installing-python/#how-to-install-on-ubuntu-and-linux-mint\" title=\"各个平台的安装过程请参考\"\u003e各个平台的安装过程请参考\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"安装依赖\"\u003e安装依赖\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// 更新系统\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get update\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get upgrade\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// 安装依赖\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e sudo apt-get install -y make build-essential libssl-dev zlib1g-dev \\\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       libbz2-dev libreadline-dev libsqlite3-dev wget curl llvm \\\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       libncurses5-dev libncursesw5-dev xz-utils tk-dev\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"下载源码\"\u003e下载源码\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// 需要自己确定对应版本的下载地址，下面连接是3.8.4版本\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ewget https://www.python.org/ftp/python/3.8.4/Python-3.8.4.tgz\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// 解压缩\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etar xvf Python-3.8.4.tgz\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// 进入目录\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd Python-3.8.4\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"编译构建和安装\"\u003e编译构建和安装\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e//配置环境\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e./configure --enable-optimizations --with-ensurepip=install\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// -j 8标识 使用8个并行编译。量力而为，并行编译很是消耗资源\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emake //或者 make -j 8\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// 安装到/usr/bin等目录（具体目录和版本有关）\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo make altinstall\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Ubuntu 从源码编译Python3"},{"content":"背景 租了一台服务器，某次重启后就无法连接网络了，多次重启后依然无网络连接，networking/network manager/ifdown/ifup都无法解决\u0026mdash;-因为这台服器根本就没有安装这些命令/模块。 最终通过配置dhcpclient解决，解决过程参考了一篇博文（ 原文看这里）\n解决办法很简单，就是启动dhcpclient，并设置为开机自动启动。\n确定网络接口名称 首先要确定连接互联网的接口名，通常是ens3。 可以使用 ifcconfig 命令获取\n# 网络接口 ens3: ............... # 网络接口 lo是本地环回接口 lo: ................... 启动dhcpclient /sbin/ifconfig ens3 up # 启动ens3网卡 /sbin/dhclient ens3 # 分配ip地址 开机自动连接网络 创建服务文件\nvi /etc/systemd/system/ens3-dhclient.service 文件内容如下\n[Unit] Description=Enable ens33 network interface and start dhclient After=network.target [Service] Type=oneshot ExecStart=/sbin/ifconfig ens3 up ExecStart=/sbin/dhclient ens3 [Install] WantedBy=default.target 使服务文件生效\nsystemctl daemon-reload systemctl enable ens3-dhclient.service systemctl start ens3-dhclient.service ","permalink":"https://blog.z6z8.cn/2024/04/12/ubuntn-%E9%87%8D%E5%90%AF%E5%90%8E%E6%97%A0%E7%BD%91%E7%BB%9C%E8%BF%9E%E6%8E%A5/","summary":"\u003ch1 id=\"背景\"\u003e背景\u003c/h1\u003e\n\u003cp\u003e租了一台服务器，某次重启后就无法连接网络了，多次重启后依然无网络连接，networking/network manager/ifdown/ifup都无法解决\u0026mdash;-因为这台服器根本就没有安装这些命令/模块。\n最终通过配置dhcpclient解决，解决过程参考了一篇博文（ \u003ca href=\"https://blog.csdn.net/weixin_52018852/article/details/132331351#:~:text=%E7%AC%AC%E4%B8%80%E4%B8%AAExecStart%E5%91%BD%E4%BB%A4%E7%94%A8%E4%BA%8E%E5%90%AF%E5%8A%A8ens33%E7%BD%91%E5%8D%A1%EF%BC%8C%E7%AC%AC%E4%BA%8C%E4%B8%AAExecStart%E5%91%BD%E4%BB%A4%E7%94%A8%E4%BA%8E%E5%90%AF%E5%8A%A8dhclient%E6%9C%8D%E5%8A%A1%E3%80%82,1.%E6%89%93%E5%BC%80%E7%BB%88%E7%AB%AF%EF%BC%8C%E5%B9%B6%E5%88%87%E6%8D%A2%E5%88%B0root%E7%94%A8%E6%88%B7%E6%88%96%E4%BD%BF%E7%94%A8sudo%E5%91%BD%E4%BB%A4%E4%BB%A5%E7%AE%A1%E7%90%86%E5%91%98%E6%9D%83%E9%99%90%E8%BF%90%E8%A1%8C%E4%BB%A5%E4%B8%8B%E5%91%BD%E4%BB%A4%E3%80%82%20%E5%9C%A8Linux%E7%B3%BB%E7%BB%9F%E4%B8%AD%EF%BC%8C%E5%8F%AF%E4%BB%A5%E4%BD%BF%E7%94%A8systemd%E6%9D%A5%E5%AE%9E%E7%8E%B0%E5%BC%80%E6%9C%BA%E8%87%AA%E5%8A%A8%E5%BC%80%E5%90%AF%E7%BD%91%E5%8D%A1%E5%B9%B6%E5%90%AF%E5%8A%A8dhclient%E6%9C%8D%E5%8A%A1%E3%80%82\" title=\"原文看这里\"\u003e原文看这里\u003c/a\u003e）\u003c/p\u003e\n\u003cp\u003e解决办法很简单，就是启动dhcpclient，并设置为开机自动启动。\u003c/p\u003e\n\u003ch1 id=\"确定网络接口名称\"\u003e确定网络接口名称\u003c/h1\u003e\n\u003cp\u003e首先要确定连接互联网的接口名，通常是ens3。 可以使用 \u003ccode\u003eifcconfig\u003c/code\u003e 命令获取\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 网络接口\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eens3: ...............\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 网络接口 lo是本地环回接口\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elo: ...................\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"启动dhcpclient\"\u003e启动dhcpclient\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/sbin/ifconfig ens3 up  # 启动ens3网卡\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/sbin/dhclient  ens3 # 分配ip地址\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"开机自动连接网络\"\u003e开机自动连接网络\u003c/h1\u003e\n\u003cp\u003e创建服务文件\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003evi /etc/systemd/system/ens3-dhclient.service\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e文件内容如下\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[Unit]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDescription=Enable ens33 network interface and start dhclient\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAfter=network.target\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[Service]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eType=oneshot\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStart=/sbin/ifconfig ens3 up\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStart=/sbin/dhclient ens3\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[Install]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWantedBy=default.target\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e使服务文件生效\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esystemctl daemon\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ereload\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esystemctl enable ens3\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003edhclient\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eservice\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esystemctl start ens3\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003edhclient\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eservice\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Ubuntn 重启后无网络连接"},{"content":"在Info.plist中配置多窗口支持 Enable Multiple Windows 置为 YES 新建一个Scene配置（如果只有一个窗口，则不需要此操作） 判断当前环境是否支持多窗口 iOS13及以上支持多窗口；iPad设备和Vision设备支持，但iPhone不支持。\nif (@available(iOS 13.0, *)) { if (UIApplication.sharedApplication.supportsMultipleScenes) {// Info.plist也配置了多窗口开关 if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad || UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomVision) { //支持多窗口 } } } 使用API创建新窗口 创建新的SceneDelegate 当App启用Scene后，需要使用Scene管理Window。为了管理新窗口，我们新建一个SceneDelegate\n@interface SecondSceneDelegate : UIResponder \u0026lt; UIWindowSceneDelegate ,NSUserActivityDelegate\u0026gt; @property (nonatomic,strong) UIWindow * window; @end @implementation SecondSceneDelegate // 将要连接到某个场景（Window需要依附在具体场景） - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { if (self.window == nil) { SecondSceneViewController *vc = [[SecondSceneViewController alloc] init]; // 自己定义的页面 UINavigationController *naviVc = [[UINavigationController alloc] initWithRootViewController:vc];//页面导航 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.windowScene = (UIWindowScene *)scene; self.window.rootViewController = naviVc; [self.window makeKeyAndVisible]; } } @end 创建新窗口 使用 requestSceneSessionActivation\nNSUserActivity * activity = [[NSUserActivity alloc] initWithActivityType:@\u0026#34;open_by_first\u0026#34;]; [UIApplication.sharedApplication requestSceneSessionActivation:nil //此参数为nil时，表示要求系统创建一个SceneSession userActivity:activity options:optios errorHandler:^(NSError * _Nonnull error) { NSLog(@\u0026#34;%@\u0026#34;,error); }]; 同时兼容iOS13及以上和iOS12及以下 请先去除工程中的StoryBoard的相关配置（否则，以下代码可能不会完全生效）。\n在Info.plist中配置多窗口支持（参考上文） 略\n修改AppDelegate @interface AppDelegate : UIResponder \u0026lt;UIApplicationDelegate\u0026gt; @property (nullable, nonatomic, strong) UIWindow *window; // 添加属性，注意这是UIApplicationDelegate的协议实现 @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { if (@available(iOS 13.0, *)) { //iOS 13，启用Scene后，窗口在Scene的实现里创建 return YES; } else { FirstSceneViewController *vc = [[FirstSceneViewController alloc] init]; // 自己定义的页面 UINavigationController *naviVc = [[UINavigationController alloc] initWithRootViewController:vc];//页面导航 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.rootViewController = naviVc; [self.window makeKeyAndVisible]; return YES; } } - (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options { NSString *cfgName = @\u0026#34;FirstScene\u0026#34;; //场景名字 if ([options.userActivities.objectEnumerator.nextObject.activityType isEqualToString:@\u0026#34;open_by_first\u0026#34;]) //使用哪个场景 { cfgName = @\u0026#34;SecondScene\u0026#34;; } return [[UISceneConfiguration alloc] initWithName:cfgName sessionRole:connectingSceneSession.role]; } @end 创建（修改）SceneDelegate 为求简单，本文采用多组 Window+SceneDelegate 来管理多个窗口，即每个Window都有自己的SceneDelegate。本文实现了两个窗口的情形。\n第一个SceneDelegate代码如下\n@interface FirstSceneDelegate : UIResponder \u0026lt;UIWindowSceneDelegate\u0026gt; @property (strong, nonatomic) UIWindow * window; @end @implementation FirstSceneDelegate - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { session.userInfo = @{@\u0026#34;userData\u0026#34;:@\u0026#34;first_session\u0026#34;}; if (self.window == nil) { FirstSceneViewController *vc = [[FirstSceneViewController alloc] init]; // 自己定义的页面 UINavigationController *naviVc = [[UINavigationController alloc] initWithRootViewController:vc];//页面导航 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.windowScene = (UIWindowScene *)scene; self.window.rootViewController = naviVc; [self.window makeKeyAndVisible]; } } @end 第二个SceneDelegate代码如下\n@interface SecondSceneDelegate : UIResponder \u0026lt; UIWindowSceneDelegate ,NSUserActivityDelegate\u0026gt; @property (nonatomic,strong) UIWindow * window; @end @implementation SecondSceneDelegate // 将要连接到某个场景（Window需要依附在具体场景） - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { session.userInfo = @{@\u0026#34;userData\u0026#34;:@\u0026#34;second_session\u0026#34;}; if (self.window == nil) { SecondSceneViewController *vc = [[SecondSceneViewController alloc] init]; // 自己定义的页面 UINavigationController *naviVc = [[UINavigationController alloc] initWithRootViewController:vc];//页面导航 self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.windowScene = (UIWindowScene *)scene; self.window.rootViewController = naviVc; [self.window makeKeyAndVisible]; } } @end 在第一个窗口的页面下，使用按钮打开第二个窗口 按钮事件响应\n- (void)onClickButton:(id)sender { if (@available(iOS 13.0, *)) { if (UIApplication.sharedApplication.supportsMultipleScenes) { if (UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomPad || UIDevice.currentDevice.userInterfaceIdiom == UIUserInterfaceIdiomVision) { // 查找，确定是否已经打开过 UISceneSession *foundSession = nil; NSString * foundStr = @\u0026#34;second_session\u0026#34;; for (UISceneSession * session in UIApplication.sharedApplication.openSessions) { if (session.userInfo \u0026amp;\u0026amp; [foundStr isEqualToString:session.userInfo[@\u0026#34;userData\u0026#34;]]) { foundSession = session; break; } } UISceneActivationRequestOptions *optios = nil; if (foundSession) // 已存在，激活即可 { [UIApplication.sharedApplication requestSceneSessionActivation:foundSession userActivity:nil options:optios errorHandler:^(NSError * _Nonnull error) { NSLog(@\u0026#34;%@\u0026#34;,error); }]; } else // 新建场景 { NSUserActivity * activity = [[NSUserActivity alloc] initWithActivityType:@\u0026#34;open_by_first\u0026#34;]; [UIApplication.sharedApplication requestSceneSessionActivation:nil userActivity:activity options:optios errorHandler:^(NSError * _Nonnull error) { NSLog(@\u0026#34;%@\u0026#34;,error); }]; } } } } } 其他注意事项 启用Scene后，UIAlertView将无法使用（运行时崩溃），需要用UIAlertController进行替换 在iPad端，实现多窗口时，需要将Info.list里的 Requires full screen 置为false，同时要设置为支持所有屏幕方向。否则可能会收到类似错误“the delegate of workspace fbscenemanger declined to create scene” ","permalink":"https://blog.z6z8.cn/2024/02/26/ios13-%E5%90%8C%E4%B8%80app%E5%AE%9E%E7%8E%B0%E5%A4%9A%E7%AA%97%E5%8F%A3%EF%BC%88ipad%E5%92%8Cvision%E5%B9%B3%E5%8F%B0%EF%BC%89/","summary":"\u003ch1 id=\"在infoplist中配置多窗口支持\"\u003e在Info.plist中配置多窗口支持\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003eEnable Multiple Windows 置为 YES\u003c/li\u003e\n\u003cli\u003e新建一个Scene配置（如果只有一个窗口，则不需要此操作）\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2024/02/1.png\"\u003e\u003c/p\u003e\n\u003ch1 id=\"判断当前环境是否支持多窗口\"\u003e判断当前环境是否支持多窗口\u003c/h1\u003e\n\u003cp\u003eiOS13及以上支持多窗口；iPad设备和Vision设备支持，但iPhone不支持。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (@available(iOS \u003cspan style=\"color:#ae81ff\"\u003e13.0\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (UIApplication.sharedApplication.supportsMultipleScenes)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\u003cspan style=\"color:#75715e\"\u003e// Info.plist也配置了多窗口开关\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e  (UIDevice.currentDevice.userInterfaceIdiom \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e UIUserInterfaceIdiomPad\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e UIDevice.currentDevice.userInterfaceIdiom \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e UIUserInterfaceIdiomVision)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e//支持多窗口\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"使用api创建新窗口\"\u003e使用API创建新窗口\u003c/h1\u003e\n\u003ch2 id=\"创建新的scenedelegate\"\u003e创建新的SceneDelegate\u003c/h2\u003e\n\u003cp\u003e当App启用Scene后，需要使用Scene管理Window。为了管理新窗口，我们新建一个SceneDelegate\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@interface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eSecondSceneDelegate\u003c/span\u003e : \u003cspan style=\"color:#a6e22e\"\u003eUIResponder\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e UIWindowSceneDelegate ,NSUserActivityDelegate\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@property\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003enonatomic\u003c/span\u003e,\u003cspan style=\"color:#66d9ef\"\u003estrong\u003c/span\u003e) UIWindow \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e window;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@implementation\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eSecondSceneDelegate\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 将要连接到某个场景（Window需要依附在具体场景）\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e- (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003escene:\u003c/span\u003e(UIScene \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)scene \u003cspan style=\"color:#a6e22e\"\u003ewillConnectToSession:\u003c/span\u003e(UISceneSession \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)session \u003cspan style=\"color:#a6e22e\"\u003eoptions:\u003c/span\u003e(UISceneConnectionOptions \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)connectionOptions\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (self.window \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e nil)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        SecondSceneViewController \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003evc \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[SecondSceneViewController alloc] init]; \u003cspan style=\"color:#75715e\"\u003e// 自己定义的页面\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        UINavigationController \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003enaviVc \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[UINavigationController alloc] initWithRootViewController:vc];\u003cspan style=\"color:#75715e\"\u003e//页面导航\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        self.window \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        self.window.windowScene \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (UIWindowScene \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)scene;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        self.window.rootViewController \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e naviVc;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        [self.window makeKeyAndVisible];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"创建新窗口\"\u003e创建新窗口\u003c/h2\u003e\n\u003cp\u003e使用 \u003ccode\u003erequestSceneSessionActivation\u003c/code\u003e\u003c/p\u003e","title":"iOS13 同一App实现多窗口（iPad和Vision平台）"},{"content":"1、将Objective-C头文件拖入framework工程引用，应可在以下路径看到头文件\nBuild Phases -\u0026gt; Headers -\u0026gt; Project 2、创建Bridge头文件，如 “TestBridging.h”，并填入头文件的相对路径\nBuild Settings -\u0026gt; Swift Compiler General -\u0026gt; Objective-C Bridging Header -\u0026gt; xxxx/TestBridging.h 3、在Bridge头文件中引用Objective-C头文件 （不用使用\u0026lt;\u0026gt;形式引用）\n// TestBridging.h #import \u0026#34;A.h\u0026#34; #import \u0026#34;B.h\u0026#34; #import \u0026#34;C.h\u0026#34; 4、关闭 defines Module\nBuild Settings -\u0026gt; Packaging -\u0026gt; Defines Module -\u0026gt; No ","permalink":"https://blog.z6z8.cn/2023/08/14/swift-%E8%AF%AD%E8%A8%80%E7%BC%96%E5%86%99%E9%9D%99%E6%80%81framework%EF%BC%8C%E5%BC%95%E7%94%A8objective-c%E6%96%87%E4%BB%B6/","summary":"\u003cp\u003e1、将Objective-C头文件拖入framework工程引用，应可在以下路径看到头文件\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eBuild Phases -\u0026gt; Headers -\u0026gt; Project\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e2、创建Bridge头文件，如 “TestBridging.h”，并填入头文件的相对路径\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eBuild Settings -\u0026gt; Swift Compiler General -\u0026gt; Objective-C Bridging Header -\u0026gt; xxxx/TestBridging.h\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e3、在Bridge头文件中引用Objective-C头文件 （不用使用\u0026lt;\u0026gt;形式引用）\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// TestBridging.h\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#import \u0026#34;A.h\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#import \u0026#34;B.h\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#import \u0026#34;C.h\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e4、关闭 defines Module\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eBuild Settings -\u0026gt; Packaging -\u0026gt; Defines Module -\u0026gt; No\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Swift 语言编写静态Framework，引用Objective-C文件"},{"content":"使用SwiftUI时，经常会遇到@ViewBuilder，代码看起来很简洁，背后确实复杂的语法规则。\n本文涉及三点：\n@resultBuilder 可变参数 闭包以及尾随闭包 我们可以自己定义一个类似@ViewBuilder的注解，本文将实现一个自定义的字符串拼接的注解。\n首先 用 @resultBuilder 修饰的 struct符号需要实现静态 buildBlock 方法\n@resultBuilder public struct TestStringBuilder { public static func buildBlock( s1 : String ,s2 : String) -\u0026gt; String { return s1 + s2 } } 然后定义一个函数，只有一个闭包参数，参数使用 @TestStringBuilder 修饰\nfunc test_string_builder(@TestStringBuilder strs_join: () -\u0026gt; String ) { print(strs_join()) } 现在可以给 test_string_builder 传入闭包参数了\ntest_string_builder( strs_join :{ \u0026#34;a\u0026#34; \u0026#34;b\u0026#34; }) //将打印字符串 “ab” 该尾随闭包出场了，它是一个书写在函数括号之后的闭包表达式，函数支持将其作为最后一个参数调用\ntest_string_builder(){ \u0026#34;a\u0026#34; \u0026#34;b\u0026#34; } //将打印字符串 “ab” 如果函数只需要闭包表达式一个参数，当您使用尾随闭包时，可以把()省略掉\ntest_string_builder{ \u0026#34;a\u0026#34; \u0026#34;b\u0026#34; } //将打印字符串 “ab” 现在是不是有点像@ViewBuilder的用法了？最后是可变参数，修改下 buildBlock 定义，以支持可变参数\n@resultBuilder public struct TestStringBuilder { public static func buildBlock(_ strs: String...) -\u0026gt; String { var ret = \u0026#34;\u0026#34; for s in strs { ret = ret + s } return ret } } 最终 test_string_builder 的用法\ntest_string_builder { \u0026#34;a\u0026#34; \u0026#34;b\u0026#34; \u0026#34;c\u0026#34; \u0026#34;d\u0026#34; } //将打印字符串 “abcd” @ViewBuilder的原理和上面类似。\n吐槽下，编译器做了很多事，以至于让人习惯语法糖后忘记了该有的本来面目。\n","permalink":"https://blog.z6z8.cn/2023/06/28/swift-%E6%B3%A8%E8%A7%A3-resultbuilder/","summary":"\u003cp\u003e使用SwiftUI时，经常会遇到@ViewBuilder，代码看起来很简洁，背后确实复杂的语法规则。\u003c/p\u003e\n\u003cp\u003e本文涉及三点：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e@resultBuilder\u003c/li\u003e\n\u003cli\u003e可变参数\u003c/li\u003e\n\u003cli\u003e闭包以及尾随闭包\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e我们可以自己定义一个类似@ViewBuilder的注解，本文将实现一个自定义的字符串拼接的注解。\u003c/p\u003e\n\u003cp\u003e首先 用 \u003ccode\u003e@resultBuilder\u003c/code\u003e 修饰的 struct符号需要实现静态 \u003ccode\u003ebuildBlock\u003c/code\u003e 方法\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-swift\" data-lang=\"swift\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e@resultBuilder \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eTestStringBuilder\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebuildBlock\u003c/span\u003e( s1 : String ,s2 : String) -\u0026gt; String {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e s1 \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e s2\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e然后定义一个函数，只有一个闭包参数，参数使用 \u003ccode\u003e@TestStringBuilder\u003c/code\u003e 修饰\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-swift\" data-lang=\"swift\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunc\u003c/span\u003e  \u003cspan style=\"color:#a6e22e\"\u003etest_string_builder\u003c/span\u003e(@TestStringBuilder strs_join: () -\u0026gt; String ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    print(strs_join())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e现在可以给 \u003ccode\u003etest_string_builder\u003c/code\u003e 传入闭包参数了\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-swift\" data-lang=\"swift\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etest_string_builder( strs_join :{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;a\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;b\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e})\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//将打印字符串 “ab”\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e该尾随闭包出场了，它是一个书写在函数括号之后的闭包表达式，函数支持将其作为最后一个参数调用\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-swift\" data-lang=\"swift\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etest_string_builder(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;a\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;b\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//将打印字符串 “ab”\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e如果函数只需要闭包表达式一个参数，当您使用尾随闭包时，可以把()省略掉\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-swift\" data-lang=\"swift\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etest_string_builder{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;a\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;b\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//将打印字符串 “ab”\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e现在是不是有点像@ViewBuilder的用法了？最后是可变参数，修改下 \u003ccode\u003ebuildBlock\u003c/code\u003e 定义，以支持可变参数\u003c/p\u003e","title":"Swift 注解 @resultBuilder"},{"content":"本文假设已经在macOS机器上安装了xcode 本文参考 https://www.rust-lang.org/zh-CN/\nmacOS 中安装 rust开发环境 安装 rust 运行下面命令\ncurl --proto \u0026#39;=https\u0026#39; --tlsv1.2 -sSf https://sh.rustup.rs | sh 中途会提示用户选择哪种安装方式：1、默认安装 ；2、自定义安装 ；3、取消安装\n本文选择默认安装，这将会在 ~/.rustup 安装工具链，在 ~/.cargo 安装包管理器。\n安装完成后，可以使用 rustc --version 查看版本\n更新rust rust会定期更新（6周），可使用命令 rustup update 进行更新\n安装苹果工具链 rustup target add 指定架构工具链名称 # 例如 rustup target add aarch64-apple-ios aarch64-apple-ios , 真机arm64 armv7-apple-ios , 真机armv7 armv7s-apple-ios , 真机armv7s x86_64-apple-ios， 模拟器x86_64 i386-apple-ios, 模拟器i386 安装VSCode 和Rust插件（本步骤可选） 建议使用VSCode + rust-analyzer扩展进行rust代码编写，详细参考https://code.visualstudio.com/docs/languages/rust\n创建iOS可用的rust静态库 创建rust项目 cargo new 项目名字 --lib # 例如 cargo new ios_rust_hello --lib 上面命令会创建一些文件，基本结构如下\nios_rust_hello |___Cargo.toml # 项目配置文件 |___src # 源代码目录 |___lib.rs #源代码 修改配置文件，设置为静态库 修改 Cargo.toml ,添加内容\n[lib] crate-type = [\u0026#34;staticlib\u0026#34;] # 表示将构建为静态库 # 注意,如果使用下面配置，将同时生成静态库和动态库。 # 但是动态库为 dylib格式，苹果不推荐使用 # crate-type = [\u0026#34;staticlib\u0026#34;,\u0026#34;cdylib\u0026#34;] 更多配置参考 https://doc.rust-lang.org/cargo/reference/manifest.html\n使用FFI暴露API 在rust代码中定义暴露给iOS使用的函数\n#[no_mangle] pub extern fn print_hello() { println!(\u0026#34;Hello\u0026#34;); } #[no_mangle] ，告诉编译器，按照C风格修饰函数名 extern ，这个函数要导出 对应到iOS ObjC中的函数（准确说是C语言中的函数）\nextern print_hello(void); 构建（指定cpu架构） Cargo.toml尚不能配置为指定架构，需要手动使用命令指定构建\ncargo build --target aarch64-apple-ios --release # --target cpu架构（参考本文安装苹果工具链部分） # --release 不使用时默认构建debug版本 另外，使用 rustc --print target-list 打印支持的所有cpu架构\n和iOS工程集成 将已生成的rust静态库拖入xcode工程即可，或者也可以使用cocoapods管理。\n","permalink":"https://blog.z6z8.cn/2023/06/19/ios%E4%B8%AD%E9%9B%86%E6%88%90rust/","summary":"\u003cp\u003e本文假设已经在macOS机器上安装了xcode\n本文参考 \u003ca href=\"https://www.rust-lang.org/zh-CN/\"\u003ehttps://www.rust-lang.org/zh-CN/\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"macos-中安装-rust开发环境\"\u003emacOS 中安装 rust开发环境\u003c/h1\u003e\n\u003ch2 id=\"安装-rust\"\u003e安装 rust\u003c/h2\u003e\n\u003cp\u003e运行下面命令\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecurl --proto \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;=https\u0026#39;\u003c/span\u003e --tlsv1.2 -sSf https://sh.rustup.rs | sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e中途会提示用户选择哪种安装方式：1、默认安装 ；2、自定义安装 ；3、取消安装\u003c/p\u003e\n\u003cp\u003e本文选择默认安装，这将会在 \u003ccode\u003e~/.rustup\u003c/code\u003e 安装工具链，在 \u003ccode\u003e~/.cargo\u003c/code\u003e 安装包管理器。\u003c/p\u003e\n\u003cp\u003e安装完成后，可以使用 \u003ccode\u003e rustc --version\u003c/code\u003e 查看版本\u003c/p\u003e\n\u003ch3 id=\"更新rust\"\u003e更新rust\u003c/h3\u003e\n\u003cp\u003erust会定期更新（6周），可使用命令 \u003ccode\u003erustup update\u003c/code\u003e 进行更新\u003c/p\u003e\n\u003ch2 id=\"安装苹果工具链\"\u003e安装苹果工具链\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erustup target add 指定架构工具链名称\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 例如\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erustup target add  aarch64-apple-ios\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003eaarch64-apple-ios , 真机arm64\u003c/li\u003e\n\u003cli\u003earmv7-apple-ios , 真机armv7\u003c/li\u003e\n\u003cli\u003earmv7s-apple-ios , 真机armv7s\u003c/li\u003e\n\u003cli\u003ex86_64-apple-ios， 模拟器x86_64\u003c/li\u003e\n\u003cli\u003ei386-apple-ios, 模拟器i386\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"安装vscode-和rust插件本步骤可选\"\u003e安装VSCode 和Rust插件（本步骤可选）\u003c/h2\u003e\n\u003cp\u003e建议使用VSCode + rust-analyzer扩展进行rust代码编写，详细参考https://code.visualstudio.com/docs/languages/rust\u003c/p\u003e\n\u003ch1 id=\"创建ios可用的rust静态库\"\u003e创建iOS可用的rust静态库\u003c/h1\u003e\n\u003ch2 id=\"创建rust项目\"\u003e创建rust项目\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecargo new  项目名字  --lib\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 例如 cargo new  ios_rust_hello  --lib\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e上面命令会创建一些文件，基本结构如下\u003c/p\u003e","title":"iOS中集成Rust"},{"content":" 关于 Git Commit ID的计算过程讨论，可参考 How is git commit sha1 formed\n计算过程 # 获取元数据字符串 info=`git cat-file commit HEAD` # 计算元数据的字符串长度 infoLen=`echo $info | wc -c` infoLen=${infoLen// /} # 拼接字符串 str=`printf \u0026#34;commit %s\\0\u0026#34; $infoLen` str=$str$info # 计算SHA1 echo $str | shasum 其他 使用 git cat-file -p hash 命令查看git hash代表的具体内容\ngit cat-file -p 哈希字符串 ","permalink":"https://blog.z6z8.cn/2023/05/04/%E6%89%8B%E5%8A%A8%E8%AE%A1%E7%AE%97git-commit-id%EF%BC%88git-hash%EF%BC%89/","summary":"\u003cblockquote\u003e\n\u003cp\u003e关于 Git Commit ID的计算过程讨论，可参考 \u003ca href=\"https://gist.github.com/masak/2415865\"\u003eHow is git commit sha1 formed\u003c/a\u003e\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch1 id=\"计算过程\"\u003e计算过程\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 获取元数据字符串\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003einfo\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003egit cat-file commit HEAD\u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 计算元数据的字符串长度\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003einfoLen\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003eecho $info | wc -c\u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003einfoLen\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e${\u003c/span\u003einfoLen// /\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 拼接字符串\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003estr\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003eprintf \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;commit %s\\0\u0026#34;\u003c/span\u003e $infoLen\u003cspan style=\"color:#e6db74\"\u003e`\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003estr\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e$str$info\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 计算SHA1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho $str | shasum\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"其他\"\u003e其他\u003c/h1\u003e\n\u003cp\u003e使用 \u003ccode\u003egit cat-file -p hash\u003c/code\u003e 命令查看git hash代表的具体内容\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit cat-file -p 哈希字符串\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"手动计算Git Commit ID（Git Hash）"},{"content":"不允许从沙盒目录加载动态库（代码），尤其是在生产环境上。 在iOS9中，还没有这么严格的管控要求，在iOS10+后要求更加严格了。\nhttps://developer.apple.com/forums/thread/711730\n","permalink":"https://blog.z6z8.cn/2023/05/04/file-system-sandbox-blocked-mmap/","summary":"\u003cp\u003e不允许从沙盒目录加载动态库（代码），尤其是在生产环境上。\n在iOS9中，还没有这么严格的管控要求，在iOS10+后要求更加严格了。\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://developer.apple.com/forums/thread/711730\"\u003ehttps://developer.apple.com/forums/thread/711730\u003c/a\u003e\u003c/p\u003e","title":"file system sandbox blocked mmap()"},{"content":"embedded.mobileprovison是由二进制的加密数据和普通文本字符串组成，我们使用NSPropertyListSerialization类解析普通文本字符串\n首先将普通文本字符串提前出来，这里用到了NSScanner\nNSString *embeddedPath = [[NSBundle mainBundle] pathForResource:@\u0026#34;embedded\u0026#34; ofType:@\u0026#34;mobileprovision\u0026#34;]; NSString *embeddedProvisioning = [NSString stringWithContentsOfFile:embeddedPath encoding:NSISOLatin1StringEncoding error:nil]; NSScanner *scanner = [[NSScanner alloc] initWithString:embeddedProvisioning]; if (![scanner scanUpToString:@\u0026#34;\u0026lt;plist\u0026#34; intoString:nil]) { NSLog(@\u0026#34;parse embedded.mobilerovision error, no plist markup\u0026#34;); return nil; } NSString *extractedPlist = nil; //接收普通文本字符串 if (![scanner scanUpToString:@\u0026#34;\u0026lt;/plist\u0026gt;\u0026#34; intoString:\u0026amp;extractedPlist]) { NSLog(@\u0026#34;parse embedded.mobilerovision error, no plist markup\u0026#34;); return nil; } extractedPlist = [extractedPlist stringByAppendingString:@\u0026#34;\u0026lt;/plist\u0026gt;\u0026#34;]; //添加xml标签结束标记 然后就可以使用NSPropertyListSerialization解析了\nNSError *error; NSDictionary *plist = [NSPropertyListSerialization propertyListWithData:[extractedPlist dataUsingEncoding:NSISOLatin1StringEncoding] options:NSPropertyListImmutable format:nil error:\u0026amp;error]; if (error || ![plist isKindOfClass:[NSDictionary class]]) { NSLog(@\u0026#34;parse embedded.mobilerovision error, %@\u0026#34;,error); return nil; } return plist; //返回结果 参考 https://www.process-one.net/blog/reading-ios-provisioning-profile-in-swift/\n","permalink":"https://blog.z6z8.cn/2023/04/11/ios%E8%BF%90%E8%A1%8C%E6%97%B6%E8%A7%A3%E6%9E%90embedded-mobileprovison/","summary":"\u003cp\u003eembedded.mobileprovison是由二进制的加密数据和普通文本字符串组成，我们使用NSPropertyListSerialization类解析普通文本字符串\u003c/p\u003e\n\u003cp\u003e首先将普通文本字符串提前出来，这里用到了NSScanner\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eNSString \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eembeddedPath \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[NSBundle mainBundle] pathForResource:\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;embedded\u0026#34;\u003c/span\u003e ofType:\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;mobileprovision\u0026#34;\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSString \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eembeddedProvisioning \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [NSString stringWithContentsOfFile:embeddedPath encoding:NSISOLatin1StringEncoding error:nil];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSScanner \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003escanner \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[NSScanner alloc] initWithString:embeddedProvisioning];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e[scanner scanUpToString:\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;\u0026lt;plist\u0026#34;\u003c/span\u003e intoString:nil]) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        NSLog(\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;parse embedded.mobilerovision error, no plist markup\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e nil;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSString \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eextractedPlist \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e nil; \u003cspan style=\"color:#75715e\"\u003e//接收普通文本字符串\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e[scanner scanUpToString:\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;\u0026lt;/plist\u0026gt;\u0026#34;\u003c/span\u003e intoString:\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eextractedPlist]) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        NSLog(\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;parse embedded.mobilerovision error, no plist markup\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e nil;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    extractedPlist \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [extractedPlist stringByAppendingString:\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;\u0026lt;/plist\u0026gt;\u0026#34;\u003c/span\u003e]; \u003cspan style=\"color:#75715e\"\u003e//添加xml标签结束标记\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e然后就可以使用NSPropertyListSerialization解析了\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSError \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eerror;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSDictionary \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eplist \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [NSPropertyListSerialization propertyListWithData:[extractedPlist dataUsingEncoding:NSISOLatin1StringEncoding] options:NSPropertyListImmutable format:nil error:\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eerror];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (error \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e[plist isKindOfClass:[NSDictionary \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e]])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        NSLog(\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;parse embedded.mobilerovision error, %@\u0026#34;\u003c/span\u003e,error);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e nil;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e plist; \u003cspan style=\"color:#75715e\"\u003e//返回结果\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e参考\n\u003ca href=\"https://www.process-one.net/blog/reading-ios-provisioning-profile-in-swift/\"\u003ehttps://www.process-one.net/blog/reading-ios-provisioning-profile-in-swift/\u003c/a\u003e\u003c/p\u003e","title":"iOS运行时解析embedded.mobileprovison"},{"content":"iOS开发环境下，构建动态库时可能会出现undefined symbols，某些情况下我们选择让链接器（ld）忽略这些错误\n# 传给 ld特定 Wl参数，来忽略undefined symbols -Wl,-U ,符号A, -U ,符号B, -U, 符号C ... #或者使用 Xlinker -Xlinker -U -Xlinker 符号A,-Xlinker -U -Xlinker 符号B,-Xlinker -U -Xlinker 符号C... 上面的参数告诉链接器（ld），未定义的符号在其他地方实现了。\n然后，当我们在hostApp环境中加载这个动态库时，可以正常加载，但是运行到某些场景时，会因为missing symbol called崩溃。\n崩溃的原因是上面忽略的undefined symbols没有被加载。\n而undefined symbols没有被加载的原因是链接器（ld）会只想Dead Code Strips这个动作，因为我们在构建动态库时选择了忽略undefined symbols，就有可能（不是一定）导致这些undefined symbols变成Dead Code而被移除掉。\n为解决这个问题，我们还需要像链接器（ld）传递一些参数，强制这些在其他地方实现的undefined symbols被链接到hostApp环境中\n# 注意和上面提到的参数区别，-u和-U，小写的u表示强制加载，大小的U表示忽略 # 传给 ld特定 Wl参数，来强制链接undefined symbols -Wl,-u ,符号A, -u, 符号B, -u, 符号C ... #或者使用 Xlinker -Xlinker -u -Xlinker 符号A,-Xlinker -u -Xlinker 符号B,-Xlinker -u -Xlinker 符号C... 另外，需要注意的是，上面提到的参数，忽略undefined symbols参数是在构建动态库过程中使用；强制链接undefined symbols参数是在构建hostApp时使用。\n","permalink":"https://blog.z6z8.cn/2023/04/10/ios%E6%9E%84%E5%BB%BA%E5%8A%A8%E6%80%81%E5%BA%93%E6%97%B6%E5%BF%BD%E7%95%A5undefined-symbols%E5%AF%BC%E8%87%B4%E7%9A%84missing-symbol-called/","summary":"\u003cp\u003eiOS开发环境下，构建动态库时可能会出现undefined symbols，某些情况下我们选择让链接器（ld）忽略这些错误\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 传给 ld特定 Wl参数，来忽略undefined symbols\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-Wl,-U ,符号A, -U ,符号B, -U, 符号C ...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#或者使用 Xlinker\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-Xlinker -U -Xlinker 符号A,-Xlinker -U -Xlinker 符号B,-Xlinker -U -Xlinker 符号C...\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e上面的参数告诉链接器（ld），未定义的符号在其他地方实现了。\u003c/p\u003e\n\u003cp\u003e然后，当我们在hostApp环境中加载这个动态库时，可以正常加载，但是运行到某些场景时，会因为missing symbol called崩溃。\u003c/p\u003e\n\u003cp\u003e崩溃的原因是上面忽略的undefined symbols没有被加载。\u003c/p\u003e\n\u003cp\u003e而undefined symbols没有被加载的原因是链接器（ld）会只想Dead Code Strips这个动作，因为我们在构建动态库时选择了忽略undefined symbols，就有可能（不是一定）导致这些undefined symbols变成Dead Code而被移除掉。\u003c/p\u003e\n\u003cp\u003e为解决这个问题，我们还需要像链接器（ld）传递一些参数，强制这些在其他地方实现的undefined symbols被链接到hostApp环境中\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 注意和上面提到的参数区别，-u和-U，小写的u表示强制加载，大小的U表示忽略\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 传给 ld特定 Wl参数，来强制链接undefined symbols\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-Wl,-u ,符号A, -u, 符号B, -u, 符号C ...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#或者使用 Xlinker\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-Xlinker -u -Xlinker 符号A,-Xlinker -u -Xlinker 符号B,-Xlinker -u -Xlinker 符号C...\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e另外，需要注意的是，上面提到的参数，忽略undefined symbols参数是在构建动态库过程中使用；强制链接undefined symbols参数是在构建hostApp时使用。\u003c/p\u003e","title":"iOS构建动态库时忽略undefined symbols导致的missing symbol called"},{"content":"目前，cocoapods-art还不能很好的适配苹果M系列芯片的macOS系统，故而探索出这条兜底的协作路径，可以不用使用cocoapods-art插件。 本文涉及相关命令 curl、 tar、 git、 pod(cocoapods)\n原理 cocoapods-art的原理是先从jfrog下载全量的podspec索引，然后在本地创建git仓库存储这些索引，供cocoapods使用。 cocoapods-art插件操作的git仓库路径在 ~/.cocoapods/repos 和 ~/.cocoapods/repos-art 里面。\n同理，我们可以按照cocoapods-art这个流程来实现我们自己的索引管理方案。\n下载索引 这里使用artifactory提供rest api，将索引下载到 /AAAA（绝对路径，且不和操作系统用户绑定） 路径\n# -u 用户名密码鉴权 # -A 自定义http的User-Agent curl -u artifactory用户名:密码 -f -L -o /AAAA/file.tgz http://artifactory域名/artifactory/api/pods/jfrog仓库名/index/fetchIndex --create-dirs --netrc-optional --retry 2 -A \u0026#39;CocoaPods/1.11.3 cocoapods-downloader/1.6.3\u0026#39; --ssl-no-revoke 创建git仓库或者更新git仓库 第一次下载索引文件时的操作（创建添加） 索引文件下载到 /AAAA/file.tgz，使用 tar 命令解压\ntar xf /AAAA/file.tgz -C /AAAA # 解压后删除压缩包 rm /AAAA/file.tgz 将 /AAAA 目录初始化为git仓库，再次下载索引时只要更新git仓库就可以了\n# 第一次下载索引文件后，初始化git仓库 cd /AAAA git init git branch -M main #设置main为默认目录 # 添加索引文件到git仓库 git add . git commit -m \u0026#34;add message\u0026#34; # 再次下载所以文件后，直接讲索引添加到git仓库 再次下载索引文件时的操作（更新） 索引文件下载到 /AAAA/file.tgz，先删除旧索引（specs），再使用 tar 命令解压压缩包\nrm -fr /AAAA/Specs tar xf /AAAA/file.tgz -C /AAAA rm /AAAA/file.tgz 更新git仓库\ngit add . git commit -m \u0026#34;update message\u0026#34; 修改Podfile源 这步是最后的操作了，将podfile的source指向我们下载后的索引目录\nsource \u0026#39;/AAAA\u0026#39; #绝对路径，且不和操作系统用户绑定，避免podfile.lock文件因为操作系统用户不同而发生变化 然后执行 pod install就可以了\n","permalink":"https://blog.z6z8.cn/2023/03/16/%E4%B8%8D%E4%BD%BF%E7%94%A8cocoapods-art%E6%8F%92%E4%BB%B6%E6%83%85%E5%86%B5%E4%B8%8B%E4%B8%8Ejfrog%E5%8D%8F%E4%BD%9C/","summary":"\u003cp\u003e目前，cocoapods-art还不能很好的适配苹果M系列芯片的macOS系统，故而探索出这条兜底的协作路径，可以不用使用cocoapods-art插件。\n本文涉及相关命令 \u003ccode\u003ecurl\u003c/code\u003e、 \u003ccode\u003etar\u003c/code\u003e、 \u003ccode\u003egit\u003c/code\u003e、 \u003ccode\u003epod(cocoapods)\u003c/code\u003e\u003c/p\u003e\n\u003ch1 id=\"原理\"\u003e原理\u003c/h1\u003e\n\u003cp\u003ecocoapods-art的原理是先从jfrog下载全量的podspec索引，然后在本地创建git仓库存储这些索引，供cocoapods使用。\ncocoapods-art插件操作的git仓库路径在 \u003ccode\u003e~/.cocoapods/repos\u003c/code\u003e 和 \u003ccode\u003e~/.cocoapods/repos-art\u003c/code\u003e 里面。\u003c/p\u003e\n\u003cp\u003e同理，我们可以按照cocoapods-art这个流程来实现我们自己的索引管理方案。\u003c/p\u003e\n\u003ch1 id=\"下载索引\"\u003e下载索引\u003c/h1\u003e\n\u003cp\u003e这里使用artifactory提供rest api，将索引下载到 \u003ccode\u003e/AAAA（绝对路径，且不和操作系统用户绑定）\u003c/code\u003e 路径\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# -u 用户名密码鉴权\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# -A 自定义http的User-Agent\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecurl  \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eu artifactory用户名:\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e密码\u003c/span\u003e  \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ef \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eL \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eo \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eAAAA\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003efile\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etgz  http:\u003cspan style=\"color:#f92672\"\u003e//\u003c/span\u003eartifactory域名\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eartifactory\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eapi\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003epods\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003ejfrog仓库名\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eindex\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003efetchIndex  \u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003ecreate\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003edirs \u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003enetrc\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eoptional \u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003eretry \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eA \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;CocoaPods/1.11.3 cocoapods-downloader/1.6.3\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003essl\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eno\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003erevoke\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"创建git仓库或者更新git仓库\"\u003e创建git仓库或者更新git仓库\u003c/h1\u003e\n\u003ch2 id=\"第一次下载索引文件时的操作创建添加\"\u003e第一次下载索引文件时的操作（创建添加）\u003c/h2\u003e\n\u003cp\u003e索引文件下载到 \u003ccode\u003e/AAAA/file.tgz\u003c/code\u003e，使用 \u003ccode\u003etar\u003c/code\u003e 命令解压\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etar xf /AAAA/file.tgz -C  /AAAA\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 解压后删除压缩包\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erm /AAAA/file.tgz\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e将 \u003ccode\u003e/AAAA\u003c/code\u003e 目录初始化为git仓库，再次下载索引时只要更新git仓库就可以了\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 第一次下载索引文件后，初始化git仓库\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd /AAAA\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit init\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit branch -M main #设置main为默认目录\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 添加索引文件到git仓库\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit add .\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit commit -m \u0026#34;add message\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 再次下载所以文件后，直接讲索引添加到git仓库\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"再次下载索引文件时的操作更新\"\u003e再次下载索引文件时的操作（更新）\u003c/h2\u003e\n\u003cp\u003e索引文件下载到 \u003ccode\u003e/AAAA/file.tgz\u003c/code\u003e，先删除旧索引（specs），再使用 \u003ccode\u003etar\u003c/code\u003e 命令解压压缩包\u003c/p\u003e","title":"不使用cocoapods-art插件情况下与jfrog协作"},{"content":"一个可能的原因：多个静态库（或动态库）的Minimum Deployments不一致，通常相差比较大。 例如 A库是Objective-C开放，最小依赖iOS 11; B库是swift开放，最小依赖iOS 16 而HostApp是iOS 11，这在运行时很可能触发 missing symbol called\n猜测是iOS 11和iOS16的swift运行时库有较大差异。\n","permalink":"https://blog.z6z8.cn/2023/02/13/objective-c-%E8%B0%83%E7%94%A8-swift-dyld-missing-symbol-called/","summary":"\u003cp\u003e一个可能的原因：多个静态库（或动态库）的Minimum Deployments不一致，通常相差比较大。\n例如\nA库是Objective-C开放，最小依赖iOS 11;\nB库是swift开放，最小依赖iOS 16\n而HostApp是iOS 11，这在运行时很可能触发 \u003ccode\u003emissing symbol called\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e猜测是iOS 11和iOS16的swift运行时库有较大差异。\u003c/p\u003e","title":"Objective-C 调用 Swift : dyld missing symbol called"},{"content":"本文指的转换为无源码时的转换（有源码那叫编译构建） 涉及工具\nlibtool 用于静态库转为动态库 lipo 用于查看库信息，将fat库拆分为thin库，将thin库合并为fat库 ar 用于将thin库解压为object文件 基本过程，将fat静态库拆分为thin静态库，再将thin静态库解压为object文件，然后将object文件压缩为thin动态库，最后将thin动态库合并为fat动态库\n拆分fat静态库 先查看fat库基本信息，重点是看由哪些指令架构的thin库组成\nlipo -info libfat.a # 输出信息中重点看指令架构 Architectures in the fat file: libfat.a are: x86_64 arm64 按照指令架构拆分fat库\nlipo libfat.a -extract x86_64 -output libfoo.a 解压thin静态库 会输出一组 .o 文件\nar -x libfoo.a 压缩为thin动态库 注意下，需要手动添加依赖库, -framework 依赖库 -l依赖库\nlibtool -dynamic *.o -o libfoo_dynamic-x86_64.dylib -framework CoreFoundation -lSystem 将thin动态库合并为fat动态库 lipo -create libfoo_dynamic-x86_64.dylib libfoo_dynamic-arm64.dylib -output ./libfoo_dynamic.dylib 参考 https://pewpewthespells.com/blog/convert_static_to_dynamic.html\n","permalink":"https://blog.z6z8.cn/2023/02/08/%E5%B0%86ios%E9%9D%99%E6%80%81%E5%BA%93%E8%BD%AC%E4%B8%BA%E5%8A%A8%E6%80%81%E5%BA%93/","summary":"\u003cp\u003e本文指的转换为无源码时的转换（有源码那叫编译构建）\n涉及工具\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003elibtool 用于静态库转为动态库\u003c/li\u003e\n\u003cli\u003elipo 用于查看库信息，将fat库拆分为thin库，将thin库合并为fat库\u003c/li\u003e\n\u003cli\u003ear 用于将thin库解压为object文件\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e基本过程，将fat静态库拆分为thin静态库，再将thin静态库解压为object文件，然后将object文件压缩为thin动态库，最后将thin动态库合并为fat动态库\u003c/p\u003e\n\u003ch1 id=\"拆分fat静态库\"\u003e拆分fat静态库\u003c/h1\u003e\n\u003cp\u003e先查看fat库基本信息，重点是看由哪些指令架构的thin库组成\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elipo -info  libfat.a\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 输出信息中重点看指令架构\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eArchitectures in the fat file: libfat.a are: x86_64 arm64\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e按照指令架构拆分fat库\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elipo libfat.a -extract x86_64 -output libfoo.a\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"解压thin静态库\"\u003e解压thin静态库\u003c/h1\u003e\n\u003cp\u003e会输出一组 \u003ccode\u003e.o\u003c/code\u003e 文件\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ear -x libfoo.a\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"压缩为thin动态库\"\u003e压缩为thin动态库\u003c/h1\u003e\n\u003cp\u003e注意下，需要手动添加依赖库, \u003ccode\u003e-framework 依赖库  -l依赖库\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elibtool \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003edynamic \u003cspan style=\"color:#f92672\"\u003e*.\u003c/span\u003eo \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eo libfoo_dynamic\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ex86_64\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003edylib \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003eframework CoreFoundation \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003elSystem\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"将thin动态库合并为fat动态库\"\u003e将thin动态库合并为fat动态库\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003elipo -create libfoo_dynamic-x86_64.dylib  libfoo_dynamic-arm64.dylib -output ./libfoo_dynamic.dylib\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e参考\n\u003ca href=\"https://pewpewthespells.com/blog/convert_static_to_dynamic.html\"\u003ehttps://pewpewthespells.com/blog/convert_static_to_dynamic.html\u003c/a\u003e\u003c/p\u003e","title":"将iOS静态库转为动态库"},{"content":"可能的一个原因是设置了NSHTTPCookieDiscard这个key\nNSMutableDictionary\u0026lt;NSString *, id\u0026gt; *properties = [NSMutableDictionary dictionary]; properties[NSHTTPCookieName] = @\u0026#34;aaa\u0026#34;; properties[NSHTTPCookieValue] = @\u0026#34;bbb\u0026#34;; // properties[NSHTTPCookieDiscard] = @\u0026#34;FALSE\u0026#34;; 该选项不生效，设置后会影响NSHTTPCookieExpires properties[NSHTTPCookiePath] = @\u0026#34;/ccc/ddd\u0026#34;; properties[NSHTTPCookieExpires] = [[NSDate new] dateByAddingTimeInterval:3*3600*24]; properties[NSHTTPCookieDomain] = @\u0026#34;xxx.yyy.zzz\u0026#34;; NSHTTPCookie *cookie = [[NSHTTPCookie alloc] initWithProperties:properties]; NSLog(@\u0026#34;%@\u0026#34;,cookie); // cookide 的过期时间应该设置成功了 ","permalink":"https://blog.z6z8.cn/2023/01/31/ios-nshttpcookie-%E8%AE%BE%E7%BD%AEnshttpcookieexpires%E5%A4%B1%E8%B4%A5/","summary":"\u003cp\u003e可能的一个原因是设置了NSHTTPCookieDiscard这个key\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSMutableDictionary\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eNSString \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eproperties \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [NSMutableDictionary dictionary];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    properties[NSHTTPCookieName] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;aaa\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    properties[NSHTTPCookieValue] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;bbb\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//    properties[NSHTTPCookieDiscard] = @\u0026#34;FALSE\u0026#34;; 该选项不生效，设置后会影响NSHTTPCookieExpires\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    properties[NSHTTPCookiePath] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;/ccc/ddd\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    properties[NSHTTPCookieExpires] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[NSDate new] dateByAddingTimeInterval:\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3600\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e24\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    properties[NSHTTPCookieDomain] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;xxx.yyy.zzz\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSHTTPCookie \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ecookie \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[NSHTTPCookie alloc] initWithProperties:properties];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSLog(\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;%@\u0026#34;\u003c/span\u003e,cookie); \u003cspan style=\"color:#75715e\"\u003e// cookide 的过期时间应该设置成功了\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"iOS NSHTTPCookie 设置NSHTTPCookieExpires失败"},{"content":"默认情况下，构建动态库时遇到undefinded symbol会构建失败。但有时候，这些undefinded symbol在运行时是存在的（如host app中、其他动态库中），这时可以添加链接参数，让xcode忽略undefinded symbol。\n忽略所有undefinded symbol 省事，但不推荐。\n在 other link flags 中添加下面参数即可\n-undefined dynamic_lookup 忽略指定undefined symbol 可以精确控制 在 other link flags 中添加下面参数\n# 有几个需要忽略的符号，就添加几行 -Wl,-U,symbol_nameA -Wl,-U,symbol_nameB -Wl,-U,symbol_nameC ... 其他注意事项 通过上述方法忽略的undefinded symbol，在运行时会在 flat namespace中查找对应的符号\n","permalink":"https://blog.z6z8.cn/2023/01/15/xcode%E6%9E%84%E5%BB%BA%E5%8A%A8%E6%80%81%E5%BA%93%E5%BF%BD%E7%95%A5undefined-symbol/","summary":"\u003cp\u003e默认情况下，构建动态库时遇到undefinded symbol会构建失败。但有时候，这些undefinded symbol在运行时是存在的（如host app中、其他动态库中），这时可以添加链接参数，让xcode忽略undefinded symbol。\u003c/p\u003e\n\u003ch1 id=\"忽略所有undefinded-symbol\"\u003e忽略所有undefinded symbol\u003c/h1\u003e\n\u003cp\u003e省事，但不推荐。\u003c/p\u003e\n\u003cp\u003e在 other link flags 中添加下面参数即可\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-undefined dynamic_lookup\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"忽略指定undefined-symbol\"\u003e忽略指定undefined symbol\u003c/h1\u003e\n\u003cp\u003e可以精确控制 在 other link flags 中添加下面参数\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 有几个需要忽略的符号，就添加几行\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-Wl,-U,symbol_nameA\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-Wl,-U,symbol_nameB\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-Wl,-U,symbol_nameC\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e...\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"其他注意事项\"\u003e其他注意事项\u003c/h1\u003e\n\u003cp\u003e通过上述方法忽略的undefinded symbol，在运行时会在 flat namespace中查找对应的符号\u003c/p\u003e","title":"xcode构建动态库忽略undefined symbol"},{"content":"介绍 1、IPA是ZIP压缩文件，可以直接用zip命令压缩解压 2、IPA 重签名需要准备p12证书、mobileprovision描述文件 3、IPA里面可能包含动态库(.framework , .dylib)，也需要重签名 4、IPA里面的扩展（.appex）也有自己的mobileprovision，不复用主App。 5、扩展（.appex）的mobileprovision的id要和App的mobileprovision里面的id保持一致。例如主App是 A.B.C，那么扩展的必须是A.B.C.xxxx 。 6、重签名时，应要重新设置Info.plist里EXTENSION_GROUP值，修改为 group.主App的bundle_id，例如 group.A.B.C\n命令 压缩解压缩 unzip 老包.ipa zip -r 新包.ipa Payload/ SwiftSupport/ # 如果没SwiftSupport可以不添加 查看本地的签名证书列表 security find-identity -v -p codesigning # 会输出证书的HASH值和证书名 打印mobileprovision的基本信息 主要获取application-identifier，为后面修改InfoPlist里面的bundle做准备\n/usr/libexec/PlistBuddy -c \\\u0026#34;Print Entitlements:application-identifier\\\u0026#34; /dev/stdin \u0026lt;\u0026lt;\u0026lt; $(/usr/bin/security cms -D -i mobileprovision文件路径 ) 修改InfoPlist的bundle id /usr/libexec/PlistBuddy -c \u0026#34;Set:CFBundleIdentifier 新id\u0026#34; \u0026#34;/需要修改的bundle路径如framework/Info.plist\u0026#34; 读取InfoPlist的bundle id 使用defaults，比较简单\ndefaults read /需要读取的bundle路径如framework/Info CFBundleIdentifier # 注意，不添加.plist后缀 生成entitlements # 先获取全部信息 security cms -D -i \u0026#34;embedded.mobileprovision路径\u0026#34; \u0026gt; 输出的plist文件路径\u0026#34; # 提取entitlements信息 /usr/libexec/PlistBuddy -x -c \u0026#39;Print:Entitlements\u0026#39; 全部信息的plist文件路径 \u0026gt; 输出entitlements信息的plist文件路径 重新签名 /usr/bin/codesign --continue -f -s \u0026#34;证书HASH或者名字\u0026#34; --entitlements \u0026#34;entitlements信息的plist文件路径\u0026#34; \u0026#34;需要签名的bundle如framework、appex、app\u0026#34; 流程 1、准备好证书和mobileprovision文件 2、解压缩ipa 3、复制对应mobileprovision到app目录、appex目录，并重命名为embedded.mobileprovision 4、修改app、appex的Info.plist文件里的bundle id和EXTENSION_GROUP值 5、生成entitlements信息文件 6、用codesign对app、appex重新签名 7、使用app的证书文件对动态库重新签名 8、把重新签名后的文件压缩为ipa\n","permalink":"https://blog.z6z8.cn/2022/12/09/ios-%E9%87%8D%E7%AD%BE%E5%90%8D%E7%9F%A5%E8%AF%86%E7%82%B9/","summary":"\u003ch1 id=\"介绍\"\u003e介绍\u003c/h1\u003e\n\u003cp\u003e1、IPA是ZIP压缩文件，可以直接用zip命令压缩解压\n2、IPA 重签名需要准备p12证书、mobileprovision描述文件\n3、IPA里面可能包含动态库(.framework , .dylib)，也需要重签名\n4、IPA里面的扩展（.appex）也有自己的mobileprovision，不复用主App。\n5、扩展（.appex）的mobileprovision的id要和App的mobileprovision里面的id保持一致。例如主App是 A.B.C，那么扩展的必须是A.B.C.xxxx 。\n6、重签名时，应要重新设置Info.plist里EXTENSION_GROUP值，修改为 \u003ccode\u003egroup.主App的bundle_id\u003c/code\u003e，例如 \u003ccode\u003egroup.A.B.C\u003c/code\u003e\u003c/p\u003e\n\u003ch1 id=\"命令\"\u003e命令\u003c/h1\u003e\n\u003ch2 id=\"压缩解压缩\"\u003e压缩解压缩\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eunzip 老包.ipa\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ezip -r  新包.ipa  Payload/ SwiftSupport/ \u003cspan style=\"color:#75715e\"\u003e# 如果没SwiftSupport可以不添加\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"查看本地的签名证书列表\"\u003e查看本地的签名证书列表\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esecurity find-identity -v -p codesigning\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 会输出证书的HASH值和证书名\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"打印mobileprovision的基本信息\"\u003e打印mobileprovision的基本信息\u003c/h2\u003e\n\u003cp\u003e主要获取application-identifier，为后面修改InfoPlist里面的bundle做准备\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/usr/libexec/PlistBuddy -c \\\u0026#34;Print Entitlements:application-identifier\\\u0026#34; /dev/stdin \u0026lt;\u0026lt;\u0026lt; $(/usr/bin/security cms -D -i mobileprovision文件路径 )\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"修改infoplist的bundle-id\"\u003e修改InfoPlist的bundle id\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/usr/libexec/PlistBuddy -c \u0026#34;Set:CFBundleIdentifier 新id\u0026#34; \u0026#34;/需要修改的bundle路径如framework/Info.plist\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"读取infoplist的bundle-id\"\u003e读取InfoPlist的bundle id\u003c/h2\u003e\n\u003cp\u003e使用defaults，比较简单\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edefaults read  /需要读取的bundle路径如framework/Info  CFBundleIdentifier\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 注意，不添加.plist后缀\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"生成entitlements\"\u003e生成entitlements\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 先获取全部信息\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esecurity cms -D -i \u0026#34;embedded.mobileprovision路径\u0026#34; \u0026gt;  输出的plist文件路径\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 提取entitlements信息\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/usr/libexec/PlistBuddy -x -c \u0026#39;Print:Entitlements\u0026#39;  全部信息的plist文件路径 \u0026gt;  输出entitlements信息的plist文件路径\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"重新签名\"\u003e重新签名\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/usr/bin/codesign --continue -f -s \u0026#34;证书HASH或者名字\u0026#34; --entitlements \u0026#34;entitlements信息的plist文件路径\u0026#34;  \u0026#34;需要签名的bundle如framework、appex、app\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"流程\"\u003e流程\u003c/h1\u003e\n\u003cp\u003e1、准备好证书和mobileprovision文件\n2、解压缩ipa\n3、复制对应mobileprovision到app目录、appex目录，并重命名为embedded.mobileprovision\n4、修改app、appex的Info.plist文件里的bundle id和EXTENSION_GROUP值\n5、生成entitlements信息文件\n6、用codesign对app、appex重新签名\n7、使用app的证书文件对动态库重新签名\n8、把重新签名后的文件压缩为ipa\u003c/p\u003e","title":"iOS 重签名知识点"},{"content":"解决办法1: 将xcode.app里面的nsurlsessiond程序重命名\n/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联网\n参考 https://developer.apple.com/forums/thread/114981\n","permalink":"https://blog.z6z8.cn/2022/11/30/mac-osx-%E8%BF%90%E8%A1%8Cios%E6%A8%A1%E6%8B%9F%E5%99%A8%E6%97%B6%EF%BC%8Cnsurlsessiond%E4%B8%8D%E5%81%9C%E5%9C%B0%E6%B6%88%E8%80%97%E5%AE%BD%E5%B8%A6/","summary":"\u003cp\u003e解决办法1:\n将xcode.app里面的nsurlsessiond程序重命名\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/Library/Developer/CoreSimulator/Profiles/Runtimes/iOS.simruntime/Contents/Resources/RuntimeRoot/usr/libexec/nsurlsessiond\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e解决办法2:\n建立防火墙规则，禁止xcode.app里面的nsurlsessiond联网\u003c/p\u003e\n\u003cp\u003e参考\n\u003ca href=\"https://developer.apple.com/forums/thread/114981\"\u003ehttps://developer.apple.com/forums/thread/114981\u003c/a\u003e\u003c/p\u003e","title":"mac osx 运行iOS模拟器时，nsurlsessiond不停地消耗宽带"},{"content":"背景 合作项目，一方提供宿主App，一方提供动态库。双方囿于合规而不能为对方提供源码，所以双方提供的产物都是二进制产物。 运行时双方融合是没有问题的，但是对开发（尤其是动态库开发方）是不友好的。\n当然，这场景要是在其他操作系统是没有什么大问题的。但对于iOS而言，因为苹果的硬性限制，真机环境调试是有些麻烦的。为解决开发阶段的调试需求，本文提供了一种思路并实践可行。\n一些准备 开发者证书（调试）是必需的 Xcode ，本文成文时使用的是13.4.1 fastlane 工具，本文使用其重签名工具 手动调试 在介绍一键调试前，先大致介绍下如何手动调试。 若要在真机环境调试，需要先将部署到真机的所有可执行文件进行签名，这包括App主程序和动态framework\n获取开发者证书列表 运行命令，获取可用的证书列表\nsecurity find-identity -v -p codesigning 结果一般是十六进制字符串和证书名字，例如\n1) 十六进制串 \u0026#34;Apple Development: xxxxx(yyyyyyy)\u0026#34; 1 valid identities found 动态库重签名 codesign -f -s 证书标识(十六进制串) xxxx.framework ipa包重签名 本文使用fastlane工具\n# 安装fastlane sudo gem install fastlane 安装成功后，执行重签名\nfastlane sigh resign #然后安装提示输入ipa包文件路径、证书文件路径 #期间也可填写证书的十六进制串 特别注意：重签名证书必需使用 开发证书。 重签名成功后，获得同名的ipa包，使用Xcode提供的 Devices and Simulators 工具将ipa包安装到iPhone真机中\n附加到进程 在真机上启动App 然后使用Xcode 提供的 Debug -\u0026gt; Attach to Process 工具，将动态库附加到App进程中，正常情况下是就可以了进行调试了。\n一键调试 一键调试的原理和过程和手动调试是类似的，只不过把一些工作自动化了\n解压包 将重签名的ipa包解压，获得里面的Payload，找到对应的宿主App（一般名字为xxxxx.app）\n创建新动态Target 新建Target不需要侵入其他Target的工程配置。\n假设新建Target就叫做 DebugiPhoneosTarget，打开DebugiPhoneosTarget的scheme进行编辑 Edit Scheme -\u0026gt; DebugiPhoneosTarget -\u0026gt; Run -\u0026gt; Info -\u0026gt; Executeable -\u0026gt; Other ， 选择解压后宿主App\n另外，编辑Scheme时，最好去掉最下方的“Share”选项（即不共享这个Scheme配置，避免git仓库管理时频繁发生冲突）\n配置好后，直接点击Xcode Run是可以直接启动宿主App。如果能成功启动宿主App，那么一键调试就成功了一半。\n配置Build Phase脚本 在 DebugiPhoneosTarget 的 Build Phase 里面新建一个 Run Script Phase，内容为 sh $SRCROOT/debug.sh 一些参数 或者 python $SRCROOT/debug.py 一些参数（$SRCROOT是工程目录，一些参数见下文）。当然，你可以使用其他语言类型的脚本，本文使用python脚本。\n在debug.py中，主要就做了件事： 1、将Xcode构建生成的动态framework复制到宿主App/Frameworks目录中 2、对新生成的动态framework进行重签名 其实，还可以有第3件事，就是复制图片等资源文件，不过这就看具体的项目工程了。\ndebug.py中的核心代码\n#!/usr/bin/python # -*- coding: UTF-8 -*- import sys import os CONFIGURATION_BUILD_DIR = sys.argv[1] # 构建产物输出目录 EXPANDED_CODE_SIGN_IDENTITY = sys.argv[2] # 签名证书的十六进制串 # 动态framework路径 frameworkName = xxxxx frameworkPath = xxxxxx # 宿主App的路径 hostAppPath = xxxxxx # 复制framework src = os.path.join(frameworkPath, frameworkName) dst = os.path.jons(hostAppPath,frameworkName ,frameworkName) func_copy(src,dst) # func_copy自定义的复制函数 #复制Info.plist 特别提醒Info.plist里面的内容必须是framework自己的，否则会影响重签名，导致运行失败 src = os.path.join(frameworkPath, \u0026#34;Info.plist\u0026#34;) dst = os.path.jons(hostAppPath,frameworkName ,\u0026#34;Info.plist\u0026#34;) func_copy(src,dst) # func_copy自定义的复制函数 #重签名 dst = dst = os.path.jons(hostAppPath,frameworkName ) os.system(\u0026#34;codesign -f -s 证书标识(十六进制串) \u0026#34; + dst) 脚本中CONFIGURATION_BUILD_DIR和EXPANDED_CODE_SIGN_IDENTITY就是上文提到的 一些参数，需要主动传入，幸好Xcode 提供了环境变量宏，所以Build Phase脚本内容更新如下：\npython $SRCROOT/debuy.py $CONFIGURATION_BUILD_DIR $EXPANDED_CODE_SIGN_IDENTITY 或者 sh $SRCROOT/debug.sh $CONFIGURATION_BUILD_DIR $EXPANDED_CODE_SIGN_IDENTITY 好了，再次点击Xcode Run试试\n","permalink":"https://blog.z6z8.cn/2022/09/05/ios-%E6%97%A0%E5%AE%BF%E4%B8%BBapp%E6%BA%90%E7%A0%81%E6%97%B6%EF%BC%8C%E7%9C%9F%E6%9C%BA%E7%8E%AF%E5%A2%83%E4%B8%80%E9%94%AE%E8%B0%83%E8%AF%95%E5%8A%A8%E6%80%81%E5%BA%93/","summary":"\u003ch1 id=\"背景\"\u003e背景\u003c/h1\u003e\n\u003cp\u003e合作项目，一方提供宿主App，一方提供动态库。双方囿于合规而不能为对方提供源码，所以双方提供的产物都是二进制产物。\n运行时双方融合是没有问题的，但是对开发（尤其是动态库开发方）是不友好的。\u003c/p\u003e\n\u003cp\u003e当然，这场景要是在其他操作系统是没有什么大问题的。但对于iOS而言，因为苹果的硬性限制，真机环境调试是有些麻烦的。为解决开发阶段的调试需求，本文提供了一种思路并实践可行。\u003c/p\u003e\n\u003ch1 id=\"一些准备\"\u003e一些准备\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e开发者证书（调试）是必需的\u003c/li\u003e\n\u003cli\u003eXcode ，本文成文时使用的是13.4.1\u003c/li\u003e\n\u003cli\u003efastlane 工具，本文使用其重签名工具\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"手动调试\"\u003e手动调试\u003c/h1\u003e\n\u003cp\u003e在介绍一键调试前，先大致介绍下如何手动调试。\n若要在真机环境调试，需要先将部署到真机的所有可执行文件进行签名，这包括App主程序和动态framework\u003c/p\u003e\n\u003ch2 id=\"获取开发者证书列表\"\u003e获取开发者证书列表\u003c/h2\u003e\n\u003cp\u003e运行命令，获取可用的证书列表\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esecurity find-identity -v -p codesigning\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e结果一般是十六进制字符串和证书名字，例如\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  1) 十六进制串  \u0026#34;Apple Development: xxxxx(yyyyyyy)\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     1 valid identities found\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"动态库重签名\"\u003e动态库重签名\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecodesign  -f -s 证书标识(十六进制串)   xxxx.framework\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"ipa包重签名\"\u003eipa包重签名\u003c/h2\u003e\n\u003cp\u003e本文使用fastlane工具\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 安装fastlane\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo gem install fastlane\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e安装成功后，执行重签名\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efastlane sigh resign\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#然后安装提示输入ipa包文件路径、证书文件路径\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#期间也可填写证书的十六进制串\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e特别注意：重签名证书必需使用 \u003ccode\u003e开发证书\u003c/code\u003e。\n重签名成功后，获得同名的ipa包，使用Xcode提供的 \u003ccode\u003eDevices and Simulators\u003c/code\u003e 工具将ipa包安装到iPhone真机中\u003c/p\u003e\n\u003ch2 id=\"附加到进程\"\u003e附加到进程\u003c/h2\u003e\n\u003cp\u003e在真机上启动App\n然后使用Xcode 提供的 \u003ccode\u003eDebug -\u0026gt; Attach to Process\u003c/code\u003e 工具，将动态库附加到App进程中，正常情况下是就可以了进行调试了。\u003c/p\u003e\n\u003ch1 id=\"一键调试\"\u003e一键调试\u003c/h1\u003e\n\u003cp\u003e一键调试的原理和过程和手动调试是类似的，只不过把一些工作自动化了\u003c/p\u003e","title":"iOS  无宿主App源码时，真机环境一键调试动态库"},{"content":"一个 set 命令就可以了\n","permalink":"https://blog.z6z8.cn/2022/09/02/macos-shell-%E6%89%93%E5%8D%B0%E6%89%80%E6%9C%89%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F/","summary":"\u003cp\u003e一个 \u003ccode\u003eset\u003c/code\u003e 命令就可以了\u003c/p\u003e","title":"macOS shell 打印所有环境变量"},{"content":"安装准备 1、Windows7 64位 2、Cygwin 64位\n安装Cygwin 在 https://www.cygwin.com/install.html 下载Cygwin的引导安装工具setup-x86_64.exe，打开后选择从网络安装（Install from Internet），国内的话选择mirrors.163.com镜像，之后选择默认配置，然后工具会自动从网络下载所需文件并安装。\n安装Ruby 默认情况下，Cygwin不会自动安装Ruby环境。再次打开setup-x86_64.exe工具，选择Ruby安装包 安装gcc 、g++ 、make 因为Cocoapods的一些依赖是C/C++文件包，所以需要安装编译工具 安装git、curl 虽然安装Cocoapods时不需要这两个工具，但是运行时是需要的\n安装CocoaPods 在Cygwin中运行\ngem install cocoapods # 安装后运行，查看版本 pod --version ","permalink":"https://blog.z6z8.cn/2022/08/14/win7%E5%AE%89%E8%A3%85cocoapods/","summary":"\u003ch1 id=\"安装准备\"\u003e安装准备\u003c/h1\u003e\n\u003cp\u003e1、Windows7 64位\n2、Cygwin 64位\u003c/p\u003e\n\u003ch1 id=\"安装cygwin\"\u003e安装Cygwin\u003c/h1\u003e\n\u003cp\u003e在 \u003ca href=\"https://www.cygwin.com/install.html\"\u003ehttps://www.cygwin.com/install.html\u003c/a\u003e 下载Cygwin的引导安装工具setup-x86_64.exe，打开后选择从网络安装（Install from Internet），国内的话选择mirrors.163.com镜像，之后选择默认配置，然后工具会自动从网络下载所需文件并安装。\u003c/p\u003e\n\u003ch2 id=\"安装ruby\"\u003e安装Ruby\u003c/h2\u003e\n\u003cp\u003e默认情况下，Cygwin不会自动安装Ruby环境。再次打开setup-x86_64.exe工具，选择Ruby安装包\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2022/08/1.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"安装gcc-g-make\"\u003e安装gcc 、g++ 、make\u003c/h2\u003e\n\u003cp\u003e因为Cocoapods的一些依赖是C/C++文件包，所以需要安装编译工具\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2022/08/2.png\"\u003e\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2022/08/3.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"安装gitcurl\"\u003e安装git、curl\u003c/h2\u003e\n\u003cp\u003e虽然安装Cocoapods时不需要这两个工具，但是运行时是需要的\u003c/p\u003e\n\u003ch1 id=\"安装cocoapods\"\u003e安装CocoaPods\u003c/h1\u003e\n\u003cp\u003e在Cygwin中运行\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egem install cocoapods\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 安装后运行，查看版本\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epod --version\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Win7安装CocoaPods"},{"content":"创建增量bundle 创建指定区间的增量bundle\ngit bundle create 文件名.bundle commit_idA..commit_idB 将创建从节点《commit_idA（不含）到节点commit_idB（含）》的增量数据，并存储到 《文件名.bundle》中 验证bundle 验证bundle文件是否匹配当前仓库版本（可以理解为bundle和当前仓库是否有共同的父节点）\ngit bundle verify 文件名.bundle 显示bundle中的引用 git bundle list-heads 文件名.bundle 从bundle中拉取更新 git pull 文件名.bundle bundle中的分支名:本地仓库中的分支名 其中，本地仓库中的分支名可以是《本地的远程分支》，也可以是《本地的本地分支》 ","permalink":"https://blog.z6z8.cn/2022/08/11/git-bundle-%E5%A2%9E%E9%87%8F%E5%90%8C%E6%AD%A5%E4%BB%93%E5%BA%93%E6%95%B0%E6%8D%AE/","summary":"\u003ch1 id=\"创建增量bundle\"\u003e创建增量bundle\u003c/h1\u003e\n\u003cp\u003e创建指定区间的增量bundle\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit bundle create  文件名.bundle  commit_idA..commit_idB\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e将创建从节点《commit_idA（不含）到节点commit_idB（含）》的增量数据，并存储到 《文件名.bundle》中\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"验证bundle\"\u003e验证bundle\u003c/h1\u003e\n\u003cp\u003e验证bundle文件是否匹配当前仓库版本（可以理解为bundle和当前仓库是否有共同的父节点）\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit bundle verify 文件名.bundle\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"显示bundle中的引用\"\u003e显示bundle中的引用\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit bundle list-heads 文件名.bundle\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"从bundle中拉取更新\"\u003e从bundle中拉取更新\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit pull  文件名.bundle  bundle中的分支名:本地仓库中的分支名\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e其中，本地仓库中的分支名可以是《本地的远程分支》，也可以是《本地的本地分支》\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"git bundle 增量同步仓库数据"},{"content":"近期因为一些原因，从内网传输数据到外网的行为受到限制，便研究了些非正常手段进行数据传输\n使用二维码 原理是在内网系统的屏幕上生成二维码，每秒刷新一次；在外网用拍照或者截屏的方式读取二维码图片，解码为数据。\n单个QR码国际标准二维码，二进制模式最多可存储2953字节，2KB多一点，所以使用二维码进行数据传输其速率应该在几KB/S。\n生成二维码 需要使用 PIL(pillow) 图像库, qrcode 二维码生成库，以及 tkinter UI界面库。 tkinter 默认随Python一起安装。\nfrom PIL import Image, ImageTk import qrcode import base64 import tkinter def generateTkImages(data): tkImgs = [] for i in range(4): # 单次生成4张二维码图片，这里需要自己根据屏幕适配 content = b\u0026#39;需要传输的数据\u0026#39; #理论上不需要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(\u0026#39;1030x550+0+0\u0026#39;) app = QrApp(root) root.after(500,app.test) root.mainloop() 二维码解码 本文使用 pyzbar 解码，图片来自截屏\nfrom pyzbar import pyzbar from PIL import ImageGrab import base64 # 截屏 img = ImageGrab.grab() #使用pyzbar扫描并解码 barcodes = pyzbar.decode(img,symbols=[pyzbar.ZBarSymbol.QRCODE]) for j in barcodes: data = j.data.decode(\u0026#34;utf-8\u0026#34;) data = base64.b64decode(data) print(data) 使用音频 使用音频传输数据的思路是，用波形的高低代表0和1 ，将数据转换成音频文件，并播放出来，然后录音，最后分析录音文件，并还原为数据。\n理论上，44100采样率的音频每秒传输数据极限不超过 44100 / 8 = 5512字节，实际上音频播放时和录音时会有不同程度的音频比特丢失，所以实际传输速率会受影响；而为保证传输精度，单个数据比特需要占有将连续的相邻音频比特，也就是多个音频比特才能表示一个数据比特，所以实际传输速率会更低。\n生成Wave文件 import wave data = b\u0026#34;数据\u0026#34; audioBits = [] for Byte in range(len(data)): for i in range(8): bit = (Byte \u0026gt;\u0026gt; (7-i)) \u0026amp; 1 for k in range(30): #每30个音频比特表示一个数据比特，这里需要根据录音精度调整 audioBits.append( 255 * bit ) wavPath = \u0026#34;wave音频文件存储路径\u0026#34; with wave.open(wavPath,\u0026#34;wb\u0026#34;) as fd: fd.setparams((1,1,44100,44100,\u0026#34;NONE\u0026#34;,\u0026#34;not compressed\u0026#34;)) fd.writeframes(bits) Windows 录音 使用 pyaudio\nimport pyaudio import wave #获取录音设备序号 def findRecordingDeviceID(pd ): name = \u0026#39;立体声混音\u0026#39; for i in range(pd.get_device_count()): devInfo = pd.get_device_info_by_index(i) if devInfo[\u0026#39;name\u0026#39;].find(name) \u0026gt;=0 and devInfo[\u0026#39;hostApi\u0026#39;] == 0 : return i return -1 def record() pd = pyaudio.PyAudio() #查找设备 dev_id = findRecordingDeviceID(pd) if dev_id \u0026lt; 0 : print(\u0026#39;无法找到录音设备!\u0026#39;) return #打开设备 record_stream = pd.open(input_device_index=dev_id, format=pyaudio.paInt16, channels=1, rate=44100, input=True, frames_per_buffer=1024) #循环读取流 frames = [] while(True): data = record_stream.read(1024) frames.append(data) if (len(frames) \u0026gt; 1000): # 设置停止条件，这里只是演示 break #停止读取流 record_stream.stop_stream() #关闭流 record_stream.close() #停止资源占用 pd.terminate() wavPath = \u0026#34;wave音频文件存储路径\u0026#34; with wave.open(wavPath,\u0026#34;wb\u0026#34;) as fd: fd.setparams((1,1,44100,44100,\u0026#34;NONE\u0026#34;,\u0026#34;not compressed\u0026#34;)) fd.writeframes(b\u0026#39;\u0026#39;.join(frames)) 解码Wave为数据 示意代码\nwavPath = \u0026#34;wave音频文件存储路径\u0026#34; song = wave.open(wavPath) frame_bytes = song.readframes(song.getnframes()) # 需要先检测音频比特的有效开端，例如连续100个高波形作为开端，后面为有效传输 # 假设已经检测到有效传输 sz = len(frame_bytes) offset = 0 bits = [] while sz \u0026gt;= 30: sum = 0 for k in range(30): sum += frame_bytes[offset+k] if (sum / 30) \u0026gt; 50: # 这里认为大于50就是 bit 1 bits.append(1) else: bits.append(0) sz -= 30 offset += 30 把比特流转换为字节（略） ","permalink":"https://blog.z6z8.cn/2022/08/10/python%E4%BD%BF%E7%94%A8%E5%9B%BE%E7%89%87%E3%80%81%E9%9F%B3%E9%A2%91%E7%AD%89%E4%BC%A0%E8%BE%93%E6%95%B0%E6%8D%AE/","summary":"\u003cp\u003e近期因为一些原因，从内网传输数据到外网的行为受到限制，便研究了些非正常手段进行数据传输\u003c/p\u003e\n\u003ch1 id=\"使用二维码\"\u003e使用二维码\u003c/h1\u003e\n\u003cp\u003e原理是在内网系统的屏幕上生成二维码，每秒刷新一次；在外网用拍照或者截屏的方式读取二维码图片，解码为数据。\u003c/p\u003e\n\u003cp\u003e单个QR码国际标准二维码，二进制模式最多可存储2953字节，2KB多一点，所以使用二维码进行数据传输其速率应该在几KB/S。\u003c/p\u003e\n\u003ch2 id=\"生成二维码\"\u003e生成二维码\u003c/h2\u003e\n\u003cp\u003e需要使用 \u003ccode\u003ePIL(pillow)\u003c/code\u003e 图像库, \u003ccode\u003eqrcode\u003c/code\u003e 二维码生成库，以及 \u003ccode\u003etkinter\u003c/code\u003e UI界面库。 \u003ccode\u003etkinter\u003c/code\u003e 默认随Python一起安装。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003efrom\u003c/span\u003e PIL \u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e Image, ImageTk\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e qrcode\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e base64\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e tkinter\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e  \u003cspan style=\"color:#a6e22e\"\u003egenerateTkImages\u003c/span\u003e(data):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    tkImgs \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e []\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e range(\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e):  \u003cspan style=\"color:#75715e\"\u003e# 单次生成4张二维码图片，这里需要自己根据屏幕适配\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        content  \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003eb\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;需要传输的数据\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e#理论上不需要base64编码，但是实际测试使用pyzbar解码字节流二维码时会乱码，所以使用base64将字节流转为字符串\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        bs \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e base64\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eb64encode(content)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e#创建二维码容器，指定单个区块尺寸和边框尺寸\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        qr \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e qrcode\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eQRCode(box_size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e,border \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e#添加数据\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        qr\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eadd_data(bs)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e#生成二维码图片\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        img \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e qr\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003emake_image()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e#转换成tkinter支持的图像\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        tkImg \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ImageTk\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ePhotoImage(image \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e img)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        tkImgs\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eappend(tkImg) \u003cspan style=\"color:#75715e\"\u003e# 使用数组存储，避免因为tkinter的bug只显示最后一张\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e tkImgs\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eQrApp\u003c/span\u003e(tkinter\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eFrame):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__init__\u003c/span\u003e(self,master \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eNone\u003c/span\u003e):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        super()\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003e__init__\u003c/span\u003e(master)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003emaster \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e master\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epack()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003elabels \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e []\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e range(\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            lb \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e tkinter\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eLabel(self)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            lb\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003egrid(row \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e int(i \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) , column \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e ) \u003cspan style=\"color:#75715e\"\u003e# 2行 2 列\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003elabels\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eappend(lb)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e  \u003cspan style=\"color:#a6e22e\"\u003etest\u003c/span\u003e(self):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        tkImgs \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e generateTkImages(需要传输的数据)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e range(\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003elabels[i]\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003econfigure(image\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003etkImgs[i])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003emaster\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eupdate() \u003cspan style=\"color:#75715e\"\u003e#更新界面\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003emaster\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eafter(\u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e) \u003cspan style=\"color:#75715e\"\u003e# 保持1000毫秒\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eroot \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e tkinter\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eTk()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eroot\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003egeometry(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;1030x550+0+0\u0026#39;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e QrApp(root)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eroot\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eafter(\u003cspan style=\"color:#ae81ff\"\u003e500\u003c/span\u003e,app\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etest)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eroot\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003emainloop()\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"二维码解码\"\u003e二维码解码\u003c/h2\u003e\n\u003cp\u003e本文使用 \u003ccode\u003epyzbar\u003c/code\u003e 解码，图片来自截屏\u003c/p\u003e","title":"Python使用图片、音频等传输数据"},{"content":"注意，本文的部分操作需要使用MacOSX操作系统，以用来将dmg文件转换为iso/cdr格式的光盘镜像\n操作环境 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中安装，过程略。\n安装VirtualBox扩展 打开VirtualBox，按照以下操作路径安装扩展包\n管理 -\u0026gt; 全局设定 -\u0026gt; 扩展 -\u0026gt; 右侧的添加新包按钮\n创建ISO/CDR光盘镜像 本文在macOS 12环境中操作。\n将dmg安装镜像复制到应用程序中 本文使用 macOS Monterey 12.4 21F79 Installer for CLOVER 5142 and FirPE.dmg 安装镜像，双击打开，找到 安装macOS Monterey，然后整体拖拽到应用程序路径(/Applications)\n理论上这个步骤不是必须的，但是本文测试中发现不在/Applications路径时，后续操作出现异常。\n创建 安装macOS Monterey 的可引导镜像 使用hdiutil命令(可参考 通过 macOS 安装器制作 macOS 安装镜像（可用虚拟机及黑苹果等）)\n//创建空白磁盘镜像 此处开辟了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 ，创建虚拟机\n关键配置（其他默认）： CPU 4核 RAM 8G 显存 128M 磁盘空间 80G 取消软驱启动 启用EFI 使用USB 3.0控制器 执行VirtualBox Code 此操作在Windows环境之行，且为必要步骤\ncd \u0026#34;C:\\Program Files\\Oracle\\VirtualBox\\\u0026#34; VBoxManage.exe modifyvm \u0026#34;虛擬機名稱\u0026#34; --cpuidset 00000001 000106e5 00100800 0098e3fd bfebfbff VBoxManage setextradata \u0026#34;虛擬機名稱\u0026#34; VBoxInternal/Devices/efi/0/Config/DmiSystemProduct “MacBookPro15,1” VBoxManage setextradata \u0026#34;虛擬機名稱\u0026#34; \u0026#34;VBoxInternal/Devices/efi/0/Config/DmiBoardProduct\u0026#34; \u0026#34;Mac-551B86E5744E2388\u0026#34; VBoxManage setextradata \u0026#34;虛擬機名稱\u0026#34; \u0026#34;VBoxInternal/Devices/smc/0/Config/DeviceKey\u0026#34; \u0026#34;ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc\u0026#34; VBoxManage setextradata \u0026#34;虛擬機名稱\u0026#34; \u0026#34;VBoxInternal/Devices/smc/0/Config/GetKeyFromRealSMC\u0026#34; 1 # 如果是使用 AMD CPU 的電腦，請多加入下面這一行。 VBoxManage modifyvm \u0026#34;虛擬機名稱\u0026#34; --cpu-profile \u0026#34;Intel Core i7-6700K\u0026#34; 挂在光盘镜像，启动虚拟机 将制作好的ISO/CDR光盘镜像挂载到虚拟机，并设置为第一启动顺序，然后启动虚拟机。正常情况下，可以看到macOS安装引导页面\n格式化磁盘 在安装引导页面，选择 磁盘工具，抹除上述创建的80G虚拟磁盘数据，格式为 Mac OS扩展（日志格式），方案为 GUID分区图，完成后关闭磁盘工具\n安装macOS 在安装引导页面，选择 安装macOS xxxxx，等待之行吧\n参考 Win10安装最新版（macOS Monterey 12.0.1）黑苹果虚拟机\n10分鐘學會如何在 VirtualBox 安裝 macOS Monterey！\n通过 macOS 安装器制作 macOS 安装镜像（可用虚拟机及黑苹果等）\n","permalink":"https://blog.z6z8.cn/2022/07/18/windows-10-%E4%BD%BF%E7%94%A8virtualbox%E5%AE%89%E8%A3%85-macos-monterey/","summary":"\u003cp\u003e\u003ccode\u003e注意，本文的部分操作需要使用MacOSX操作系统，以用来将dmg文件转换为iso/cdr格式的光盘镜像\u003c/code\u003e\u003c/p\u003e\n\u003ch1 id=\"操作环境\"\u003e操作环境\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003eWindows 10\u003c/li\u003e\n\u003cli\u003emacOS 12\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"下载工具\"\u003e下载工具\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e这里下载 \u003ca href=\"https://mirrors.dtops.cc/ISO/MacOS/\"\u003ehttps://mirrors.dtops.cc/ISO/MacOS/\u003c/a\u003e dmg格式的安装包\u003c/li\u003e\n\u003cli\u003e这里下载 \u003ca href=\"https://www.virtualbox.org/wiki/Downloads\"\u003ehttps://www.virtualbox.org/wiki/Downloads\u003c/a\u003e VirtualBox platform packages安装包和 和 Oracle VM VirtualBox Extension Pack扩展包\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"安装virtualbox\"\u003e安装VirtualBox\u003c/h1\u003e\n\u003cp\u003e在Windows 10中安装，过程略。\u003c/p\u003e\n\u003ch2 id=\"安装virtualbox扩展\"\u003e安装VirtualBox扩展\u003c/h2\u003e\n\u003cp\u003e打开VirtualBox，按照以下操作路径安装扩展包\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003e管理 -\u0026gt; 全局设定 -\u0026gt; 扩展 -\u0026gt; 右侧的添加新包按钮\u003c/code\u003e\u003c/p\u003e\n\u003ch1 id=\"创建isocdr光盘镜像\"\u003e创建ISO/CDR光盘镜像\u003c/h1\u003e\n\u003cp\u003e本文在macOS 12环境中操作。\u003c/p\u003e\n\u003ch2 id=\"将dmg安装镜像复制到应用程序中\"\u003e将dmg安装镜像复制到应用程序中\u003c/h2\u003e\n\u003cp\u003e本文使用 \u003ccode\u003emacOS Monterey 12.4 21F79 Installer for CLOVER 5142 and FirPE.dmg\u003c/code\u003e 安装镜像，双击打开，找到 \u003ccode\u003e安装macOS Monterey\u003c/code\u003e，然后整体拖拽到应用程序路径(/Applications)\u003c/p\u003e\n\u003cp\u003e理论上这个步骤不是必须的，但是本文测试中发现不在/Applications路径时，后续操作出现异常。\u003c/p\u003e\n\u003ch2 id=\"创建-安装macos-monterey-的可引导镜像\"\u003e创建 \u003ccode\u003e安装macOS Monterey\u003c/code\u003e 的可引导镜像\u003c/h2\u003e\n\u003cp\u003e使用hdiutil命令(可参考 \u003ca href=\"https://zhuanlan.zhihu.com/p/151326765\"\u003e通过 macOS 安装器制作 macOS 安装镜像（可用虚拟机及黑苹果等）\u003c/a\u003e)\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e//创建空白磁盘镜像  此处开辟了14G多的空白空间。空间大小可以自己调整\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// monterey 为镜像名称\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehdiutil create -o /tmp/monterey -size 14500m -volname monterey -layout SPUD -fs HFS+J\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e//将monterey.dmg镜像挂载为monterey卷\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehdiutil attach /tmp/monterey.dmg -noverify -mountpoint /Volumes/monterey\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e//将应用程序（/Applications）内的安装包制作成可引导的安装盘\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo /Applications/Install\u003cspan style=\"color:#ae81ff\"\u003e\\ \u003c/span\u003emacOS\u003cspan style=\"color:#ae81ff\"\u003e\\ \u003c/span\u003eMonterey\u003cspan style=\"color:#ae81ff\"\u003e\\ \u003c/span\u003ebeta.app/Contents/Resources/createinstallmedia --volume /Volumes/monterey --nointeraction\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e//将安装盘数据刻录为iso/cdr光盘镜像\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehdiutil convert /tmp/monterey.dmg -format UDTO -o ~/Desktop/monterey.cdr\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"创建macos虚拟机\"\u003e创建macOS虚拟机\u003c/h1\u003e\n\u003cp\u003e打开VirtualBox ，创建虚拟机\u003c/p\u003e","title":"Windows 10 使用VirtualBox安装 MacOS Monterey"},{"content":"背景 ​ 本文将介绍一种在有源码的情况下，新老版本静态SDK共存于同一应用的方法实现。\n​ 静态SDK升级并上线后，可能会发现新版本SDK有问题而老版本SDK没有问题的现象，这时对于已经升级的应用将无法直接回退到老版本SDK，除非一开始就新老版本SDK同时存在于这个应用中。\n​ 对于Objiective-C这种没有命名空间的语言，当一份代码构建出两个静态库，且两个静态库同时链接于同一个应用时（同一个应用同时链接这个两个静态库），那么将会发生符号冲突问题\u0026mdash;-符号重定义（duplicate symbol）；而解决符号重定义的办法就是将符号重命名，当然删除符号也可以\u0026mdash;-不过这样可能引起符号为定义错误。\n​ 就Objiective-C而言，符号重命名需要修改源码。对于静态SDK工程来说，第一步是需要先将类名、函数名、全局变量名这些符号列举出来，然后逐一添加前缀或者后缀， 对于影响业务逻辑的地方还需要斟酌修改，特别是Objiective-C的运行时反射更要注意。例如像NSClassFromString，相关代码添加前缀或者后缀要仔细。\n模块化拆分 ​ 这步骤不是必须，但是强烈推荐的。\n​ 就双静态SDK共存这事来看，模块化拆分的唯一目的是减少需要修改的符号数量：例如，通常情况下像AFNetworking这种工具库是没有必要添加前缀或者后缀的。\n​ 所以，拆分的唯一原则：将长期不修改的代码拆分出来，这部分可以作为双SDK的公共库。\n导出符号列表 ​ 常见的方法是使用 nm 工具，可以导出SDK里的符号列表。也可采用分析 linkmap 文件的方式，导出SDK里的符号列表。\n​ 需要导出的符号有：\n类名\n函数名\u0026mdash;非类所属\n全局变量名\n导出的全局变量名如果是静态变量名，一般不需要添加前缀或者后缀。不一般的情况，非静态全局变量引用了静态变量，这时就要处理下。\n添加前缀或者后缀 ​ 这里推荐使用预编译宏技术，定义一个宏并使用 ## 连接符\n#define SUFX (x) x##_我是后缀 // 类 @interface SUFX(MyClass) ---\u0026gt; @interface MyClass_我是后缀 [SUFX(MyClass) method] ---\u0026gt; [MyClass_我是后缀 method] // 函数 void SUFX(MyFunc) ---\u0026gt; void MyFunc_我是后缀 //变量 int SUFX(MyVar) ---\u0026gt; int MyVar_我是后缀 给Objective-C添加命名空间？ 最后，介绍下llvm编译插件，增加命名空间语法支持，从根本上解决问题。不过，尚未完成。。。\nhttps://github.com/kylesluder/objc-namespaces\n","permalink":"https://blog.z6z8.cn/2022/06/17/objective-c-%E6%96%B0%E8%80%81%E9%9D%99%E6%80%81sdk%E5%85%B1%E5%AD%98%E6%96%B9%E6%A1%88/","summary":"\u003ch1 id=\"背景\"\u003e背景\u003c/h1\u003e\n\u003cp\u003e​ 本文将介绍一种在有源码的情况下，新老版本静态SDK共存于同一应用的方法实现。\u003c/p\u003e\n\u003cp\u003e​ 静态SDK升级并上线后，可能会发现新版本SDK有问题而老版本SDK没有问题的现象，这时对于已经升级的应用将无法直接回退到老版本SDK，除非一开始就新老版本SDK同时存在于这个应用中。\u003c/p\u003e\n\u003cp\u003e​ 对于Objiective-C这种没有命名空间的语言，当一份代码构建出两个静态库，且两个静态库同时链接于同一个应用时（同一个应用同时链接这个两个静态库），那么将会发生符号冲突问题\u0026mdash;-符号重定义（duplicate symbol）；而解决符号重定义的办法就是将符号重命名，当然删除符号也可以\u0026mdash;-不过这样可能引起符号为定义错误。\u003c/p\u003e\n\u003cp\u003e​ 就Objiective-C而言，符号重命名需要修改源码。对于静态SDK工程来说，第一步是需要先将类名、函数名、全局变量名这些符号列举出来，然后逐一添加前缀或者后缀， \u003ccode\u003e对于影响业务逻辑的地方还需要斟酌修改，特别是Objiective-C的运行时反射更要注意。例如像NSClassFromString，相关代码添加前缀或者后缀要仔细\u003c/code\u003e。\u003c/p\u003e\n\u003ch1 id=\"模块化拆分\"\u003e模块化拆分\u003c/h1\u003e\n\u003cp\u003e​ 这步骤不是必须，但是强烈推荐的。\u003c/p\u003e\n\u003cp\u003e​ 就双静态SDK共存这事来看，模块化拆分的唯一目的是减少需要修改的符号数量：例如，通常情况下像AFNetworking这种工具库是没有必要添加前缀或者后缀的。\u003c/p\u003e\n\u003cp\u003e​ 所以，拆分的唯一原则：将长期不修改的代码拆分出来，这部分可以作为双SDK的公共库。\u003c/p\u003e\n\u003ch1 id=\"导出符号列表\"\u003e导出符号列表\u003c/h1\u003e\n\u003cp\u003e​ 常见的方法是使用 \u003ccode\u003enm\u003c/code\u003e 工具，可以导出SDK里的符号列表。也可采用分析 \u003ccode\u003elinkmap\u003c/code\u003e 文件的方式，导出SDK里的符号列表。\u003c/p\u003e\n\u003cp\u003e​ 需要导出的符号有：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e类名\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e函数名\u0026mdash;非类所属\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e全局变量名\u003c/p\u003e\n\u003cp\u003e导出的全局变量名如果是静态变量名，一般不需要添加前缀或者后缀。不一般的情况，非静态全局变量引用了静态变量，这时就要处理下。\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"添加前缀或者后缀\"\u003e添加前缀或者后缀\u003c/h1\u003e\n\u003cp\u003e​ 这里推荐使用预编译宏技术，定义一个宏并使用 \u003ccode\u003e##\u003c/code\u003e 连接符\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#define SUFX (x)  x##_我是后缀\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// 类\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e@interface SUFX(MyClass)   ---\u0026gt;  @interface  MyClass_我是后缀\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[SUFX(MyClass)  method]    ---\u0026gt;  [MyClass_我是后缀  method]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// 函数\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003evoid SUFX(MyFunc)            ---\u0026gt;  void MyFunc_我是后缀\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e//变量\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eint SUFX(MyVar)                  ---\u0026gt;  int MyVar_我是后缀\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"给objective-c添加命名空间\"\u003e给Objective-C添加命名空间？\u003c/h1\u003e\n\u003cp\u003e最后，介绍下llvm编译插件，增加命名空间语法支持，从根本上解决问题。不过，尚未完成。。。\u003c/p\u003e","title":"Objective-C 新老静态SDK共存方案"},{"content":"查阅资料，找到以下 使用https://caniuse.com/ 数据， 对应的在线工具为 https://seedmanc.github.io/jscc/ 。不过，这个在线工具还有待完善，检查结果漏了很多。\n另外一个是，基于eslint的兼容性检查插件， https://github.com/amilajack/eslint-plugin-compat ，推荐使用这个，可以配置各种浏览器、语法版本、很灵活\n","permalink":"https://blog.z6z8.cn/2022/05/26/javascript%E5%85%BC%E5%AE%B9%E6%80%A7%E6%A3%80%E6%9F%A5javascript-compatibility-check/","summary":"\u003cp\u003e查阅资料，找到以下\n使用https://caniuse.com/ 数据， 对应的在线工具为 \u003ca href=\"https://seedmanc.github.io/jscc/\"\u003ehttps://seedmanc.github.io/jscc/\u003c/a\u003e 。不过，这个在线工具还有待完善，检查结果漏了很多。\u003c/p\u003e\n\u003cp\u003e另外一个是，基于eslint的兼容性检查插件， \u003ca href=\"https://github.com/amilajack/eslint-plugin-compat\"\u003ehttps://github.com/amilajack/eslint-plugin-compat\u003c/a\u003e ，推荐使用这个，可以配置各种浏览器、语法版本、很灵活\u003c/p\u003e","title":"JavaScript兼容性检查(JavaScript compatibility check)"},{"content":"内容来自互联网，使用了google翻译。\n简介 ​ 在iOS中，音频焦点是操作系统为了管理音频硬件而引入的概念，是指App对音频硬件在时间纬度上的使用控制（不是使用权限，使用权限需要App单独申请）；App可以独占使用，也可以共享使用\u0026mdash;-独占/共享音频焦点。\n​ 独占音频焦点，则只能有一个App使用音频硬件；共享音频焦点，则多个App可以同时使用音频硬件，通常共享音频焦点会导致多个App播放的音频被混音。\n​ iOS中还有个音频会话的概念，在一个App中只有一个音频会话。这里需要注意下，iOS系统只有一个音频焦点，所以App要想使用音频硬件，需要使用音频会话来抢占音频焦点。\n​ 抢占音频焦点示例：\n// 一个App内所有场景/任务都共享同一个音频会话 AVAudioSession *session = [AVAudioSession sharedInstance]; //获取共享单例 //设置音频硬件使用模式 NSError *error = nil; if ([session setCategory:AVAudioSessionCategoryAmbient error:\u0026amp;error] == NO) { NSLog(@\u0026#34;%@\u0026#34;,error); //发生错误 return; } //抢占音频焦点 error = nil; if ([session setActive:YES error:\u0026amp;error] == NO) { NSLog(@\u0026#34;%@\u0026#34;,error); //发生错误 return; } ​ 上述代码中，先设置 AVAudioSessionCategoryAmbient 模式，表示应用会随着静音键和屏幕关闭而静音，并且不会中止其它应用播放声音（可以和其它自带应用如iPod，safari等同时播放声音），然后再使用 setActive 抢占音频焦点。\n释放音频焦点 ​ 我们的App抢占音频焦点后，可能会导致其他App失去音频焦点，所以当我们使用完音频硬件时，应将音频焦点释放出来。\n// 一个App内所有场景/任务都共享同一个音频会话 AVAudioSession *session = [AVAudioSession sharedInstance]; //获取共享单例 //释放音频焦点 NSError *error = nil; if ([session setActive:NO error:\u0026amp;error] == NO) { NSLog(@\u0026#34;%@\u0026#34;,error); //发生错误 return; } 释放音频焦点还可以这样：\n//也可以这样释放音频焦点, 为了确保之前被打断的正在播放音频的App能收到resume消息。 if ([session setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:\u0026amp;error] == NO ) { NSLog(@\u0026#34;%@\u0026#34;,error); //发生错误 return; } 使用哪种方式，取决于App的音频硬件使用模式。\n音频硬件使用模式 设置接口有两个，都可以设置音频使用模式。相关参数为AVAudioSessionCategory和AVAudioSessionCategoryOptions。需要注意的是，AVAudioSessionCategoryOptions是 位枚举，可以组合使用。\n- (BOOL)setCategory:(AVAudioSessionCategory)category error:(NSError **)outError; - (BOOL)setCategory:(AVAudioSessionCategory)category withOptions:(AVAudioSessionCategoryOptions)options error:(NSError **)outError; AVAudioSessionCategory AVAudioSessionCategoryAmbient\n使用这个category的应用会随着静音键和屏幕关闭而静音。并且不会中止其它应用播放声音，可以和其它自带应用如iPod，safari等同时播放声音。\n该Category无法在后台播放声音。\nAVAudioSessionCategorySoloAmbient\n类似于AVAudioSessionCategoryAmbient ，不同之处在于它会中止其它应用播放声音。 这个category为默认category。\n该Category无法在后台播放声音。\nAVAudioSessionCategoryPlayback\n使用这个category的应用不会随着静音键和屏幕关闭而静音。默认情况下，其他不支持混音（nonmixable）的应用将被中止播放声音；也可以设置 AVAudioSessionCategoryOptionMixWithOthers，让自己的应用支持混音，这时不会中止其他不支持混音的应用播放声音；\n该Category可在后台播放声音。\nAVAudioSessionCategoryRecord\n用于需要录音的场景，设置该category后，除了来电铃声，闹钟或日历提醒之外的其它系统声音都不会被播放。\n该Category只提供单纯录音功能，可以在后台录音。\nAVAudioSessionCategoryPlayAndRecord\n在播放和录音同时存在的场景，这个category是唯一选择，应用不会随着静音键和屏幕关闭而静音。默认情况下，其他不支持混音（nonmixable）的应用将被中止播放声音；也可以设置 AVAudioSessionCategoryOptionMixWithOthers，让自己的应用支持混音，这时不会中止其他不支持混音的应用播放声音\n该Category可以在后台录音、播放声音。\nAVAudioSessionCategoryMultiRoute\n非专业场景基本上不会使用。支持多个音频路由同时工作。例如，手机扬声器播放歌曲A，同时连接该手机的耳机中播放歌曲B。\nAVAudioSessionCategoryOptions AVAudioSessionCategoryOptionMixWithOthers\n播放声音时，支持和其他App混音。\n仅在AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryPlayback 或 AVAudioSessionCategoryMultiRoute 时，才可以设置这个选项。\n如果音频使用模式设置为 AVAudioSessionCategoryAmbient，则会自动设置此选项。 同样，设置 AVAudioSessionCategoryOptionDuckOthers 或 AVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers 选项也会启用此选项。\nAVAudioSessionCategoryOptionDuckOthers\n播放声音时，支持和其他App混音，但是会降低其他App播放的声音。可以用在偶尔播放音频的场景，如导航播报。\n仅在AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryPlayback 或 AVAudioSessionCategoryMultiRoute 时，才可以设置此选项。\nAVAudioSessionCategoryOptionAllowBluetooth\n支持蓝牙设备作为输入（这应指录音）。\n仅 AVAudioSessionCategoryPlayAndRecord 或 AVAudioSessionCategoryRecord 时，才能设置此选项。\nAVAudioSessionCategoryOptionDefaultToSpeaker\n在没有其他音频设备时，使用内置扬声器播。\n其他音频设备如耳机，会影响该选项，当耳机插入时，音频路由会转向耳机麦克风/耳机；拔出耳机时，音频路由则恢复到内置麦克风/内置扬声器。\n只有在使用 AVAudioSessionCategoryPlayAndRecord 时才能设置此选项\nAVAudioSessionCategoryOptionInterruptSpokenAudioAndMixWithOthers\niOS9及以上可用，播放音频时暂停来自其他App音频播放(注意，暂停而不是中止)，播放完成释放音频焦点后，系统会恢复其他App的音频播放。\n可以用在偶尔播放音频的场景，如导航播报。\n仅当 AVAudioSessionCategoryPlayAndRecord、AVAudioSessionCategoryPlayback 或 AVAudioSessionCategoryMultiRoute 时，才能设置此选项。\nAVAudioSessionCategoryOptionAllowBluetoothA2DP\niOS10及以上可用，支持A2DP的蓝牙设备。\n如果将应用程序配置为 AVAudioSessionCategoryAmbient、AVAudioSessionCategorySoloAmbient 或 AVAudioSessionCategoryPlayback 类别，系统会自动路由到 A2DP 端口。\n从 iOS10开始，使用 AVAudioSessionCategoryPlayAndRecord 的应用程序允许将输出路由到配对的蓝牙 A2DP 设备。\n要启用此行为，请在设置音频会话的类别时传递此类别选项。\n使用 AVAudioSessionCategoryMultiRoute 或 AVAudioSessionCategoryRecord 时，会隐式清除此选项（将不可使用A2DP设备）\nAVAudioSessionCategoryOptionAllowAirPlay\niOS10及以上可用，支持AirPlay设备。\n如果设置了 AVAudioSessionCategoryPlayAndRecord，那么需要显式设置此选项才支持AirPlay。\n对于其他大多数音频使用模式，系统会隐式设置此选项；例外是AVAudioSessionCategoryMultiRoute 和 AVAudioSessionCategoryRecord ，这两个会隐式清除此选项。\nAVAudioSessionCategoryOptionOverrideMutedMicrophoneInterruption\niOS14.5及以上可用，出于隐私考虑，系统在静音时使内置麦克风会中断录制。\n当使用AVAudioSessionCategoryPlayAndRecord且开启了该选项，那么在静音时，播放将照常继续，但是麦克风中断录制（硬件会生成样本缓冲区，但值为 0）。\n音频焦点使用原则 App使用音频焦点的原则:\n谁使用谁抢占，使用完毕后要释放; 最小限度的音频模式。不要申请不必要的硬件资源，例如在听音乐场景申请麦克风是不必要的。 // 一个App内所有场景/任务都共享同一个音频会话 AVAudioSession *session = [AVAudioSession sharedInstance]; //获取共享单例 //当前音频模式 AVAudioSessionCategory lastCategory = session.category; AVAudioSessionCategoryOptions lastCategoryOptions = session.categoryOptions; if(音频模式是否满足场景需要) { //需要修改音频模式 NSError *error = nil; if ([session setCategory:按需要设置 withOptions:按需要设置 error:\u0026amp;error] == NO) { //发生错误,异常处理 NSLog(@\u0026#34;%@\u0026#34;,error); return; } //抢占音频焦点 error = nil; if ([session setActive:YES error:\u0026amp;error] == NO) { //发生错误,异常处理 NSLog(@\u0026#34;%@\u0026#34;,error); return; } } /// 使用音频资源 ///使用完毕后 if(是否需要恢复音频模式) { //需要恢复 NSError *error = nil; if ([session setCategory:lastCategory withOptions:lastCategoryOptions error:\u0026amp;error] == NO) { //发生错误,异常处理 NSLog(@\u0026#34;%@\u0026#34;,error); return; } } /// 没有其他场景需要使用音频焦点了 //释放音频焦点 NSError *error = nil; if ([session setActive:YES error:\u0026amp;error] == NO) { //发生错误,异常处理 NSLog(@\u0026#34;%@\u0026#34;,error); return; } //也可以这样释放音频焦点，这时系统会通知其他App中断结束，可以恢复音频焦点了 //if ([session setActive:NO withOptions:AVAudioSessionSetActiveOptionNotifyOthersOnDeactivation error:\u0026amp;error] == NO ) //{ // NSLog(@\u0026#34;%@\u0026#34;,error); //发生错误 // return; //} 需要注意的是，对于SDK开发来说，因为自身不能完全掌控宿主App，所以使用音频资源时应每次都要抢占音频焦点；而对音频焦点的释放，应提供释放音频焦点的默认实现，同时建议增加接口让供宿主App实现释放动作，以增加宿主App对音频焦点的掌控能力。\n","permalink":"https://blog.z6z8.cn/2022/03/28/ios%E5%85%B3%E4%BA%8E%E9%9F%B3%E9%A2%91%E7%84%A6%E7%82%B9%E7%9A%84%E8%B5%84%E6%96%99%E6%95%B4%E7%90%86/","summary":"\u003cp\u003e内容来自互联网，使用了google翻译。\u003c/p\u003e\n\u003ch1 id=\"简介\"\u003e简介\u003c/h1\u003e\n\u003cp\u003e​ 在iOS中，音频焦点是操作系统为了管理音频硬件而引入的概念，是指App对音频硬件在时间纬度上的使用控制（不是使用权限，使用权限需要App单独申请）；App可以独占使用，也可以共享使用\u0026mdash;-独占/共享音频焦点。\u003c/p\u003e\n\u003cp\u003e​ 独占音频焦点，则只能有一个App使用音频硬件；共享音频焦点，则多个App可以同时使用音频硬件，通常共享音频焦点会导致多个App播放的音频被混音。\u003c/p\u003e\n\u003cp\u003e​ iOS中还有个音频会话的概念，在一个App中只有一个音频会话。这里需要注意下，iOS系统只有一个音频焦点，所以App要想使用音频硬件，需要使用音频会话来抢占音频焦点。\u003c/p\u003e\n\u003cp\u003e​ 抢占音频焦点示例：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objective-c\" data-lang=\"objective-c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 一个App内所有场景/任务都共享同一个音频会话\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003eAVAudioSession \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003esession \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [AVAudioSession sharedInstance]; \u003cspan style=\"color:#75715e\"\u003e//获取共享单例\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//设置音频硬件使用模式\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003eNSError \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eerror \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e nil;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ([session setCategory:AVAudioSessionCategoryAmbient error:\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eerror] \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NO)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSLog(\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;%@\u0026#34;\u003c/span\u003e,error); \u003cspan style=\"color:#75715e\"\u003e//发生错误\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//抢占音频焦点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003eerror \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e nil;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ([session setActive:YES error:\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eerror] \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NO)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSLog(\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;%@\u0026#34;\u003c/span\u003e,error); \u003cspan style=\"color:#75715e\"\u003e//发生错误\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e​ 上述代码中，先设置 \u003ccode\u003eAVAudioSessionCategoryAmbient\u003c/code\u003e 模式，表示应用会随着静音键和屏幕关闭而静音，并且不会中止其它应用播放声音（可以和其它自带应用如iPod，safari等同时播放声音），然后再使用 \u003ccode\u003esetActive\u003c/code\u003e 抢占音频焦点。\u003c/p\u003e\n\u003ch1 id=\"释放音频焦点\"\u003e释放音频焦点\u003c/h1\u003e\n\u003cp\u003e​ 我们的App抢占音频焦点后，可能会导致其他App失去音频焦点，所以当我们使用完音频硬件时，应将音频焦点释放出来。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objective-c\" data-lang=\"objective-c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 一个App内所有场景/任务都共享同一个音频会话\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003eAVAudioSession \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003esession \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [AVAudioSession sharedInstance]; \u003cspan style=\"color:#75715e\"\u003e//获取共享单例\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//释放音频焦点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003eNSError \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eerror \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e nil;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ([session setActive:NO error:\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eerror] \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NO)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSLog(\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;%@\u0026#34;\u003c/span\u003e,error); \u003cspan style=\"color:#75715e\"\u003e//发生错误\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e释放音频焦点还可以这样：\u003c/p\u003e","title":"iOS关于音频焦点的资料整理"},{"content":"本次着手实现将 target=\u0026quot;_blank\u0026ldquo;的行为修改为 target=\u0026quot;_self\u0026quot;。\nCEF3提供了UI窗口生命周期接口 CefLifeSpanHandler，借助这个接口来监听新窗口创建事件，并在创建前取消窗口创建，使用已有窗口来加载新链接。\nclass CefLifeSpanHandler : public virtual CefBaseRefCounted { public: ///由UI线程调用，调用时机是新浏览窗口创建前。 // frame 弹出新窗口链接的源frame（即从哪个frame里的链接弹出新窗口） // target_url 目的链接 // target_frame_name 目的frame名字 // 返回true，则表示要取消窗口创建 virtual bool OnBeforePopup(CefRefPtr browser, CefRefPtr frame, const CefString\u0026amp; target_url, const CefString\u0026amp; target_frame_name, WindowOpenDisposition target_disposition, bool user_gesture, const CefPopupFeatures\u0026amp; popupFeatures, CefWindowInfo\u0026amp; windowInfo, CefRefPtr\u0026amp; client, CefBrowserSettings\u0026amp; settings, CefRefPtr\u0026amp; extra_info, bool* no_javascript_access) { frame-\u0026gt;LoadURL(target_url); //在当前frame中加载链接 return true; //返回true，取消窗口创建 } ","permalink":"https://blog.z6z8.cn/2022/03/23/%E3%80%90cef3%E5%AD%A6%E4%B9%A0%E3%80%91-%E5%9C%A8%E5%90%8C%E4%B8%80%E7%AA%97%E5%8F%A3%E6%89%93%E5%BC%80%E9%93%BE%E6%8E%A5/","summary":"\u003cp\u003e本次着手实现将 \u003ccode\u003etarget=\u0026quot;_blank\u003c/code\u003e\u0026ldquo;的行为修改为 \u003ccode\u003etarget=\u0026quot;_self\u0026quot;\u003c/code\u003e。\u003c/p\u003e\n\u003cp\u003eCEF3提供了UI窗口生命周期接口 \u003ccode\u003eCefLifeSpanHandler\u003c/code\u003e，借助这个接口来监听新窗口创建事件，并在创建前取消窗口创建，使用已有窗口来加载新链接。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-c++\" data-lang=\"c++\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCefLifeSpanHandler\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evirtual\u003c/span\u003e CefBaseRefCounted {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e///由UI线程调用，调用时机是新浏览窗口创建前。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e// frame 弹出新窗口链接的源frame（即从哪个frame里的链接弹出新窗口）\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e// target_url 目的链接\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e// target_frame_name 目的frame名字\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e// 返回true，则表示要取消窗口创建\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e  \u003cspan style=\"color:#66d9ef\"\u003evirtual\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e OnBeforePopup(CefRefPtr browser,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             CefRefPtr frame,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e CefString\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e target_url,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e CefString\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e target_frame_name,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             WindowOpenDisposition target_disposition,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e user_gesture,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e CefPopupFeatures\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e popupFeatures,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             CefWindowInfo\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e windowInfo,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             CefRefPtr\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e client,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             CefBrowserSettings\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e settings,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             CefRefPtr\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e extra_info,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                             \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e no_javascript_access)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    frame\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eLoadURL(target_url); \u003cspan style=\"color:#75715e\"\u003e//在当前frame中加载链接\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e true; \u003cspan style=\"color:#75715e\"\u003e//返回true，取消窗口创建\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"【CEF3学习】– 在同一窗口打开链接"},{"content":"CEF3关于文件下载的开放接口是 CefDownloadHandler，这个类的公开函数也挺简单的，就两个：一个是下载前 OnBeforeDownload，一个是下载状态更新 OnDownloadUpdated\nclass CefDownloadHandler : public virtual CefBaseRefCounted { public: /// 文件下载前调用 // suggested_name （建议的）文件保存名 // callback 回调，用来通知下载动作继续进行。默认情况下，如果不主动调用这个回调，则会取消下载动作。 virtual void OnBeforeDownload( CefRefPtr browser, CefRefPtr download_item, const CefString\u0026amp; suggested_name, CefRefPtr callback) = 0; /// 用来通知下载状态信息，包括下载进度、总大小、已完成大小、是否完成等；这个方法可能会被调用多次，以用来持续更新下载状态 // download_item 下载项，下载的状态信息保存在这里。 // callback 回调，用来取消/暂停/恢复/下载。默认情况下，如果不主动调用这个回调，则会继续下载。 virtual void OnDownloadUpdated(CefRefPtr browser, CefRefPtr download_item, CefRefPtr callback) {} }; 需要注意的是，上面两个方法都有一个 download_item 参数，这个参数是不能在上面两个方法的作用域外使用的。\n","permalink":"https://blog.z6z8.cn/2022/03/23/%E3%80%90cef3%E5%AD%A6%E4%B9%A0%E3%80%91-%E6%96%87%E4%BB%B6%E4%B8%8B%E8%BD%BD%E7%AE%A1%E7%90%86/","summary":"\u003cp\u003eCEF3关于文件下载的开放接口是 \u003ccode\u003eCefDownloadHandler\u003c/code\u003e，这个类的公开函数也挺简单的，就两个：一个是下载前 \u003ccode\u003eOnBeforeDownload\u003c/code\u003e，一个是下载状态更新 \u003ccode\u003eOnDownloadUpdated\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-c++\" data-lang=\"c++\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCefDownloadHandler\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evirtual\u003c/span\u003e CefBaseRefCounted {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e/// 文件下载前调用\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e// suggested_name  （建议的）文件保存名\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e// callback  回调，用来通知下载动作继续进行。默认情况下，如果不主动调用这个回调，则会取消下载动作。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e  \u003cspan style=\"color:#66d9ef\"\u003evirtual\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e OnBeforeDownload(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      CefRefPtr browser,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      CefRefPtr download_item,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e CefString\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e suggested_name,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      CefRefPtr callback) \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e/// 用来通知下载状态信息，包括下载进度、总大小、已完成大小、是否完成等；这个方法可能会被调用多次，以用来持续更新下载状态\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e// download_item  下载项，下载的状态信息保存在这里。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e// callback  回调，用来取消/暂停/恢复/下载。默认情况下，如果不主动调用这个回调，则会继续下载。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e  \u003cspan style=\"color:#66d9ef\"\u003evirtual\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eOnDownloadUpdated\u003c/span\u003e(CefRefPtr browser,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                 CefRefPtr download_item,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                 CefRefPtr callback) {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e需要注意的是，上面两个方法都有一个 \u003ccode\u003edownload_item\u003c/code\u003e 参数，这个参数是不能在上面两个方法的作用域外使用的。\u003c/p\u003e","title":"【CEF3学习】-- 文件下载管理"},{"content":"本文要实现的是在 右键菜单 中添加一个修改User-Agent功能 定义一个变量，用来控制是使用默认UA还是Android UA\nstatic bool s_UerAgentAndroid = false; 添加 右键菜单\n// 添加菜单枚举 enum client_menu_ids { CLIENT_ID_SHOW_DEVTOOLS = MENU_ID_USER_FIRST, ... .... CLIENT_ID_UserAnget, }; // 修改菜单项和菜单事件处理 void ClientHandler::OnBeforeContextMenu(CefRefPtr browser, CefRefPtr frame, CefRefPtr params, CefRefPtr model) { ...... ...... //添加菜单项 model-\u0026gt;AddItem(CLIENT_ID_UserAnget, s_UerAgentAndroid ? \u0026#34;默认UA\u0026#34;:\u0026#34;Android UA\u0026#34;); if (delegate_) delegate_-\u0026gt;OnBeforeContextMenu(model); } bool ClientHandler::OnContextMenuCommand(CefRefPtr browser, CefRefPtr frame, CefRefPtr params, int command_id, EventFlags event_flags) { CEF_REQUIRE_UI_THREAD(); switch (command_id) { ...... ...... //菜单事件处理 case CLIENT_ID_UserAnget: s_UerAgentAndroid = !s_UerAgentAndroid; browser-\u0026gt;Reload(); // 修改UA后重新加载网页 return true; default: // Allow default handling, if any. return ExecuteTestMenu(command_id); } } 下面就是对每一个请求修改HTTP报文的User-Agent。CEF3会将网页所有资源请求事件通知给 CefRequestHandler 或其子类处理，其 OnBeforeResourceLoad 是在http请求发出前的处理点，修改相应内容，代码如下\ncef_return_value_t ClientHandler::OnBeforeResourceLoad( CefRefPtr browser, CefRefPtr frame, CefRefPtr request, CefRefPtr callback) { ...... ...... if (s_UerAgentAndroid) { //设置UA字段 request-\u0026gt;SetHeaderByName(\u0026#34;User-Agent\u0026#34;, \u0026#34;Mozilla/5.0 (Android5.1.1)\u0026#34;, true); } return resource_manager_-\u0026gt;OnBeforeResourceLoad(browser, frame, request, callback); } ","permalink":"https://blog.z6z8.cn/2022/03/09/%E3%80%90cef3%E5%AD%A6%E4%B9%A0%E3%80%91-%E4%BF%AE%E6%94%B9user-agent/","summary":"\u003cp\u003e本文要实现的是在 \u003ca href=\"https://139.155.43.7/2022/03/07/%e3%80%90cef3%e5%ad%a6%e4%b9%a0%e3%80%91-%e6%b7%bb%e5%8a%a0%e5%8f%b3%e9%94%ae%e8%8f%9c%e5%8d%95\"\u003e右键菜单\u003c/a\u003e 中添加一个修改User-Agent功能\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2022/03/1-1.png\"\u003e\u003c/p\u003e\n\u003cp\u003e定义一个变量，用来控制是使用默认UA还是Android UA\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-cpp\" data-lang=\"cpp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e s_UerAgentAndroid \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e false;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e添加 \u003ca href=\"https://139.155.43.7/2022/03/07/%e3%80%90cef3%e5%ad%a6%e4%b9%a0%e3%80%91-%e6%b7%bb%e5%8a%a0%e5%8f%b3%e9%94%ae%e8%8f%9c%e5%8d%95\"\u003e右键菜单\u003c/a\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-cpp\" data-lang=\"cpp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 添加菜单枚举\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eenum\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclient_menu_ids\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    CLIENT_ID_SHOW_DEVTOOLS \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e MENU_ID_USER_FIRST,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ....\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    CLIENT_ID_UserAnget,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 修改菜单项和菜单事件处理\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e ClientHandler\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eOnBeforeContextMenu(CefRefPtr browser,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                        CefRefPtr frame,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                        CefRefPtr params,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                        CefRefPtr model) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ......\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ......\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//添加菜单项\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    model\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eAddItem(CLIENT_ID_UserAnget, s_UerAgentAndroid \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;默认UA\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Android UA\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (delegate_)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    delegate_\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eOnBeforeContextMenu(model);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e ClientHandler\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eOnContextMenuCommand(CefRefPtr browser,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                         CefRefPtr frame,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                         CefRefPtr params,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                         \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e command_id,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                         EventFlags event_flags) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  CEF_REQUIRE_UI_THREAD();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eswitch\u003c/span\u003e (command_id) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     ......\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     ......\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#75715e\"\u003e//菜单事件处理\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e CLIENT_ID_UserAnget:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          s_UerAgentAndroid \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003es_UerAgentAndroid;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          browser\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eReload(); \u003cspan style=\"color:#75715e\"\u003e// 修改UA后重新加载网页\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e          \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e true;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e// Allow default handling, if any.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e      \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ExecuteTestMenu(command_id);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e下面就是对每一个请求修改HTTP报文的User-Agent。CEF3会将网页所有资源请求事件通知给 \u003ccode\u003eCefRequestHandler\u003c/code\u003e 或其子类处理，其 \u003ccode\u003eOnBeforeResourceLoad\u003c/code\u003e 是在http请求发出前的处理点，修改相应内容，代码如下\u003c/p\u003e","title":"【CEF3学习】-- 修改User-Agent"},{"content":"cefclient这个项目启动后，默认情况下会有下图所示的右键菜单 我们要做的就是仿照这个菜单，添加新的菜单项。 根据关键字搜索，可以找到client_handler.cpp文件，有两函数 OnBeforeContextMenu、 OnContextMenuCommand，用来处理菜单项。修改这两个函数，增加新的菜单项，例如重新加载当前页面。\n/// enum client_menu_ids { CLIENT_ID_SHOW_DEVTOOLS = MENU_ID_USER_FIRST, .... CLIENT_ID_TESTMENU_RADIOITEM3, CLIENT_ID_RELOAD_PAGE /// 添加一个菜单项枚举 }; void ClientHandler::OnBeforeContextMenu(CefRefPtr browser, CefRefPtr frame, CefRefPtr params, CefRefPtr model) { ///在菜单显示前，处理菜单项 .... model-\u0026gt;AddItem(CLIENT_ID_RELOAD_PAGE, \u0026#34;重新加载页面\u0026#34;); .... } bool ClientHandler::OnContextMenuCommand(CefRefPtr browser, CefRefPtr frame, CefRefPtr params, int command_id, EventFlags event_flags){ ///对应菜单项的响应处理 switch (command_id) { case CLIENT_ID_RELOAD_PAGE: browser-\u0026gt;Reload(); return true; case CLIENT_ID_SHOW_DEVTOOLS: ..... ... } } 至此，添加右键菜单的需求实现了。 再回过来看看 ClientHandler，看它的定义\nclass ClientHandler : public CefClient, public CefContextMenuHandler, public CefDisplayHandler, public CefDownloadHandler, public CefDragHandler, public CefFocusHandler, public CefKeyboardHandler, public CefLifeSpanHandler, public CefLoadHandler, public CefRequestHandler, public CefResourceRequestHandler ClientHandler 采用多继承方式，把上下文菜单、显示状态、下载、拖拽、焦点、键盘等浏览器事件集中起来处理，如果我们要修改相关需求，改变ClientHandler的对应实现就可以了。\n那么ClientHandler是在什么时候注册到事件循环中的？通过断点查看调用栈，大致的过程如下：\nCefBrowserHost::CreateBrowser() 创建浏览器窗口 -\u0026gt; CefClientCppToC::Wrap() -\u0026gt; CefClientCppToC::CefClientCppToC() 设置浏览器的事件处理句柄 -\u0026gt; 进入消息循环 -\u0026gt; 分发消息事件 -\u0026gt; client_get_context_menu_handler() 处理上下文菜单事件 -\u0026gt; CefContextMenuHandlerCppToC::Wrap() -\u0026gt; CefContextMenuHandlerCppToC::CefContextMenuHandlerCppToC() 设置上下文菜单的过程处理句柄（显示前、点击、消失等） -\u0026gt; context_menu_handler_on_before_context_menu() c函数 显示前处理 -\u0026gt; ClientHandler::OnBeforeContextMenu() c++函数 显示前处理\n","permalink":"https://blog.z6z8.cn/2022/03/07/%E3%80%90cef3%E5%AD%A6%E4%B9%A0%E3%80%91-%E6%B7%BB%E5%8A%A0%E5%8F%B3%E9%94%AE%E8%8F%9C%E5%8D%95/","summary":"\u003cp\u003ecefclient这个项目启动后，默认情况下会有下图所示的右键菜单\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2022/03/6.png\"\u003e\u003c/p\u003e\n\u003cp\u003e我们要做的就是仿照这个菜单，添加新的菜单项。\n根据关键字搜索，可以找到client_handler.cpp文件，有两函数 \u003ccode\u003eOnBeforeContextMenu\u003c/code\u003e、 \u003ccode\u003eOnContextMenuCommand\u003c/code\u003e，用来处理菜单项。修改这两个函数，增加新的菜单项，例如重新加载当前页面。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-cpp\" data-lang=\"cpp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e///\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eenum\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclient_menu_ids\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  CLIENT_ID_SHOW_DEVTOOLS \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e MENU_ID_USER_FIRST,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ....\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  CLIENT_ID_TESTMENU_RADIOITEM3,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  CLIENT_ID_RELOAD_PAGE \u003cspan style=\"color:#75715e\"\u003e/// 添加一个菜单项枚举\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e ClientHandler\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eOnBeforeContextMenu(CefRefPtr browser,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                        CefRefPtr frame,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                        CefRefPtr params,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                        CefRefPtr model) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e///在菜单显示前，处理菜单项\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        ....\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          model\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eAddItem(CLIENT_ID_RELOAD_PAGE, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;重新加载页面\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       ....\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e ClientHandler\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eOnContextMenuCommand(CefRefPtr browser,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                         CefRefPtr frame,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                         CefRefPtr params,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                         \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e command_id,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                         EventFlags event_flags){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e///对应菜单项的响应处理\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003eswitch\u003c/span\u003e (command_id) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e CLIENT_ID_RELOAD_PAGE:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       browser\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eReload();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e true;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e CLIENT_ID_SHOW_DEVTOOLS:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     .....\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     ...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2022/03/6-1.png\"\u003e\u003c/p\u003e","title":"【CEF3学习】-- 添加右键菜单"},{"content":"下载下来的CEF压缩包解压后，里面包含CEF接口源码、示例、静态库等资源，并提供cmake脚本文件以生成IDE工程文件；使用CMake UI来操作这些脚本文件。 首先，填写好CEF解压后的路径（包含CMakeLists.txt的目录）,IDE工程文件的输出路径（可以写和CMakeLists.txt相同的目录） 然后，点击 Configure 按钮，配置IDE参数 正常情况下，下图到参数是自动生成的 点击 Generate 按钮，生成IDE工程文件 打开IDE工程文件，直接以Debug模式运行 cefclient 这个项目，可以看到一个十分简单的浏览器页面出现了\n","permalink":"https://blog.z6z8.cn/2022/03/07/%E3%80%90cef3%E5%AD%A6%E4%B9%A0%E3%80%91-%E7%94%9F%E6%88%90ide%E7%9A%84%E5%B7%A5%E7%A8%8B%E6%96%87%E4%BB%B6/","summary":"\u003cp\u003e下载下来的CEF压缩包解压后，里面包含CEF接口源码、示例、静态库等资源，并提供cmake脚本文件以生成IDE工程文件；使用CMake UI来操作这些脚本文件。\n首先，填写好CEF解压后的路径（包含CMakeLists.txt的目录）,IDE工程文件的输出路径（可以写和CMakeLists.txt相同的目录）\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2022/03/1.png\"\u003e\u003c/p\u003e\n\u003cp\u003e然后，点击 \u003ccode\u003eConfigure\u003c/code\u003e 按钮，配置IDE参数\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2022/03/2.png\"\u003e\u003c/p\u003e\n\u003cp\u003e正常情况下，下图到参数是自动生成的\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2022/03/3.png\"\u003e\u003c/p\u003e\n\u003cp\u003e点击 \u003ccode\u003eGenerate\u003c/code\u003e 按钮，生成IDE工程文件\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2022/03/4.png\"\u003e\u003c/p\u003e\n\u003cp\u003e打开IDE工程文件，直接以Debug模式运行 \u003ccode\u003ecefclient\u003c/code\u003e 这个项目，可以看到一个十分简单的浏览器页面出现了\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2022/03/5.png\"\u003e\u003c/p\u003e","title":"【CEF3学习】-- 生成IDE的工程文件"},{"content":"CEF全称Chromium Embedded Framework，是一个基于Google Chromium 的开源项目。相关资料在https://bitbucket.org/chromiumembedded/cef/wiki/Home 中基本都能找到。\n我不选择手动构建，一是因为没有合适的硬件资源，二是构建好的二进制产品可以很方便的从这里下载。 https://cef-builds.spotifycdn.com/index.html\n上面这个网站提供包括32/64位以及RAM架构的CPU下的Linux/MacOS/Windows平台的构建产品； 提供的版本有两种，一种是稳定版本（Current Stable Build (Preferred)），一种是Beta版本（Current Beta Build (For Testing)）。\n本文选择的是MacOS-64-Standard Distribution版本， https://cef-builds.spotifycdn.com/cef_binary_97.1.7%2Bg45ce543%2Bchromium-97.0.4692.99_macosx64.tar.bz2\n","permalink":"https://blog.z6z8.cn/2022/03/07/%E3%80%90cef3%E5%AD%A6%E4%B9%A0%E3%80%91-%E4%B8%8B%E8%BD%BD%E6%9E%84%E5%BB%BA%E5%A5%BD%E7%9A%84%E7%89%88%E6%9C%AC/","summary":"\u003cp\u003eCEF全称Chromium Embedded Framework，是一个基于Google Chromium 的开源项目。相关资料在https://bitbucket.org/chromiumembedded/cef/wiki/Home 中基本都能找到。\u003c/p\u003e\n\u003cp\u003e我不选择手动构建，一是因为没有合适的硬件资源，二是构建好的二进制产品可以很方便的从这里下载。\n\u003ca href=\"https://cef-builds.spotifycdn.com/index.html\"\u003ehttps://cef-builds.spotifycdn.com/index.html\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e上面这个网站提供包括32/64位以及RAM架构的CPU下的Linux/MacOS/Windows平台的构建产品；\n提供的版本有两种，一种是稳定版本（Current Stable Build (Preferred)），一种是Beta版本（Current Beta Build (For Testing)）。\u003c/p\u003e\n\u003cp\u003e本文选择的是MacOS-64-Standard Distribution版本， \u003ca href=\"https://cef-builds.spotifycdn.com/cef_binary_97.1.7%2Bg45ce543%2Bchromium-97.0.4692.99_macosx64.tar.bz2\"\u003ehttps://cef-builds.spotifycdn.com/cef_binary_97.1.7%2Bg45ce543%2Bchromium-97.0.4692.99_macosx64.tar.bz2\u003c/a\u003e\u003c/p\u003e","title":"【CEF3学习】-- 下载构建好的版本"},{"content":"把老的xcode工程升级为cocoapod工程，先创建一个空的podfile\nuse_frameworks!:linkage =\u0026gt; :static inhibit_all_warnings! # 忽略引入库的所有警告 workspace \u0026#39;all.xcworkspace\u0026#39; target \u0026#39;testXcode8\u0026#39; do platform :ios, \u0026#39;8.0\u0026#39; project \u0026#39;testXcode8/testXcode8\u0026#39; end pod install 后，执行构建在链接阶段报错 Framework not found Pods_testXcode8\n尝试的解决过程就不赘述了，最后修改了一个八杆子打不着的BuidSetting解决的，将 Build Active Architecture Only 由非默认值NO修改为默认值\n未修改前 修改后 ","permalink":"https://blog.z6z8.cn/2022/02/10/framework-not-found-pods_xxxxx/","summary":"\u003cp\u003e把老的xcode工程升级为cocoapod工程，先创建一个空的podfile\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-ruby\" data-lang=\"ruby\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003euse_frameworks!\u003cspan style=\"color:#e6db74\"\u003e:linkage\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e:static\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003einhibit_all_warnings! \u003cspan style=\"color:#75715e\"\u003e# 忽略引入库的所有警告\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eworkspace \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;all.xcworkspace\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etarget \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;testXcode8\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    platform \u003cspan style=\"color:#e6db74\"\u003e:ios\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;8.0\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    project \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;testXcode8/testXcode8\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eend\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003ccode\u003epod install\u003c/code\u003e 后，执行构建在链接阶段报错 \u003ccode\u003eFramework not found Pods_testXcode8\u003c/code\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2022/02/1.png\"\u003e\u003c/p\u003e\n\u003cp\u003e尝试的解决过程就不赘述了，最后修改了一个八杆子打不着的BuidSetting解决的，将 \u003ccode\u003eBuild Active Architecture Only\u003c/code\u003e 由非默认值NO修改为默认值\u003c/p\u003e\n\u003cp\u003e未修改前\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2022/02/2.png\"\u003e\u003c/p\u003e\n\u003cp\u003e修改后\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2022/02/3.png\"\u003e\u003c/p\u003e","title":"Framework not found Pods_xxxxx"},{"content":"本文demo\n构造了这样的场景： 有两个动态库framework，DA和DB，DA定义了函数func，DB定义了函数func，两个func的名字一样，但是内部实现不一样，然后使用App加载这两个动态库，结果运行时func的调用和预期的不一致。\n动态库DA // func.h const char * func(void); const char * func_a(void); // func.c #include \u0026#34;func.h\u0026#34; const char * func(void) { return \u0026#34;i m da func\\n\u0026#34;; } const char * func_a(void) { return \u0026#34;i m da func_a\\n\u0026#34;; } 动态库DB // func.h const char * func(void); const char * func_b(void); // func.c #include \u0026#34;func.h\u0026#34; const char * func(void) { return \u0026#34;i m db func\\n\u0026#34;; } const char * func_a(void) { return \u0026#34;i m db func_b\\n\u0026#34;; } App 集成 //Appdelegate.m #import \u0026#34;AppDelegate.h\u0026#34; #import @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { printf(\u0026#34;%s\u0026#34;,func()); //预期打印 i m da func printf(\u0026#34;%s\u0026#34;,func_a()); return YES; } //ViewController.m #import \u0026#34;ViewController.h\u0026#34; #import @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; printf(\u0026#34;%s\u0026#34;,func());//预期打印 i m db func printf(\u0026#34;%s\u0026#34;,func_b()); } @end 实测\ni m db func i m da func_a i m db func i m db func_b ","permalink":"https://blog.z6z8.cn/2021/12/15/ios-%E5%8A%A8%E6%80%81%E5%BA%93%E8%BF%90%E8%A1%8C%E6%97%B6%E7%AC%A6%E5%8F%B7%E5%86%B2%E7%AA%81/","summary":"\u003cp\u003e\u003ca href=\"/wp-content/uploads/2021/12/Test.zip\"\u003e本文demo\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e构造了这样的场景：\n有两个动态库framework，DA和DB，DA定义了函数func，DB定义了函数func，两个func的名字一样，但是内部实现不一样，然后使用App加载这两个动态库，结果运行时func的调用和预期的不一致。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e动态库DA\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// func.h\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efunc\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efunc_a\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// func.c\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026#34;func.h\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efunc\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;i m da func\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efunc_a\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;i m da func_a\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e动态库DB\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// func.h\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efunc\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efunc_b\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// func.c\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026#34;func.h\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efunc\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;i m db func\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efunc_a\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;i m db func_b\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\n\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003eApp 集成\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//Appdelegate.m\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e#import \u0026#34;AppDelegate.h\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#import\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@implementation\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eAppDelegate\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (\u003cspan style=\"color:#66d9ef\"\u003eBOOL\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003eapplication:\u003c/span\u003e(UIApplication \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)application \u003cspan style=\"color:#a6e22e\"\u003edidFinishLaunchingWithOptions:\u003c/span\u003e(NSDictionary \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)launchOptions {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    printf(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%s\u0026#34;\u003c/span\u003e,func()); \u003cspan style=\"color:#75715e\"\u003e//预期打印  i m da func\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    printf(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%s\u0026#34;\u003c/span\u003e,func_a());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e YES;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//ViewController.m\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e#import \u0026#34;ViewController.h\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#import\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@implementation\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eViewController\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003eviewDidLoad\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [super viewDidLoad];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    printf(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%s\u0026#34;\u003c/span\u003e,func());\u003cspan style=\"color:#75715e\"\u003e//预期打印  i m db func\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    printf(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;%s\u0026#34;\u003c/span\u003e,func_b());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e实测\u003c/p\u003e","title":"iOS 动态库运行时符号冲突"},{"content":"App页面置灰，本质是将彩色图像转换为灰度图像，本文提供两种方法实现，一种是App整体置灰，一种是单个页面置灰，可结合具体的业务场景使用。\n方法一：分别将图片和文字置灰 一般情况下，App页面的颜色深度是24bit，也就是RGB各8bit；如果算上Alpha通道的话就是32bit，RGBA(或者ARGB)各8bit。灰度图像的颜色深度是8bit，这8bit表示的颜色不是彩色，而是256种不同亮度的黑色或白色。 说到灰度图像，在YUV颜色空间上\u0026mdash;其中Y代表亮度，调整Y值就可以得到不同的灰度图像。 理论上，颜色空间RGB和YUV是等价的，同一种颜色用RGB或YUV都可以表示。从RGB数值对应到亮度Y，一般采用公式Y = 0.299R+0.587G+0.114B，得到的结果再填充到RGB上就得到了对应的灰度RGB颜色。\nY = 0.299R+0.587G+0.114B Gray = RGB(Y,Y,Y) 以上是方法一App页面置灰的原理基础。\nUIImage转成灰度图 核心是创建一个灰度空间，然后将图像绘制到这个空间上\n－(UIImage*)getGrayImage:(UIImage*)sourceImage { int width = sourceImage.size.width; int height = sourceImage.size.height; // 创建灰度空间 CGColorSpaceRef colorSpace =CGColorSpaceCreateDeviceGray(); // 创建绘制上下文 CGContextRef context =CGBitmapContextCreate(nil,width,height,8,0,colorSpace,kCGImageAlphaNone); CGColorSpaceRelease(colorSpace); if(context== NULL){ return nil; } // 绘制原始图像到新的上下文（灰度） CGContextDrawImage(context,CGRectMake(0,0, width, height), sourceImage.CGImage); // 获取灰度图像 CGImageRef grayImageRef =CGBitmapContextCreateImage(context); // CGImage -\u0026gt; UIImage UIImage*grayImage=[UIImage imageWithCGImage:grayImageRef]; //回收资源 CGContextRelease(context); CGImageRelease(grayImageRef); return grayImage; } UIColor转成灰度颜色 比较简单了，使用公式就可以了 Y = 0.299R+0.587G+0.114B\nUIColor *color = xxxx; CGFloat r,g,b,a; [color getRed:\u0026amp;r green:\u0026amp;g\u0026gt; blue:\u0026amp;b alpha:\u0026amp;a]; CGFloat y = 0.299*r+0.587*g+0.114*b; UIColor *gray = [UIColor colorWithRed:y green:y blue:y alpha:a] 方法二：给App整体添加灰色滤镜 这个方法可以是App整体置灰，包括WebView页面。 原理就是把App页面当成一副图像，使用另一副偏灰图像和这个图像进行叠加运算，从而得到新的图像。 iOS 提供了Core Image 滤镜，这些滤镜可以设置在UIView.layer上。 我们要做的就是选取合适的滤镜，并将滤镜放置到App的最顶层\n// 最顶层视图，承载滤镜，自身不接收、不拦截任何触摸事件 @interface UIViewOverLay : UIView @end @implementation UIViewOverLay -(UIView*)hitTest:(CGPoint)point withEvent:(UIEvent *)event { return nil; } @end UIWindow *window = App的Window; UIViewOverLay *overlay = [[UIViewOverLay alloc]initWithFrame:self.window.bounds]; overlay.translatesAutoresizingMaskIntoConstraints = false; overlay.backgroundColor = [UIColor lightGrayColor]; overlay.layer.compositingFilter = @\u0026#34;saturationBlendMode\u0026#34;; [window addSubview:overlay]; 最后通过各种方法，要保证overlay在最顶层. 上面使用的是UIView承载滤镜，其实看代码就知道了也可以直接使用CALayer来承载滤镜（需要注意的是在UIWindow上直接添加CALayer时，在某些特殊的场景可能会造成绘制异常）\n方法三: 给App整体添加灰色滤镜（私有API） 灵感来自 UIVisualEffectView 这个公开的API。既然这个类能够实现App任意页面的毛玻璃效果\u0026ndash;一个基于高斯模糊的滤镜，那么必然可以仿照这个类实现其他滤镜效果。于是找到了 CAFilter 这个私有API，示意代码如下\n//获取RGBA颜色数值 CGFloat r,g,b,a; [[UIColor lightGrayColor] getRed:\u0026amp;r green:\u0026amp;g blue:\u0026amp;b alpha:\u0026amp;a]; //创建滤镜 id cls = NSClassFromString(@\u0026#34;CAFilter\u0026#34;); id filter = [cls filterWithName:@\u0026#34;colorMonochrome\u0026#34;]; //设置滤镜参数 [filter setValue:@[@(r),@(g),@(b),@(a)] forKey:@\u0026#34;inputColor\u0026#34;]; [filter setValue:@(0) forKey:@\u0026#34;inputBias\u0026#34;]; [filter setValue:@(1) forKey:@\u0026#34;inputAmount\u0026#34;]; //设置给window window.layer.filters = [NSArray arrayWithObject:filter]; 参考 如何将真彩色图转换为各种灰度图\nRGB、YUV和HSV颜色空间模型\nCore Image Filter\nCAFilter\n","permalink":"https://blog.z6z8.cn/2021/12/14/ios-app%E9%A1%B5%E9%9D%A2%E7%BD%AE%E7%81%B0%E5%AE%9E%E7%8E%B0/","summary":"\u003cp\u003eApp页面置灰，本质是将彩色图像转换为灰度图像，本文提供两种方法实现，一种是App整体置灰，一种是单个页面置灰，可结合具体的业务场景使用。\u003c/p\u003e\n\u003ch1 id=\"方法一分别将图片和文字置灰\"\u003e方法一：分别将图片和文字置灰\u003c/h1\u003e\n\u003cp\u003e一般情况下，App页面的颜色深度是24bit，也就是RGB各8bit；如果算上Alpha通道的话就是32bit，RGBA(或者ARGB)各8bit。灰度图像的颜色深度是8bit，这8bit表示的颜色不是彩色，而是256种不同亮度的黑色或白色。\n说到灰度图像，在YUV颜色空间上\u0026mdash;其中Y代表亮度，调整Y值就可以得到不同的灰度图像。\n理论上，颜色空间RGB和YUV是等价的，同一种颜色用RGB或YUV都可以表示。从RGB数值对应到亮度Y，一般采用公式Y = 0.299R+0.587G+0.114B，得到的结果再填充到RGB上就得到了对应的灰度RGB颜色。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eY = 0.299R+0.587G+0.114B\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eGray = RGB(Y,Y,Y)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e以上是方法一App页面置灰的原理基础。\u003c/p\u003e\n\u003ch2 id=\"uiimage转成灰度图\"\u003eUIImage转成灰度图\u003c/h2\u003e\n\u003cp\u003e核心是创建一个灰度空间，然后将图像绘制到这个空间上\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e－\u003c/span\u003e(UIImage\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)getGrayImage:(UIImage\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)sourceImage\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e width \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e sourceImage.size.width;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e height \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e sourceImage.size.height;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#75715e\"\u003e// 创建灰度空间\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e   CGColorSpaceRef colorSpace \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eCGColorSpaceCreateDeviceGray();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#75715e\"\u003e// 创建绘制上下文\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e   CGContextRef context \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eCGBitmapContextCreate(nil,width,height,\u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e,colorSpace,kCGImageAlphaNone);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   CGColorSpaceRelease(colorSpace);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(context\u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NULL){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e nil;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#75715e\"\u003e// 绘制原始图像到新的上下文（灰度）\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e   CGContextDrawImage(context,CGRectMake(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, width, height), sourceImage.CGImage);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#75715e\"\u003e// 获取灰度图像\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e   CGImageRef grayImageRef \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eCGBitmapContextCreateImage(context);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#75715e\"\u003e// CGImage -\u0026gt; UIImage\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e   UIImage\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003egrayImage\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e[UIImage imageWithCGImage:grayImageRef];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#75715e\"\u003e//回收资源\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e   CGContextRelease(context);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   CGImageRelease(grayImageRef);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e grayImage;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"uicolor转成灰度颜色\"\u003eUIColor转成灰度颜色\u003c/h2\u003e\n\u003cp\u003e比较简单了，使用公式就可以了 \u003ccode\u003eY = 0.299R+0.587G+0.114B\u003c/code\u003e\u003c/p\u003e","title":"iOS App页面置灰实现"},{"content":"环境:\nGoogleWebRTC 1.1.31999 Xcode 13 iOS 15 问题描述：\n1、 学习WebRTC时，先用simple-peer实现了浏览器和浏览器之间的音视频互通。\n2、然后结合浏览器的经验，基于GoogleWebRTC for iOS实现了iOS真机和浏览器直接的互通\n3、 最后在测试iOS真机之间的互通时，基本不互通，测试失败。排查了很长时间，最后定位为API调用顺序错误\n应先设置远端SDP，再设置远端ICE，具体到API就是，先设置 调用 setRemoteDescription,然后再调用 addIceCandidate\n// 收到远端SDP和ICE信息后 [peerConnection setRemoteDescription:remoteSDP completionHandler:^(NSError * err){ [peerConnection addIceCandidate:remoteICE]; } ]; ","permalink":"https://blog.z6z8.cn/2021/11/18/googlewebrtc-for-ios-%E8%AE%BE%E7%BD%AEsdp%E5%92%8Cice%E9%A1%BA%E5%BA%8F%E9%94%99%E8%AF%AF%E5%AF%BC%E8%87%B4%E4%B8%8D%E4%BA%92%E9%80%9A/","summary":"\u003cp\u003e环境:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eGoogleWebRTC 1.1.31999\u003c/li\u003e\n\u003cli\u003eXcode 13\u003c/li\u003e\n\u003cli\u003eiOS 15\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e问题描述：\u003c/p\u003e\n\u003cp\u003e1、 学习WebRTC时，先用simple-peer实现了浏览器和浏览器之间的音视频互通。\u003c/p\u003e\n\u003cp\u003e2、然后结合浏览器的经验，基于GoogleWebRTC for iOS实现了iOS真机和浏览器直接的互通\u003c/p\u003e\n\u003cp\u003e3、 最后在测试iOS真机之间的互通时，基本不互通，测试失败。排查了很长时间，最后定位为API调用顺序错误\u003c/p\u003e\n\u003cp\u003e\u003cstrong\u003e应先设置远端SDP，再设置远端ICE\u003c/strong\u003e，具体到API就是，先设置\n调用 \u003ccode\u003esetRemoteDescription\u003c/code\u003e,然后再调用 \u003ccode\u003eaddIceCandidate\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 收到远端SDP和ICE信息后\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e[peerConnection setRemoteDescription:remoteSDP completionHandler:\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e(NSError \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e err){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        [peerConnection addIceCandidate:remoteICE];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"GoogleWebRTC for iOS 设置SDP和ICE顺序错误导致不互通"},{"content":"环境准备 Apple Console (控制台程序，MacOS自带) iPhone（iPad等设备也可，不需要越狱） 数据线 iOS App（不需要破解，直接从AppStore安装就可以） 操作步骤 1、通过usb将iPhone手机和Mac电脑连接\n2、打开 Apple Console，选中的设备\n3、点击开始，可以实时看到设备日志了，然后打开App，运行一段时间。\n在日志里面搜索关键字 summary for task,应可以看到对网络性能的统计 字段解析 先摘抄一段日志\n16:34:02.523191+0800 MPBBank Task \u0026lt;4C18F624-05B7-427D-AC9D-46C6C69B29C9\u0026gt;.\u0026lt;1\u0026gt; summary for task success {transaction_duration_ms=576, response_status=200, connection=1, protocol=\u0026#34;http/1.1\u0026#34;, domain_lookup_duration_ms=105, connect_duration_ms=240, secure_connection_duration_ms=167, private_relay=false, request_start_ms=389, request_duration_ms=0, response_start_ms=574, response_duration_ms=1, request_bytes=1629, response_bytes=10056, cache_hit=false} 以上对应 日志时间（16:34:02.523191+0800）， 日志发生源的进程（MPBBank，此为招商银行App的进程）， 日志信息（Task \u0026lt;6510978A-4EA6-4970-A5A6-1AFBF3B0C0E1\u0026gt;.\u0026lt;1\u0026gt; \u0026hellip;.）\n主要关注下 日志信息 字段，可以看到其内容为\nTask \u0026lt;4C18F624-05B7-427D-AC9D-46C6C69B29C9\u0026gt;.\u0026lt;1\u0026gt; # 任务Id summary for task success # 任务成功统计 { transaction_duration_ms=576, # 传输时长 response_status=200, # 响应码 connection=1, protocol=\u0026#34;http/1.1\u0026#34;, # 网络协议 domain_lookup_duration_ms=105, # DNS查询时长 connect_duration_ms=240, # 连接时长secure_connection_duration_ms=167, # 安全连接时长 private_relay=false, request_start_ms=389, # 请求开始时刻 request_duration_ms=0, # 请求时长 response_start_ms=574, # 响应开始时刻 response_duration_ms=1, # 响应时长 request_bytes=1629, # 请求报文大小 response_bytes=10056, # 响应报文大小 cache_hit=false # 是否命中缓存 } 基本上从字面意思解释就可以了。 经过反复观察，以上部分数据存在以下关系： transaction_duration_ms = response_start_ms + response_duration_ms,最终计算结果可能会有几毫秒误差。\n另外，关于任务ID（上面例子中 4C18F624-05B7-427D-AC9D-46C6C69B29C9），可以作为关键字在设备日志中搜索，可以看到改任务的整个过程（当然也有任务相关日志不完整的情况存在）， resume-\u0026gt;setting up-\u0026gt;....-\u0026gt;sent-\u0026gt;...response...。\n关于WKWebView 使用以上方法可以统计出来App发送网络请求，但是无法统计App内使用WKWebView的情况，原因是WKWebView使用的是单独的进程发送网络请求。 其实，统计WKWebView网络使用情况也比较简单。 在日志中搜索 summary for task 关键字，如果看到进程名字为 com.apple.WebKit.Networking 的，那这个任务有可能是WKWebView发送的网络请求，也有可能是Safari发送的。 怎么确定是App内的WKWebView发送的请求呢？通过进程ID进行关联：\nApp内的WKWebView发送请求时，会通过系统请求创建一个进程，名字com.apple.WebKit.Networking 系统创建好进程com.apple.WebKit.Networking后，会把这个进程和App内的WKWebView进行绑定 绑定后App就知道到了com.apple.WebKit.Networking的进程ID，根据进行ID进行通信 搜索设备日志，关键字分别为 didConnectToProcess、 com.apple.WebKit.Networking\n从图中可知，进程 MPBBank 连接到了进程 17493（PD=17524），而进程17524正好是 com.apple.WebKit.Networking，再结合 summary for task 关键字，这样就可以把App内的WKWebView的网络性能统计出来了。\n关于自动化 以上都是通过手工操作来完成，离自动化应用还有些差距。 幸好有 libimobiledevice-utils，里面提供了 idevicesyslog 工具，可以实时的查看设备日志，日志内容和 Apple Console 基本一样。 另外，libimobiledevice-utils是跨平台的工具，剩下的事就交给python吧。\n","permalink":"https://blog.z6z8.cn/2021/11/11/ios-%E4%BB%8E%E8%AE%BE%E5%A4%87%E6%97%A5%E5%BF%97%E5%88%86%E6%9E%90app%E7%BD%91%E7%BB%9C%E6%80%A7%E8%83%BD/","summary":"\u003ch2 id=\"环境准备\"\u003e环境准备\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003eApple Console (控制台程序，MacOS自带)\u003c/li\u003e\n\u003cli\u003eiPhone（iPad等设备也可，不需要越狱）\u003c/li\u003e\n\u003cli\u003e数据线\u003c/li\u003e\n\u003cli\u003eiOS App（不需要破解，直接从AppStore安装就可以）\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"操作步骤\"\u003e操作步骤\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e1、通过usb将iPhone手机和Mac电脑连接\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e2、打开 Apple Console，选中的设备\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2021/11/1.png\"\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2021/11/2.png\"\u003e\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e3、点击开始，可以实时看到设备日志了，然后打开App，运行一段时间。\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e在日志里面搜索关键字 \u003ccode\u003esummary for task\u003c/code\u003e,应可以看到对网络性能的统计\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2021/11/3.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"字段解析\"\u003e字段解析\u003c/h2\u003e\n\u003cp\u003e先摘抄一段日志\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e16:34:02.523191+0800    MPBBank Task \u0026lt;4C18F624-05B7-427D-AC9D-46C6C69B29C9\u0026gt;.\u0026lt;1\u0026gt; summary for task success {transaction_duration_ms=576, response_status=200, connection=1, protocol=\u0026#34;http/1.1\u0026#34;, domain_lookup_duration_ms=105, connect_duration_ms=240, secure_connection_duration_ms=167, private_relay=false, request_start_ms=389, request_duration_ms=0, response_start_ms=574, response_duration_ms=1, request_bytes=1629, response_bytes=10056, cache_hit=false}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e以上对应 \u003ccode\u003e日志时间\u003c/code\u003e（16:34:02.523191+0800）， \u003ccode\u003e日志发生源的进程\u003c/code\u003e（MPBBank，此为招商银行App的进程）， \u003ccode\u003e日志信息\u003c/code\u003e（Task \u0026lt;6510978A-4EA6-4970-A5A6-1AFBF3B0C0E1\u0026gt;.\u0026lt;1\u0026gt; \u0026hellip;.）\u003c/p\u003e\n\u003cp\u003e主要关注下 \u003ccode\u003e日志信息\u003c/code\u003e 字段，可以看到其内容为\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTask \u0026lt;4C18F624-05B7-427D-AC9D-46C6C69B29C9\u0026gt;.\u0026lt;1\u0026gt; # 任务Id\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esummary for task success  # 任务成功统计\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  transaction_duration_ms=576, # 传输时长\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  response_status=200, # 响应码\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  connection=1,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  protocol=\u0026#34;http/1.1\u0026#34;, # 网络协议\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  domain_lookup_duration_ms=105, # DNS查询时长\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  connect_duration_ms=240, # 连接时长secure_connection_duration_ms=167, # 安全连接时长\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  private_relay=false,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  request_start_ms=389, # 请求开始时刻\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  request_duration_ms=0, # 请求时长\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  response_start_ms=574, # 响应开始时刻\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  response_duration_ms=1, # 响应时长\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  request_bytes=1629,  # 请求报文大小\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  response_bytes=10056, # 响应报文大小\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  cache_hit=false # 是否命中缓存\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e基本上从字面意思解释就可以了。\n经过反复观察，以上部分数据存在以下关系：\n\u003ccode\u003etransaction_duration_ms = response_start_ms + response_duration_ms\u003c/code\u003e,最终计算结果可能会有几毫秒误差。\u003c/p\u003e","title":"iOS 从设备日志分析App网络性能"},{"content":"关键属性 webkit-playsinline、 playsinline、 allowsInlineMediaPlayback\n需要在html style里面和native 里面同时设置才有效\nhtml video增加样式 webkit-playsinline、 playsinline\n\u0026lt;video controls=\u0026#34;\u0026#34; height=\u0026#34;auto\u0026#34; id=\u0026#34;video1\u0026#34; playsinline=\u0026#34;true\u0026#34; preload=\u0026#34;auto\u0026#34; webkit-playsinline=\u0026#34;true\u0026#34; width=\u0026#34;100%\u0026#34;\u0026gt;\u0026lt;source src=\u0026#34;xxxxx.mp4\u0026#34; type=\u0026#34;video/mp4\u0026#34;\u0026gt; 您的浏览器不支持 HTML5 video 标签。 \u0026lt;/source\u0026gt;\u0026lt;/video\u0026gt; native code 设置 allowsInlineMediaPlayback\nWKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; config.allowsInlineMediaPlayback = YES; WKWebView *webView = [[WKWebView alloc]initWithFrame:CGRectZero configuration:config]; 参考 https://www.zhihu.com/question/21094425\n","permalink":"https://blog.z6z8.cn/2021/11/08/ios-wkwebview-%E6%92%AD%E6%94%BE%E8%A7%86%E9%A2%91%E6%97%B6%E7%A6%81%E7%94%A8%E8%87%AA%E5%8A%A8%E5%85%A8%E5%B1%8F%E6%92%AD%E6%94%BE/","summary":"\u003cp\u003e关键属性 \u003ccode\u003ewebkit-playsinline\u003c/code\u003e、 \u003ccode\u003eplaysinline\u003c/code\u003e、 \u003ccode\u003eallowsInlineMediaPlayback\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e需要在html style里面和native 里面同时设置才有效\u003c/p\u003e\n\u003cp\u003ehtml video增加样式 \u003ccode\u003e webkit-playsinline\u003c/code\u003e、 \u003ccode\u003eplaysinline\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u0026lt;\u003cspan style=\"color:#f92672\"\u003evideo\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econtrols\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eheight\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;auto\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;video1\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eplaysinline\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;true\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epreload\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;auto\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewebkit-playsinline\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;true\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewidth\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;100%\u0026#34;\u003c/span\u003e\u0026gt;\u0026lt;\u003cspan style=\"color:#f92672\"\u003esource\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esrc\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;xxxxx.mp4\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;video/mp4\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    您的浏览器不支持 HTML5 video 标签。\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u0026lt;/\u003cspan style=\"color:#f92672\"\u003esource\u003c/span\u003e\u0026gt;\u0026lt;/\u003cspan style=\"color:#f92672\"\u003evideo\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003enative code 设置 \u003ccode\u003eallowsInlineMediaPlayback\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWKWebViewConfiguration \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003econfig \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[WKWebViewConfiguration alloc] init];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econfig.allowsInlineMediaPlayback \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YES;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWKWebView \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ewebView \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[WKWebView alloc]initWithFrame:CGRectZero configuration:config];\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e参考 \u003ca href=\"https://www.zhihu.com/question/21094425\"\u003ehttps://www.zhihu.com/question/21094425\u003c/a\u003e\u003c/p\u003e","title":"iOS WKWebView 播放视频时禁用自动全屏播放"},{"content":"webrtc介绍\n简介实现基本的数据通道文件传输修改传输速度限制选择并读取文件数据自动下载文件完整代码音视频通话https访问音视频流完整代码屏幕共享捕捉屏幕完整代码NAT穿透之STUN/TURN信令服务器信令服务实现完整代码\n详细请访问\n简介 WebRTC（网页实时通信技术），是一系列为了建立端到端文本或者随机数据的规范，标准，API和概念的统称。\n任何实现了WebRTC标准的软件之间均可通信，如PC浏览器\u0026ndash;手机浏览器、浏览器\u0026ndash;App、App\u0026ndash;App。通信双方是对等的，但通常还要引入服务端，以便于对等端能够找到对方。\n移动端浏览器对WebRTC的支持\nAndroid 4.4以上\niOS 11以上\nWebRTC应用不需要非常高性能就能够平稳运行、拥有良好体验。对于WebRTC来说，获取特定硬件的权限也不是必需的。Web应用和原生应用对比：\n原生应用会比Web应用更快，拥有更高级别的硬件权限；混合应用的运行速度更慢，不能使用移动设备的全部权限。 原生应用在不同的平台上的代码复用度有待提高；混合应用开发起来会更快，更省钱 结论：如果高性能和极致体验不是软件的必不可少的要求，那么，在绝大多数情况下，用户根本注意不到原生和混合WebRTC应用之间的差别。\n实现基本的数据通道 对浏览器而言，WebRTC API处于底层且十分复杂。不过我们可以使用封装好的高级别的API\u0026mdash;- simple-peer 是一个基础的，非常洁净的低层P2P连接封装器.下面的示例是 simple-peer 的一个标准例子。\n\u0026lt;html\u0026gt; \u0026lt;body\u0026gt; \u0026lt;style\u0026gt; #outgoing { width: 100%; word-wrap: break-word; white-space: normal; } \u0026lt;/style\u0026gt; \u0026lt;form\u0026gt; \u0026lt;textarea id=\u0026#34;incoming\u0026#34;\u0026gt;\u0026lt;/textarea\u0026gt; \u0026lt;button type=\u0026#34;submit\u0026#34;\u0026gt;submit\u0026lt;/button\u0026gt; \u0026lt;/form\u0026gt; \u0026lt;pre id=\u0026#34;outgoing\u0026#34;\u0026gt;\u0026lt;/pre\u0026gt; \u0026lt;script src=\u0026#34;simplepeer.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;script\u0026gt; const p = new SimplePeer({ initiator: location.hash === \u0026#39;#1\u0026#39;, trickle: false }) p.on(\u0026#39;error\u0026#39;, err =\u0026gt; console.log(\u0026#39;error\u0026#39;, err)) p.on(\u0026#39;signal\u0026#39;, data =\u0026gt; { console.log(\u0026#39;SIGNAL\u0026#39;, JSON.stringify(data)) document.querySelector(\u0026#39;#outgoing\u0026#39;).textContent = JSON.stringify(data) }) document.querySelector(\u0026#39;form\u0026#39;).addEventListener(\u0026#39;submit\u0026#39;, ev =\u0026gt; { ev.preventDefault() p.signal(JSON.parse(document.querySelector(\u0026#39;#incoming\u0026#39;).value)) }) p.on(\u0026#39;connect\u0026#39;, () =\u0026gt; { console.log(\u0026#39;CONNECT\u0026#39;) p.send(\u0026#39;whatever\u0026#39; + Math.random()) }) p.on(\u0026#39;data\u0026#39;, data =\u0026gt; { console.log(\u0026#39;data: \u0026#39; + data) }) \u0026lt;/script\u0026gt; \u0026lt;/body\u0026gt;\u0026lt;/html\u0026gt; 演示步骤:\n1、创建 index.html 文件，文件内容为上面的代码 2、下载 simplepeer.min.js，放到和 index.html 同目录下 3、用浏览器打开 file:///本地路径目录/index.html#1（这里使用file协议，是因为没有部署index.html到服务端），可以看到网页中输出了一个 offer 邀请信令，格式类似下面例子 {\u0026#34;type\u0026#34;:\u0026#34;offer\u0026#34;,\u0026#34;sdp\u0026#34;:\u0026#34;v=0\\r\\no=- 8456412157049919494 2 IN IP4 127.0.0.1\\r\\ns=-\\r\\nt=0 0\\r\\na=group:BUNDLE 0\\r\\na=extmap-allow-mixed\\r\\na=msid-semantic: WMS\\r\\nm=application 53799 UDP/DTLS/SCTP webrtc-datachannel\\r\\nc=IN IP4 171.84.6.216\\r\\na=candidate:1841888059 1 udp 2113937151 0ec970aa-e465-4105-a65e-81ec6552c7e5.local 53799 typ host generation 0 network-cost 999\\r\\na=candidate:842163049 1 udp 1677729535 171.84.6.216 53799 typ srflx raddr 0.0.0.0 rport 0 generation 0 network-cost 999\\r\\na=ice-ufrag:UqLe\\r\\na=ice-pwd:f08ur1ltpmFSGbMp/cwf9KkF\\r\\na=fingerprint:sha-256 71:60:B4:28:15:B6:5E:D4:CE:76:49:F8:B2:CE:44:E4:F8:F9:FD:14:7B:AA:DA:AA:BE:DF:66:62:27:2E:E9:00\\r\\na=setup:actpass\\r\\na=mid:0\\r\\na=sctp-port:5000\\r\\na=max-message-size:262144\\r\\n\u0026#34;} 4、用另外一个浏览器打开 file:///本地路径目录/index.html，注意没有 #1，然后将步骤3中的 offer 信令复制到本步骤中网页的提交框中，并提交，然后可以在网页中看到一 answer 应答信令，格式类似下面例子 {\u0026#34;type\u0026#34;:\u0026#34;answer\u0026#34;,\u0026#34;sdp\u0026#34;:\u0026#34;v=0\\r\\no=- 5040306846154650858 2 IN IP4 127.0.0.1\\r\\ns=-\\r\\nt=0 0\\r\\na=group:BUNDLE 0\\r\\na=extmap-allow-mixed\\r\\na=msid-semantic: WMS\\r\\nm=application 9 UDP/DTLS/SCTP webrtc-datachannel\\r\\nc=IN IP4 0.0.0.0\\r\\na=candidate:1841888059 1 udp 2113937151 71a8e768-d70d-4554-8ce3-c3d1ee6751a0.local 49173 typ host generation 0 network-cost 999\\r\\na=ice-ufrag:VhmK\\r\\na=ice-pwd:KVNGXnCYlO1TaAqAEnhObWP4\\r\\na=fingerprint:sha-256 5E:09:41:CF:D8:25:46:D4:E4:D7:B6:FB:6D:E7:18:7F:BE:CB:4B:98:28:72:95:06:78:24:FB:6C:6F:B4:50:AE\\r\\na=setup:active\\r\\na=mid:0\\r\\na=sctp-port:5000\\r\\na=max-message-size:262144\\r\\n\u0026#34;} 5、将步骤4中的 answer 信令制到步骤3中网页的提交框中，并提交。打开浏览器的开发者模式，可以看到两个浏览器已经建立了数据通道，并互相发送了一个随机数消息 文件传输 建立起基本的数据通道后，就可以做一些比较直观的不那么抽象事情了，比如传输文件。对于使用WebRTC进行文件传输，有一些细节需要处理\n修改传输速度限制 Chrome默认将WebRTC的数据通道传输速度限制在30K，我们可以修改SDP的内容来提高上限,例如256K。\nlet peer = new SimplePeer()peer.on(\u0026#39;signal\u0026#39;, data =\u0026gt; { data.sdp = data.sdp.replace( \u0026#39;b=AS:30\u0026#39;, \u0026#39;b=AS:262144\u0026#39; ); console.log(\u0026#39;SIGNAL\u0026#39;, JSON.stringify(data))}) 选择并读取文件数据 我们选取基本的input控件作为文件选择器,并监听文件选择动作。\n\u0026lt;input type=\u0026#34;file\u0026#34; onchange=\u0026#34;OnFileSelected(this.files)\u0026#34;/\u0026gt;\u0026lt;script\u0026gt; //选中文件 function OnFileSelected(files) { file = files[0]; let fileReader = new FileReader(); fileReader.onload = (ev)=\u0026gt;{ let blobData = ev.currentTarget.result; console.log(blobData) } fileReader.readAsArrayBuffer( file.slice( 0, file.size ) ); }\u0026lt;/script\u0026gt; 考虑到传输速度限制，在读取文件内容时，应进行切片\u0026ndash;循环读取、发送，直到文件末尾。\n自动下载文件 接收完成后，数据还保存在浏览器内存（缓存）中，需要触发文件下载机制将数据下载到本地。\nlet blobData = \u0026#39;接收的数据\u0026#39;let blob = new window.Blob( blobData );let anchor = document.createElement( \u0026#39;a\u0026#39; );anchor.href = URL.createObjectURL( blob );anchor.download = \u0026#39;文件名\u0026#39;;anchor.textContent = \u0026#39;下载文件\u0026#39;;anchor.click() 完整代码 \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;utf-8\u0026#34;/\u0026gt; \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width,initial-scale=1\u0026#34;/\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;style\u0026gt; #outgoing { width: 100%; word-wrap: break-word; white-space: normal; } \u0026lt;/style\u0026gt; \u0026lt;form\u0026gt; \u0026lt;textarea id=\u0026#34;incoming\u0026#34;\u0026gt;\u0026lt;/textarea\u0026gt; \u0026lt;button type=\u0026#34;submit\u0026#34;\u0026gt;提交\u0026lt;/button\u0026gt; \u0026lt;/form\u0026gt; \u0026lt;div\u0026gt;口令\u0026lt;/div\u0026gt; \u0026lt;pre id=\u0026#34;outgoing\u0026#34;\u0026gt;\u0026lt;/pre\u0026gt; \u0026lt;input id=\u0026#34;fileinput\u0026#34; type=\u0026#34;file\u0026#34; onchange=\u0026#34;OnFileSelected(this.files)\u0026#34; hidden=\u0026#34;true\u0026#34;/\u0026gt; \u0026lt;script src=\u0026#34;simplepeer.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;script\u0026gt; //单个块大小 const MAX_CHUNK_SIZE = 1024 * 256; //选中文件 function OnFileSelected(files) { file = files[0]; sendFile(file) } var peer; if (location.hash === \u0026#39;#1\u0026#39;) { peer = new SimplePeer({ initiator: true, trickle: false}); } else { peer = new SimplePeer({ initiator: false, trickle: false}); } peer.on(\u0026#39;error\u0026#39;, err =\u0026gt; console.log(\u0026#39;error\u0026#39;, err)); peer.on(\u0026#39;error\u0026#39;, err =\u0026gt; console.log(\u0026#39;error\u0026#39;, err)); peer.on(\u0026#39;signal\u0026#39;, data =\u0026gt; { //modify sdp to increase block size data.sdp = data.sdp.replace( \u0026#39;b=AS:30\u0026#39;, \u0026#39;b=AS:\u0026#39;+MAX_CHUNK_SIZE.toString() ); document.querySelector(\u0026#39;#outgoing\u0026#39;).textContent = JSON.stringify(data); }); document.querySelector(\u0026#39;form\u0026#39;).addEventListener(\u0026#39;submit\u0026#39;, ev =\u0026gt; { ev.preventDefault() peer.signal(JSON.parse(document.querySelector(\u0026#39;#incoming\u0026#39;).value)); }); peer.on(\u0026#39;connect\u0026#39;, () =\u0026gt; { console.log(\u0026#39;CONNECT\u0026#39;); // show file input button document.querySelector(\u0026#39;#fileinput\u0026#39;).removeAttribute(\u0026#34;hidden\u0026#34;) }); // receive file peer.on(\u0026#39;data\u0026#39;, data =\u0026gt; { recvFile(data); }); function sendFile(file) { console.log(\u0026#34;send file name size\u0026#34;); peer.send(JSON.stringify({ fileName: file.name, fileSize: file.size })); console.log(\u0026#34;send file data\u0026#34;); let fileReader = new FileReader(); let readEnd = {\u0026#34;end\u0026#34;:false}; let startPos = 0; function readFile(file) { let end = startPos + MAX_CHUNK_SIZE; if (end \u0026gt; file.size) { end = file.size; readEnd.end = true; } let fc = file.slice( startPos, end ); startPos = end; fileReader.readAsArrayBuffer( fc ); } fileReader.onload = (ev)=\u0026gt;{ let blobData = ev.currentTarget.result; console.log(\u0026#34;send file data \u0026#34;, startPos) peer.send(blobData); if (readEnd.end === false) { readFile(file) } } readFile(file); } let recvFileInfo = undefined; let recvFileData = []; let recvLen = 0; function recvFile(data) { if (recvFileInfo === undefined) { recvFileInfo = JSON.parse( data.toString() ); } else { recvLen += data.byteLength; recvFileData.push(data); console.log(\u0026#34;recv \u0026#34; + recvFileInfo.fileName + \u0026#34; \u0026#34; + recvLen.toString() + \u0026#34;/\u0026#34; + recvFileInfo.fileSize.toString()); // receive end if (recvLen \u0026gt;= recvFileInfo.fileSize) { let blob = new window.Blob( recvFileData ); var anchor = document.createElement( \u0026#39;a\u0026#39; ); anchor.href = URL.createObjectURL( blob ); anchor.download = recvFileInfo.fileName; anchor.textContent = \u0026#39;下载\u0026#39;; recvFileInfo = undefined; anchor.click(); } } } \u0026lt;/script\u0026gt; \u0026lt;/body\u0026gt;\u0026lt;/html\u0026gt; 演示步骤:\n1、创建 index.html 文件，文件内容为上面的代码 2、下载 simplepeer.min.js，放到和 index.html 同目录下 3、用浏览器打开 file:///本地路径目录/index.html#1（这里使用file协议，是因为没有部署index.html到服务端），可以看到网页中输出了一个 offer 邀请信令。 4、用另外一个浏览器打开 file:///本地路径目录/index.html，注意没有 #1，然后将步骤3中的 offer 信令复制到本步骤中网页的提交框中，并提交，然后可以在网页中看到一 answer 应答信令。 5、将步骤4中的 answer 信令制到步骤3中网页的提交框中，并提交。打开浏览器的开发者模式，可以看到两个浏览器已经建立了数据通道，此时可以传输文件了。 音视频通话 还是使用 simple-peer,利用浏览器的媒体能力，搭建一个简单的局域网内音视频通话模型。\nhttps 一般情况下，在线网页使用浏览器的摄像头和麦克风能力时，浏览器的要求是使用 htpps。这里，我们使用python简单的搭建一个 https 服务器\n首先，用 openssl 自签名一个 RSA 证书（如果有机构颁发的证书，则可以忽略此步骤）\nopenssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365 上述命令会要求输入初始密码，可以输入简单的密码如 123456（仅测试用），同时输出两个文件 key.pem 和 cert.pem，记住两个文件的路径。\n参考Simple Python HTTP(S) Server — Example，创建 https_server.py 文件,内容如下\nxxxxxxxxxx #!/usr/bin/python# -*- coding: UTF-8 -*- import sys if sys.version_info.major \u0026gt; 2: # python 3 from http.server import HTTPServer as BaseHTTPServer from http.server import BaseHTTPRequestHandler as SimpleHTTPRequestHandlerelse: #python 2 from BaseHTTPServer import HTTPServer from SimpleHTTPServer import SimpleHTTPRequestHandler import ssl httpd = HTTPServer((\u0026#39;\u0026#39;, 4443),SimpleHTTPRequestHandler) httpd.socket = ssl.wrap_socket (httpd.socket, keyfile=\u0026#34;key.pem\u0026#34;, certfile=\u0026#39;cert.pem\u0026#39;, server_side=True) httpd.serve_forever() 把 key.pem 和 cert.pem 放在和 https_server.py 同目录下，然后运行命令并输入证书密码（本例为123456）\nxxxxxxxxxx python https_server.py 一个简单的https服务搭建完毕\n访问音视频流 我们可以使用 navigator.mediaDevices.getUserMedia 来获取音视频流数据\nxxxxxxxxxx navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then((stream)=\u0026gt;{ //音视频流 stream }).catch(() =\u0026gt; { //捕获到异常 }) 获取到媒体流后,可以将媒体数据展示在 video 标签上，这样更加直观。需要注意的是，对于iOS设备，建议使用iOS11以后的版本，且需要添加 playsinline webkit-playsinline=\u0026quot;true\u0026quot; 以解决video标签的黑屏/白屏问题。\nxxxxxxxxxx \u0026lt;video id=\u0026#34;idvv\u0026#34; playsinline webkit-playsinline=\u0026#34;true\u0026#34; /\u0026gt;\u0026lt;script\u0026gt; navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then((stream)=\u0026gt;{ //音视频流 stream var video = document.querySelector(\u0026#34;idvv\u0026#34;) if (\u0026#39;srcObject\u0026#39; in video) { video.srcObject = stream } else { video.src = window.URL.createObjectURL(stream) } video.play() }).catch(() =\u0026gt; { //捕获到异常 })\u0026lt;/script\u0026gt; 完整代码 xxxxxxxxxx \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;utf-8\u0026#34;/\u0026gt; \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width,initial-scale=1\u0026#34;/\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;style\u0026gt; #outgoing { width: 100%; word-wrap: break-word; white-space: normal; } \u0026lt;/style\u0026gt; \u0026lt;form\u0026gt; \u0026lt;textarea id=\u0026#34;incoming\u0026#34;\u0026gt;\u0026lt;/textarea\u0026gt; \u0026lt;button type=\u0026#34;submit\u0026#34;\u0026gt;提交\u0026lt;/button\u0026gt; \u0026lt;/form\u0026gt; \u0026lt;div\u0026gt;口令\u0026lt;/div\u0026gt; \u0026lt;pre id=\u0026#34;outgoing\u0026#34;\u0026gt;\u0026lt;/pre\u0026gt; \u0026lt;div\u0026gt;媒体流\u0026lt;/div\u0026gt; \u0026lt;!-- ios 11以上支持video，同时需要 添加 playsinline webkit-playsinline=\u0026#34;true\u0026#34; ,解决黑屏/白屏幕问题 --\u0026gt; \u0026lt;video width=\u0026#34;40%\u0026#34; id=\u0026#34;streamLocal\u0026#34; playsinline webkit-playsinline=\u0026#34;true\u0026#34; /\u0026gt; \u0026lt;video width=\u0026#34;40%\u0026#34; id=\u0026#34;streamRemote\u0026#34; playsinline webkit-playsinline=\u0026#34;true\u0026#34; /\u0026gt; \u0026lt;script src=\u0026#34;simplepeer.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;script\u0026gt; // get video/voice stream navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(gotMedia).catch(() =\u0026gt; {}) var peer; function gotMedia (stream) { // show local record video stream showVideoStream(\u0026#34;#streamLocal\u0026#34;,stream) if (location.hash === \u0026#39;#1\u0026#39;) { peer = new SimplePeer({ initiator: true, trickle: false, stream: stream }) } else { peer = new SimplePeer({initiator:false, trickle: false, stream: stream}) } peer.on(\u0026#39;error\u0026#39;, err =\u0026gt; console.log(\u0026#39;error\u0026#39;, err)) peer.on(\u0026#39;signal\u0026#39;, data =\u0026gt; { console.log(\u0026#39;SIGNAL\u0026#39;, JSON.stringify(data)) document.querySelector(\u0026#39;#outgoing\u0026#39;).textContent = JSON.stringify(data) }) document.querySelector(\u0026#39;form\u0026#39;).addEventListener(\u0026#39;submit\u0026#39;, ev =\u0026gt; { ev.preventDefault() peer.signal(JSON.parse(document.querySelector(\u0026#39;#incoming\u0026#39;).value)) }) peer.on(\u0026#39;stream\u0026#39;, stream =\u0026gt; { // got remote video stream, now let\u0026#39;s show it in a video tag showVideoStream(\u0026#34;#streamRemote\u0026#34;,stream) }) } function showVideoStream(id,stream) { var video = document.querySelector(id) if (\u0026#39;srcObject\u0026#39; in video) { video.srcObject = stream } else { video.src = window.URL.createObjectURL(stream) // for older browsers } video.play() } \u0026lt;/script\u0026gt; \u0026lt;/body\u0026gt;\u0026lt;/html\u0026gt; 演示步骤:\n1、创建 index.html 文件，文件内容为上面的代码，放在 https_server.py 同目录下 2、下载 simplepeer.min.js，放到和 index.html 同目录下 3、运行 python https_server.py 4、用浏览器打开 https://ip地址:4443/index.html#1，可以看到网页中输出了一个 offer 邀请信令。 5、用局域网内的另外一个终端浏览器打开 https://ip地址:4443/index.html，注意没有 #1，然后将步骤4中的 offer 信令复制到本步骤中网页的提交框中，并提交，然后可以在网页中看到一 answer 应答信令。 6、将步骤4中的 answer 信令制到步骤3中网页的提交框中，并提交。顺利的话，可以两个浏览器可以显示到对方的媒体流 屏幕共享 屏幕共享的原理和音视频通话的原理类似，唯一不同的是媒体流的数据来源不一样，因此，我们可以在音视频通话的基础上，修改一个屏幕共享的实现。\nSafari浏览器对 MediaStream 支持不够友好，建议使用两个Chrome浏览器测试。\n捕捉屏幕 Chrome浏览器在2018年后才开始支持 navigator.mediaDevices.getDisplayMedia\nxxxxxxxxxx navigator.mediaDevices.getDisplayMedia({ video: true, audio: true }).then( (stream)=\u0026gt;{ // stream 屏幕数据 }).catch(() =\u0026gt; { (e) =\u0026gt; {console.log(e)} }) 完整代码 xxxxxxxxxx \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;utf-8\u0026#34;/\u0026gt; \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width,initial-scale=1\u0026#34;/\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;style\u0026gt; #outgoing { width: 100%; word-wrap: break-word; white-space: normal; } \u0026lt;/style\u0026gt; \u0026lt;form\u0026gt; \u0026lt;textarea id=\u0026#34;incoming\u0026#34;\u0026gt;\u0026lt;/textarea\u0026gt; \u0026lt;button type=\u0026#34;submit\u0026#34;\u0026gt;提交\u0026lt;/button\u0026gt; \u0026lt;/form\u0026gt; \u0026lt;div\u0026gt;口令\u0026lt;/div\u0026gt; \u0026lt;pre id=\u0026#34;outgoing\u0026#34;\u0026gt;\u0026lt;/pre\u0026gt; \u0026lt;!-- ios 11以上支持video，同时需要 添加 playsinline webkit-playsinline=\u0026#34;true\u0026#34; ,解决黑屏/白屏幕问题 --\u0026gt; \u0026lt;video id=\u0026#34;screenShare\u0026#34; playsinline webkit-playsinline=\u0026#34;true\u0026#34;\u0026gt;\u0026lt;/video\u0026gt; \u0026lt;script src=\u0026#34;simplepeer.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;script\u0026gt; // get video/voice stream if (location.hash === \u0026#39;#1\u0026#39;) { navigator.mediaDevices.getDisplayMedia({ video: true, audio: true }).then( gotMedia).catch(() =\u0026gt; {(e) =\u0026gt; {console.log(e)}}) } else { gotMedia(null) } var peer; function gotMedia (stream) { if (stream !== null) { peer = new SimplePeer({ initiator: true, trickle: false, stream: stream }) } else { peer = new SimplePeer({initiator:false, trickle: false}) } peer.on(\u0026#39;error\u0026#39;, err =\u0026gt; console.log(\u0026#39;error\u0026#39;, err)) peer.on(\u0026#39;signal\u0026#39;, data =\u0026gt; { console.log(\u0026#39;SIGNAL\u0026#39;, JSON.stringify(data)) document.querySelector(\u0026#39;#outgoing\u0026#39;).textContent = JSON.stringify(data) }) document.querySelector(\u0026#39;form\u0026#39;).addEventListener(\u0026#39;submit\u0026#39;, ev =\u0026gt; { ev.preventDefault() peer.signal(JSON.parse(document.querySelector(\u0026#39;#incoming\u0026#39;).value)) }) peer.on(\u0026#39;stream\u0026#39;, stream =\u0026gt; { // got remote video stream, now let\u0026#39;s show it in a video tag showVideoStream(\u0026#34;#screenShare\u0026#34;,stream) }) } function showVideoStream(id,stream) { var video = document.querySelector(id) if (\u0026#39;srcObject\u0026#39; in video) { video.srcObject = stream } else { video.src = window.URL.createObjectURL(stream) // for older browsers } video.play() } \u0026lt;/script\u0026gt; \u0026lt;/body\u0026gt;\u0026lt;/html\u0026gt; 演示步骤和音视频通话的例子基本一样。\nNAT穿透之STUN/TURN NAT（Network Address Translation，网络地址转换），典型的应用场景是公网IP地址和私有IP地址转换，通过使用少量的公网IP地址来代表较多的私有IP地址的方式，将有助于减缓可用的IP地址空间的枯竭。\nNAT分为四种类型，Full Cone（完全锥形）、Restricted Cone（限制锥形）、Port Restricted Cone（端口限制锥形）和Symmetric（对称形）。\n为了能让两个处在不同NAT网络的WebRTC终端能够进行数据、媒体通信，需要借助STUN/TURN来实现NAT穿透。\n一般来说，STUN（Simple Traversal of User Datagram Protocol Through Network Address Translators）， NAT的UDP的简单穿越，是一种网络协议，通过暴露两个WebRTC终端在公网上的地址，可以在锥形NAT（完全锥形、限制锥形、端口限制锥形）进行穿透，从而实现P2P通信。\nTURN（Traversal Using Relays around NAT），也是一种网络协议，可以解决STUN不能穿透对称形NAT的问题。和STUN不同的是，TURN实现穿透的方法是中转。\n如果在公网上架设了STUN/TURN服务器，那么处在不同NAT网络的WebRTC终端进行通信就变得比较容易了。在初始化WebRTC终端时，可以配置STUN/TURN服务地址列表：\nxxxxxxxxxx peer = new SimplePeer({ config: { iceServers: [{ urls: \u0026#39;stun:stun.l.google.com:19302\u0026#39; }, { urls: \u0026#39;stun:global.stun.twilio.com:3478?transport=udp\u0026#39; }] }, }) //ICE，与STUN和TURN相比，ICE并非是解决NAT穿透问题的协议，而是一个框架，整合其他现存的NAT穿透协议，如STUN、TURN、RSIP等。 使用STUN/TURN后，可以较为方便的实现NAT穿透。当然，STUN/TURN不是必需的，但是强烈推荐使用。\n信令服务器 为何还需要引入信令服务器？先回顾下本文上面的例子，使用 simple-peer 创建WebRTC终端，生成 SDP 信令（如 offer、 answer）,那么他们如何交换信令呢？本文上文的例子是通过 手动复制粘贴 实现的，而真实的业务场景中，这个人工操作是由信令服务器完成的。\nWebRTC并没有规定信令服务使用哪种协议实现，所以本文采用最简单的实现方式（真实业务场景不会使用），HTTP + GET + POST实现。先来熟悉下引入信令服务器后，两个WebRTC终端建立连接的过程：\n1、A端 初始化 offer 信令. 2、A端 向 STUN/TURN 查询自己的公网地址， STUN/TURN 会返回 candidate列表A（可连接的候选地址列表）. 3、A端 将 offer 信令和 candidate列表A 一同发给信令务器，由信令服务器转发给 B端. 4、B端 收到 offer 信令和 candidate列表A, 从 candidate列表A 选择合适的地址发送NAT穿透报文, 同时向 STUN/TURN 查询自己的公网地址获取 candidate列表B. 5、B端 生成 answer 信令，并将 answer 信令和 candidate列表B 发送给信令服务器，由信令服务器转发给 A端. 6、A端 收到 answer 信令和 candidate列表B,从 candidate列表B 选择合适的地址发送NAT穿透报文. 7、A、B建立连接。 以上只是基本的连接建立过程，当然真实业务场景会比较复杂，如可能有媒体协商。真实的业务场景下，连接过程依然可以从上面的基本过程演变出来。\n信令服务实现 上面说到本文使用HTTP + GET + POST实现，客户端使用 POST 负责发送信令，通过 GET 轮询获取信令。依然适用Python实现。\nxxxxxxxxxx import sys if sys.version_info.major \u0026gt; 2: # python 3 from http.server import HTTPServer as BaseHTTPServer from http.server import BaseHTTPRequestHandler as SimpleHTTPRequestHandlerelse: #python 2 from BaseHTTPServer import HTTPServer from SimpleHTTPServer import SimpleHTTPRequestHandler import ssl WEBRTC_OFFER = NoneWEBRTC_ANSWER = None class WebRtcSignalHandler (SimpleHTTPRequestHandler): def do_GET(self): if (self.path == \u0026#34;/webrtc_offer\u0026#34;): self.do_http_response_with(200,WEBRTC_OFFER) elif (self.path == \u0026#34;/webrtc_answer\u0026#34;): self.do_http_response_with(200,WEBRTC_ANSWER) else: SimpleHTTPRequestHandler.do_GET(self) def do_POST(self): length = int(self.headers.getheader(\u0026#39;content-length\u0026#39;)) body = self.rfile.read(length) if (self.path == \u0026#34;/webrtc_offer\u0026#34;): global WEBRTC_OFFER WEBRTC_OFFER = body WEBRTC_ANSWER = None self.do_http_response_with(200,\u0026#34;Success\u0026#34;) elif (self.path == \u0026#34;/webrtc_answer\u0026#34;): global WEBRTC_ANSWER WEBRTC_ANSWER = body self.do_http_response_with(200,\u0026#34;Success\u0026#34;) else: SimpleHTTPRequestHandler.do_POST(self) def do_http_response_with(self,code,msg): self.send_response(code) self.end_headers() if (msg): if not self.wfile.closed: self.wfile.write(msg) # self.wfile.flush() httpd = HTTPServer((\u0026#39;\u0026#39;, 4443),WebRtcSignalHandler) httpd.socket = ssl.wrap_socket (httpd.socket, keyfile=\u0026#34;key.pem\u0026#34;, # 密码123456 certfile=\u0026#39;cert.pem\u0026#39;, server_side=True) httpd.serve_forever() 完整代码 xxxxxxxxxx \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;utf-8\u0026#34;/\u0026gt; \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width,initial-scale=1\u0026#34;/\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;div\u0026gt;媒体流\u0026lt;/div\u0026gt; \u0026lt;!-- ios 11以上支持video，同时需要 添加 playsinline webkit-playsinline=\u0026#34;true\u0026#34; ,解决黑屏/白屏幕问题 --\u0026gt; \u0026lt;video width=\u0026#34;40%\u0026#34; id=\u0026#34;streamLocal\u0026#34; playsinline webkit-playsinline=\u0026#34;true\u0026#34;\u0026gt;\u0026lt;/video\u0026gt; \u0026lt;video width=\u0026#34;40%\u0026#34; id=\u0026#34;streamRemote\u0026#34; playsinline webkit-playsinline=\u0026#34;true\u0026#34;\u0026gt;\u0026lt;/video\u0026gt; \u0026lt;script src=\u0026#34;simplepeer.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt; \u0026lt;script\u0026gt; // get video/voice stream navigator.mediaDevices.getUserMedia({ video: true, audio: true }).then(gotMedia).catch(() =\u0026gt; {}) var peer var candidateList = [] var sdp = undefined const initiator = (location.hash === \u0026#39;#1\u0026#39;) function gotMedia (stream) { // show local record video stream showVideoStream(\u0026#34;#streamLocal\u0026#34;,stream) // ice config let iceConfig = [{ urls: \u0026#39;stun:stun1.l.google.com:19302\u0026#39; }, /*{ urls: \u0026#39;stun:stun2.l.google.com:19302\u0026#39; }, { urls: \u0026#39;stun:stun3.l.google.com:19302\u0026#39; }, { urls: \u0026#39;stun:stun4.l.google.com:19302\u0026#39; },*/] peer = new SimplePeer({ initiator: initiator, stream: stream , config:{iceServers : iceConfig}}) peer.on(\u0026#39;error\u0026#39;, err =\u0026gt; console.log(\u0026#39;error\u0026#39;, err)) peer.on(\u0026#39;signal\u0026#39;, data =\u0026gt; { if (data.type === \u0026#34;candidate\u0026#34;) { candidateList.push(data); } else if (data.type === \u0026#34;offer\u0026#34; || data.type === \u0026#34;answer\u0026#34;) { sdp = data; // 获取sdp信息 ，2秒后将 sdp 和 candidate 发给 信令服务器 setTimeout(() =\u0026gt; { msg = {sdp:sdp , candidate:candidateList} sendMsgSdpCandidate(msg); console.log(JSON.stringify(msg)) }, 2000) } }) setTimeout(() =\u0026gt; { // 获取 sdp fetchMsgSdpCandidate((msg)=\u0026gt;{ if ((msg.sdp.type === \u0026#34;answer\u0026#34; \u0026amp;\u0026amp; initiator ===true) || (msg.sdp.type === \u0026#34;offer\u0026#34; \u0026amp;\u0026amp; initiator ===false)) { if (msg.candidate !== undefined ) { msg.candidate.forEach( (c)=\u0026gt;{ peer.signal(c) }) } peer.signal(msg.sdp) } }) }, 2000); peer.on(\u0026#39;stream\u0026#39;, stream =\u0026gt; { // got remote video stream, now let\u0026#39;s show it in a video tag showVideoStream(\u0026#34;#streamRemote\u0026#34;,stream) }) } function sendMsgSdpCandidate(msg) { let xhr = new XMLHttpRequest() xhr.open(\u0026#34;POST\u0026#34;, initiator ? \u0026#34;webrtc_offer\u0026#34; : \u0026#34;webrtc_answer\u0026#34;, true) xhr.send(JSON.stringify(msg)) } function fetchMsgSdpCandidate( callback ) { // 为节省服务编码，此处使用http get轮询方式。 // 正常业务中，可以使用websocket，避免轮询冲击。 let xhr = new XMLHttpRequest() xhr.onload = function() { if (xhr.status == 200 \u0026amp;\u0026amp; xhr.responseText) { msg = JSON.parse(xhr.responseText) callback(msg) } else { setTimeout(() =\u0026gt; { fetchMsgSdpCandidate(callback) }, 2000); } } xhr.open(\u0026#34;GET\u0026#34;, initiator ? \u0026#34;webrtc_answer\u0026#34; : \u0026#34;webrtc_offer\u0026#34;) xhr.send() } function showVideoStream(id,stream) { var video = document.querySelector(id) if (\u0026#39;srcObject\u0026#39; in video) { video.srcObject = stream } else { video.src = window.URL.createObjectURL(stream) // for older browsers } video.play() } \u0026lt;/script\u0026gt; \u0026lt;/body\u0026gt;\u0026lt;/html\u0026gt; 演示步骤:\n1、创建 index.html 文件，文件内容为上面的代码 2、下载 simplepeer.min.js，放到和 index.html 同目录下 3、用浏览器打开 https://公网地址/index.html#1。 4、用另外一个浏览器打开 https:///公网地址/index.html，注意没有 #1。 5、正常情况下，应能建立连接。 ","permalink":"https://blog.z6z8.cn/2021/10/19/webrtc%E5%88%9D%E5%AD%A6demo/","summary":"\u003cp\u003ewebrtc介绍\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"#%E7%AE%80%E4%BB%8B\"\u003e简介\u003c/a\u003e\u003ca href=\"#%E5%AE%9E%E7%8E%B0%E5%9F%BA%E6%9C%AC%E7%9A%84%E6%95%B0%E6%8D%AE%E9%80%9A%E9%81%93\"\u003e实现基本的数据通道\u003c/a\u003e\u003ca href=\"#%E6%96%87%E4%BB%B6%E4%BC%A0%E8%BE%93\"\u003e文件传输\u003c/a\u003e\u003ca href=\"#%E4%BF%AE%E6%94%B9%E4%BC%A0%E8%BE%93%E9%80%9F%E5%BA%A6%E9%99%90%E5%88%B6\"\u003e修改传输速度限制\u003c/a\u003e\u003ca href=\"#%E9%80%89%E6%8B%A9%E5%B9%B6%E8%AF%BB%E5%8F%96%E6%96%87%E4%BB%B6%E6%95%B0%E6%8D%AE\"\u003e选择并读取文件数据\u003c/a\u003e\u003ca href=\"#%E8%87%AA%E5%8A%A8%E4%B8%8B%E8%BD%BD%E6%96%87%E4%BB%B6\"\u003e自动下载文件\u003c/a\u003e\u003ca href=\"#%E5%AE%8C%E6%95%B4%E4%BB%A3%E7%A0%81-1\"\u003e完整代码\u003c/a\u003e\u003ca href=\"#%E9%9F%B3%E8%A7%86%E9%A2%91%E9%80%9A%E8%AF%9D\"\u003e音视频通话\u003c/a\u003e\u003ca href=\"#https\"\u003ehttps\u003c/a\u003e\u003ca href=\"#%E8%AE%BF%E9%97%AE%E9%9F%B3%E8%A7%86%E9%A2%91%E6%B5%81\"\u003e访问音视频流\u003c/a\u003e\u003ca href=\"#%E5%AE%8C%E6%95%B4%E4%BB%A3%E7%A0%81-2\"\u003e完整代码\u003c/a\u003e\u003ca href=\"#%E5%B1%8F%E5%B9%95%E5%85%B1%E4%BA%AB\"\u003e屏幕共享\u003c/a\u003e\u003ca href=\"#%E6%8D%95%E6%8D%89%E5%B1%8F%E5%B9%95\"\u003e捕捉屏幕\u003c/a\u003e\u003ca href=\"#%E5%AE%8C%E6%95%B4%E4%BB%A3%E7%A0%81-3\"\u003e完整代码\u003c/a\u003e\u003ca href=\"#nat%E7%A9%BF%E9%80%8F%E4%B9%8Bstunturn\"\u003eNAT穿透之STUN/TURN\u003c/a\u003e\u003ca href=\"#%E4%BF%A1%E4%BB%A4%E6%9C%8D%E5%8A%A1%E5%99%A8\"\u003e信令服务器\u003c/a\u003e\u003ca href=\"#%E4%BF%A1%E4%BB%A4%E6%9C%8D%E5%8A%A1%E5%AE%9E%E7%8E%B0\"\u003e信令服务实现\u003c/a\u003e\u003ca href=\"#%E5%AE%8C%E6%95%B4%E4%BB%A3%E7%A0%81-4\"\u003e完整代码\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://webrtc.org.cn/webrtc-tutorial-basic/\"\u003e详细请访问\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"简介\"\u003e简介\u003c/h1\u003e\n\u003cp\u003eWebRTC（网页实时通信技术），是一系列为了建立端到端文本或者随机数据的规范，标准，API和概念的统称。\u003c/p\u003e\n\u003cp\u003e任何实现了WebRTC标准的软件之间均可通信，如PC浏览器\u0026ndash;手机浏览器、浏览器\u0026ndash;App、App\u0026ndash;App。通信双方是对等的，但通常还要引入服务端，以便于对等端能够找到对方。\u003c/p\u003e\n\u003cp\u003e移动端浏览器对WebRTC的支持\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eAndroid 4.4以上\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003eiOS 11以上\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003eWebRTC应用不需要非常高性能就能够平稳运行、拥有良好体验。对于WebRTC来说，获取特定硬件的权限也不是必需的。Web应用和原生应用对比：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e原生应用会比Web应用更快，拥有更高级别的硬件权限；混合应用的运行速度更慢，不能使用移动设备的全部权限。\u003c/li\u003e\n\u003cli\u003e原生应用在不同的平台上的代码复用度有待提高；混合应用开发起来会更快，更省钱\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e结论：如果高性能和极致体验不是软件的必不可少的要求，那么，在绝大多数情况下，用户根本注意不到原生和混合WebRTC应用之间的差别。\u003c/p\u003e\n\u003ch1 id=\"实现基本的数据通道\"\u003e实现基本的数据通道\u003c/h1\u003e\n\u003cp\u003e对浏览器而言，WebRTC API处于底层且十分复杂。不过我们可以使用封装好的高级别的API\u0026mdash;- \u003ca href=\"https://github.com/feross/simple-peer\"\u003esimple-peer\u003c/a\u003e 是一个基础的，非常洁净的低层P2P连接封装器.下面的示例是 \u003ccode\u003esimple-peer\u003c/code\u003e 的一个标准例子。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003ehtml\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003ebody\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003estyle\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e        \u003cspan style=\"color:#75715e\"\u003e#outgoing {          width: 100%;          word-wrap: break-word;          white-space: normal;        }      \u0026lt;/style\u0026gt;    \u0026lt;form\u0026gt;      \u0026lt;textarea id=\u0026#34;incoming\u0026#34;\u0026gt;\u0026lt;/textarea\u0026gt;      \u0026lt;button type=\u0026#34;submit\u0026#34;\u0026gt;submit\u0026lt;/button\u0026gt;    \u0026lt;/form\u0026gt;    \u0026lt;pre id=\u0026#34;outgoing\u0026#34;\u0026gt;\u0026lt;/pre\u0026gt;    \u0026lt;script src=\u0026#34;simplepeer.min.js\u0026#34;\u0026gt;\u0026lt;/script\u0026gt;    \u0026lt;script\u0026gt;      const p = new SimplePeer({        initiator: location.hash === \u0026#39;#1\u0026#39;,        trickle: false      })\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      p\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eon(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;error\u0026#39;\u003c/span\u003e, err \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e console\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003elog(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;error\u0026#39;\u003c/span\u003e, err))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      p\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eon(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;signal\u0026#39;\u003c/span\u003e, data \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {        console\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003elog(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;SIGNAL\u0026#39;\u003c/span\u003e, JSON\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003estringify(data))        document\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003equerySelector(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#outgoing\u0026#39;\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003etextContent \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e JSON\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003estringify(data)      })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      document\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003equerySelector(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;form\u0026#39;\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eaddEventListener(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;submit\u0026#39;\u003c/span\u003e, ev \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {        ev\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epreventDefault()        p\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003esignal\u003c/span\u003e(JSON\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eparse(document\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003equerySelector(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#incoming\u0026#39;\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003evalue))      })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      p\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eon(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;connect\u0026#39;\u003c/span\u003e, () \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {        console\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003elog(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;CONNECT\u0026#39;\u003c/span\u003e)        p\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esend(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;whatever\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e Math\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003erandom())      })\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      p\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eon(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;data\u0026#39;\u003c/span\u003e, data \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {        console\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003elog(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;data: \u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e data)      })    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/\u003c/span\u003escript\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/\u003c/span\u003ebody\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026lt;/\u003c/span\u003ehtml\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e演示步骤:\u003c/p\u003e","title":"WebRTC初学Demo"},{"content":"原因无他，导致mac笔记本发热严重，要是一两次也就罢了，每天至少一次CPU 100%，打开活动监视器，都是这个Spotlight造成的。\n步骤如下\n关闭System Integrity Protection 进入恢复模式：重启电脑， 按住 Command 和 R。 输入命令\ncsrutil disable 因为Spotlist服务受System Integrity Protection保护，不关闭的话有可能无法关闭Spotlist服务，报错如下\nUnload failed: 150: Operation not permitted while System Integrity Protection is engaged 关闭Spotlight服务 sudo mdutil -a -i off sudo mdutil -a -d sudo launchctl unload -w /System/Library/LaunchAgents/com.apple.Spotlight.plist 如果收到报错\nUnload failed: 113: Could not find specified service 那就先加载Spotlight服务\nsudo mdutil -a -i on sudo launchctl load -w /System/Library/LaunchAgents/com.apple.Spotlight.plist 然后再执行服务卸载\n打开System Integrity Protection 进入恢复模式：重启电脑， 按住 Command 和 R。 输入命令\ncsrutil enable https://macpaw.com/how-to/disable-enable-system-integrity-protection\n","permalink":"https://blog.z6z8.cn/2021/10/14/%E5%85%B3%E9%97%ADspotlight/","summary":"\u003cp\u003e原因无他，导致mac笔记本发热严重，要是一两次也就罢了，每天至少一次CPU 100%，打开活动监视器，都是这个Spotlight造成的。\u003c/p\u003e\n\u003cp\u003e步骤如下\u003c/p\u003e\n\u003ch2 id=\"关闭system-integrity-protection\"\u003e关闭System Integrity Protection\u003c/h2\u003e\n\u003cp\u003e进入恢复模式：重启电脑， 按住 Command 和 R。\n输入命令\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecsrutil disable\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e因为Spotlist服务受System Integrity Protection保护，不关闭的话有可能无法关闭Spotlist服务，报错如下\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUnload failed: \u003cspan style=\"color:#ae81ff\"\u003e150\u003c/span\u003e: Operation \u003cspan style=\"color:#f92672\"\u003enot\u003c/span\u003e permitted \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e System Integrity Protection is engaged\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"关闭spotlight服务\"\u003e关闭Spotlight服务\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo mdutil \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ea \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ei off\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo mdutil \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ea \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ed\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo launchctl unload \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ew \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eSystem\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eLibrary\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eLaunchAgents\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003ecom\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eapple\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eSpotlight\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eplist\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e如果收到报错\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUnload failed: \u003cspan style=\"color:#ae81ff\"\u003e113\u003c/span\u003e: Could \u003cspan style=\"color:#f92672\"\u003enot\u003c/span\u003e find specified service\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e那就先加载Spotlight服务\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo mdutil \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ea \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ei on\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo launchctl load \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003ew \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eSystem\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eLibrary\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eLaunchAgents\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003ecom\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eapple\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eSpotlight\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eplist\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e然后再执行服务卸载\u003c/p\u003e\n\u003ch2 id=\"打开system-integrity-protection\"\u003e打开System Integrity Protection\u003c/h2\u003e\n\u003cp\u003e进入恢复模式：重启电脑， 按住 Command 和 R。\n输入命令\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecsrutil enable\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003ca href=\"https://macpaw.com/how-to/disable-enable-system-integrity-protection\"\u003ehttps://macpaw.com/how-to/disable-enable-system-integrity-protection\u003c/a\u003e\u003c/p\u003e","title":"关闭Spotlight"},{"content":"详细介绍参考 https://developer.apple.com/documentation/healthkit\nDemo下载\n简介 ​ HealthKit 为 iPhone 和 Apple Watch 上的健康和健身数据提供了一个中央存储库。在用户许可的情况下，应用程序与 HealthKit 通信以访问和共享此数据:\n收集和存储健康和健身数据\n分析和可视化数据\n社交互动\n下图来自于苹果开发者网站\n​ HealthKit 管理和合并来自多个来源的数据，用户可以在健康应用中查看和管理他们的所有数据，包括添加数据、删除数据和更改应用的权限；用户还可以编辑每种数据类型的分享权限。\n隐私 ​ 由于健康数据可能包含敏感的个人信息，因此应用程序必须获得用户的许可才能从 HealthKit 存储区读取数据或向其写入数据，并且应用程序还必须始终采取措施保护这些数据。\n​ HealthKit 为用户提供了更细粒度的数据权限控制。用户必须明确授予每个应用对 HealthKit 存储区读取和写入数据的权限。用户可以针对每种类型的数据分别授予或拒绝权限。例如，用户可以让允许应用读取步数数据，但不允许读取血糖水平。\n数据加密存储 ​ 用户的设备在本地存储所有 HealthKit 数据。为了安全起见，当用户锁定设备时，设备会加密 HealthKit 存储。因此，应用在后台运行时可能无法HealthKit存储中读取数据。但是手机被锁定时，应用程序仍然可以写入HealthKit存储。HealthKit 会临时缓存数据，并在用户解锁手机后立即将其保存到加密存储中。\n指定应用如何使用健康数据 ​ 除非应用旨在提供健康或健身服务，否则应用不得访问 HealthKit API（ 注意:影响应用上架）。此外，作为健康和健身服务的角色必须在营销文本和用户界面中明确。具体来说，以下指南适用于所有 HealthKit 应用程序：\n您的应用不得将通过使用 HealthKit 框架获得的信息用于广告或类似服务。 仍然可以在使用 HealthKit 框架的应用程序中投放广告，但不能使用 HealthKit中的数据来投放广告 未经用户明确许可，不得将通过 HealthKit 获得的任何信息透露给第三方。 即使获得许可，也只能将信息分享给向用户提供健康或健身服务的第三方。 不能将通过 HealthKit 获得的信息出售给广告平台、数据经纪人或信息经销商。 如果用户同意，可以与第三方共享他们的 HealthKit 数据以进行 医学研究。 必须向用户明确披露您和您的应用将如何使用他们的 HealthKit 数据。 提供隐私政策 ​ 必须为使用 HealthKit 框架的任何应用程序提供隐私政策。可以在以下站点找到有关创建隐私政策的指南：\n个人健康记录模型（适用于非 HIPAA 应用程序）： http : //www.healthit.gov/policy-researchers-implementers/personal-health-record-phr-model-privacy-notice HIPAA 模型（适用于 HIPAA 涵盖的应用程序）： http : //www.hhs.gov/ocr/privacy/hipaa/modelnotices.html 这些模型由美国国家卫生信息技术协调办公室 (ONC) 开发，旨在通过简单的语言来帮助用户易于理解。这些模型解释了应用程序如何收集和共享用户数据。这些模型仅供参考，Apple 明确表示不对您使用此类模型承担任何责任。\n应用程序 Info.plist 对于使用 HealthKit 框架的应用程序，需要在Info.plist中设置以下键值\nNSHealthShareUsageDescription ，一个简短描述，向用户解释为什么需要HealthKit读取权限，用于读取HealthKit数据。\nNSHealthUpdateUsageDescription，一个简短描述，向用户解释为什么需要HealthKit写入权限，用于写入HealthKit数据。\n如果不设置相应的键值，那么应用程序在调用相关API时会触发崩溃。\n请求权限 获取权限状态 HealthData.healthStore.getRequestStatusForAuthorization 请求权限 HealthData.healthStore.requestAuthorization let allTypes = Set([HKObjectType.workoutType(), HKObjectType.quantityType(forIdentifier: .activeEnergyBurned)!, HKObjectType.quantityType(forIdentifier: .distanceCycling)!, HKObjectType.quantityType(forIdentifier: .distanceWalkingRunning)!, HKObjectType.quantityType(forIdentifier: .heartRate)!]) healthStore.requestAuthorization(toShare: allTypes, read: allTypes) { (success, error) in if !success { // Handle the error here. } } 当请求新权限时，系统会弹出一下界面\n下图来自于苹果开发者网站\n读取数据 ​ 访问数据的主要方式有以下三种：\n直接方法调用。 HealthKit 存储提供了直接访问特征数据的方法。 查询。 查询从 HealthKit 存储中返回所请求数据的当前快照。 长时间运行的查询。 这些查询会继续在后台运行，并在 HealthKit 存储发生更改时通知应用程序。 查询 查询返回 HealthKit 存储中数据的当前快照。所有查询都在匿名后台队列上运行。查询完成后，它会在后台队列上执行结果处理程序。HealthKit 提供了不同类型的查询，每个查询都旨在从 HealthKit 存储中返回不同类型的数据。\n样本查询。 这是一个通用查询。使用示例查询访问任何类型的示例数据。当您想要对结果进行排序或限制返回的样本总数时，样本查询特别有用。有关更多信息，请参阅 HKSampleQuery 锚定对象查询。 使用此查询来搜索已添加到HealthKit存储或从存储中删除的对象。第一次运行锚定查询时，它会返回当前存储中的所有匹配样本。在后续运行中，它仅返回自上次运行以来已添加或删除的项目。有关更多信息，请参阅 HKAnchoredObjectQuery 统计查询。 使用此查询对匹配样本集执行统计计算。可以使用统计查询来计算集合中的总和、最小值、最大值或平均值。有关更多信息，请参阅 HKStatisticsQuery 统计收集查询。 使用此查询可在一系列固定长度的时间间隔内执行多个统计查询。创建图表时经常使用这些查询。它们提供了一种计算事物的简单方法，例如每天消耗的卡路里总数或每五分钟间隔内所采取的步数。有关更多信息，请参阅 HKStatisticsCollectionQuery 关联查询。 使用此查询对关联数据执行复杂搜索。这些查询可以包含存储在关联样本类型的单独谓词。如果您只想匹配相关类型，请改用 样本查询。有关更多信息，请参阅 HKCorrelationQuery 来源查询。 使用此查询来搜索已将匹配样本保存到 HealthKit 存储的来源（应用程序和设备）。来源查询列出了保存特定样品类型的所有源。有关更多信息，请参阅 HKSourceQuery 活动汇总查询。 使用此查询来搜索用户的活动摘要信息。每个活动摘要对象都包含给定日期的用户活动摘要。您可以查询一天或几天的范围。有关更多信息，请参阅 HKActivitySummaryQuery 文档查询。 使用此查询来搜索健康文件。有关更多信息，请参阅 HKDocumentQuery 长时间运行的查询 长时间运行的查询会继续运行匿名后台队列，并在 HealthKit 存储发生更改时通知应用程序。此外，观察者查询可以注册后台任务。这让 HealthKit 在发生更新时在后台唤醒对应的应用程序。\nHealthkit 提供以下长时间运行的查询：\n观察者查询。 这个长时间运行的查询会监控 HealthKit 存储并通知匹配样本的任何更改。当您希望收到有关存储更改的通知时，请使用观察者查询。您可以注册观察者查询以进行后台任务。有关更多信息，请参阅 HKObserverQuery 锚定对象查询。 除了返回修改数据的当前快照之外，锚定对象查询还可以充当长时间运行的查询。如果启用，它将继续在后台运行，在匹配样本添加到存储或从存储中删除时提供更新。与观察者查询不同，这些更新包括已添加或删除的项目列表；但是，锚定对象查询不能注册用于后台任务。有关更多信息，请参阅 HKAnchoredObjectQuery 统计收集查询。 除了计算统计集合的当前快照之外，此查询还可以充当长时间运行的查询。如果将匹配的样本添加到存储或从存储中删除，此查询将重新计算统计信息收集并更新您的应用程序。无法注册统计收集查询以进行后台任务。有关更多信息，请参阅 HKStatisticsCollectionQuery 活动汇总查询。 除了计算用户活动摘要的当前快照之外，此查询还可以充当长时间运行的查询。如果用户的活动摘要数据发生更改，此查询将重新计算活动摘要并更新您的应用。无法注册活动摘要查询以进行后台任务。有关更多信息，请参阅 HKActivitySummaryQuery 一个例子 示例主要读取以下数据\n步数 步行+跑步距离 已爬楼层 对应枚举为\nHKQuantityTypeIdentifier.stepCount HKQuantityTypeIdentifier.distanceWalkingRunning HKQuantityTypeIdentifier.flightsClimbed 查询方式为统计收集查询 HKStatisticsCollectionQuery。相关表格和图表显示使用 TableView、 CollectionView 和 OCKCartesianChartView\n参考 https://developer.apple.com/documentation/healthkit\n","permalink":"https://blog.z6z8.cn/2021/10/13/ios-healthkit-%E5%81%A5%E5%BA%B7%E6%A1%86%E6%9E%B6%E7%AE%80%E4%BB%8B/","summary":"\u003cp\u003e详细介绍参考 \u003ca href=\"https://developer.apple.com/documentation/healthkit\"\u003ehttps://developer.apple.com/documentation/healthkit\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"http://139.155.43.7/wp-content/uploads/2021/10/CreatingAMobilityHealthApp-2.zip\" title=\"CreatingAMobilityHealthApp 2\"\u003eDemo下载\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"简介\"\u003e简介\u003c/h1\u003e\n\u003cp\u003e​ HealthKit 为 iPhone 和 Apple Watch 上的健康和健身数据提供了一个中央存储库。在用户许可的情况下，应用程序与 HealthKit 通信以访问和共享此数据:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e收集和存储健康和健身数据\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e分析和可视化数据\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e社交互动\u003c/p\u003e\n\u003cp\u003e下图来自于苹果开发者网站\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2021/10/1.png\"\u003e\u003c/p\u003e\n\u003cp\u003e​ HealthKit 管理和合并来自多个来源的数据，用户可以在健康应用中查看和管理他们的所有数据，包括添加数据、删除数据和更改应用的权限；用户还可以编辑每种数据类型的分享权限。\u003c/p\u003e\n\u003ch1 id=\"隐私\"\u003e隐私\u003c/h1\u003e\n\u003cp\u003e​ 由于健康数据可能包含敏感的个人信息，因此应用程序必须获得用户的许可才能从 HealthKit 存储区读取数据或向其写入数据，并且应用程序还必须始终采取措施保护这些数据。\u003c/p\u003e\n\u003cp\u003e​ HealthKit 为用户提供了更细粒度的数据权限控制。用户必须明确授予每个应用对 HealthKit 存储区读取和写入数据的权限。用户可以针对每种类型的数据分别授予或拒绝权限。例如，用户可以让允许应用读取步数数据，但不允许读取血糖水平。\u003c/p\u003e\n\u003ch2 id=\"数据加密存储\"\u003e数据加密存储\u003c/h2\u003e\n\u003cp\u003e​ 用户的设备在本地存储所有 HealthKit 数据。为了安全起见，当用户锁定设备时，设备会加密 HealthKit 存储。因此，应用在后台运行时可能无法HealthKit存储中读取数据。但是手机被锁定时，应用程序仍然可以写入HealthKit存储。HealthKit 会临时缓存数据，并在用户解锁手机后立即将其保存到加密存储中。\u003c/p\u003e\n\u003ch2 id=\"指定应用如何使用健康数据\"\u003e指定应用如何使用健康数据\u003c/h2\u003e\n\u003cp\u003e​ \u003cstrong\u003e\u003cem\u003e除非应用旨在提供健康或健身服务，否则应用不得访问 HealthKit API\u003c/em\u003e\u003c/strong\u003e（ \u003ccode\u003e注意:影响应用上架\u003c/code\u003e）。此外，作为健康和健身服务的角色必须在营销文本和用户界面中明确。具体来说，以下指南适用于所有 HealthKit 应用程序：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e您的应用不得将通过使用 HealthKit 框架获得的信息用于广告或类似服务。 \u003ccode\u003e仍然可以在使用 HealthKit 框架的应用程序中投放广告，但不能使用 HealthKit中的数据来投放广告\u003c/code\u003e\u003c/li\u003e\n\u003cli\u003e未经用户明确许可，不得将通过 HealthKit 获得的任何信息透露给第三方。 \u003cstrong\u003e\u003cem\u003e即使获得许可，也只能将信息分享给向用户提供健康或健身服务的第三方\u003c/em\u003e\u003c/strong\u003e。\u003c/li\u003e\n\u003cli\u003e不能将通过 HealthKit 获得的信息出售给广告平台、数据经纪人或信息经销商。\u003c/li\u003e\n\u003cli\u003e如果用户同意，可以与第三方共享他们的 HealthKit 数据以进行 \u003cstrong\u003e\u003cem\u003e医学研究\u003c/em\u003e\u003c/strong\u003e。\u003c/li\u003e\n\u003cli\u003e必须向用户明确披露您和您的应用将如何使用他们的 HealthKit 数据。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"提供隐私政策\"\u003e提供隐私政策\u003c/h2\u003e\n\u003cp\u003e​ 必须为使用 HealthKit 框架的任何应用程序提供隐私政策。可以在以下站点找到有关创建隐私政策的指南：\u003c/p\u003e","title":"iOS HealthKit 健康框架简介"},{"content":"原因是Safari的Websocket连接是基于HTTP/1.1的，需要把Websocket Sever的应答也基于HTTP/1.1\n一个不合适应答报文示例： 1、Safari请求基于HTTP/1.1建立WebSocket连接 2、Server应答为基于HTTP/1.0，那么Safari将关闭本次WebSocket连接请求\nGET / HTTP/1.1 #Safari请求基于HTTP/1.1建立WebSocket连接 Upgrade: websocket Connection: Upgrade Host: localhost:8000 Origin: http://localhost:8000 Pragma: no-cache Cache-Control: no-cache Sec-WebSocket-Key: psuWu4PKpvC5PlimntI1uw== Sec-WebSocket-Version: 13 Sec-WebSocket-Extensions: x-webkit-deflate-frame User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15 HTTP/1.0 101 Switching Protocols #Server应答为基于HTTP/1.0，那么Safari将关闭本次WebSocket连接请求 Server: SimpleHTTP/0.6 Python/2.7.15 Date: Wed, 08 Sep 2021 07:26:20 GMT Upgrade: websocket Connection: Upgrade Sec-WebSocket-Accept: Mwq3JIMwIENZgkjooYLJobX4L90= ","permalink":"https://blog.z6z8.cn/2021/09/08/safari-websocket-invalid-http-version-string-http-1-0/","summary":"\u003cp\u003e原因是Safari的Websocket连接是基于HTTP/1.1的，需要把Websocket Sever的应答也基于HTTP/1.1\u003c/p\u003e\n\u003cp\u003e一个不合适应答报文示例：\n1、Safari请求基于HTTP/1.1建立WebSocket连接\n2、Server应答为基于HTTP/1.0，那么Safari将关闭本次WebSocket连接请求\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eGET / HTTP/1.1   #Safari请求基于HTTP/1.1建立WebSocket连接\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUpgrade: websocket\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eConnection: Upgrade\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eHost: localhost:8000\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eOrigin: http://localhost:8000\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePragma: no-cache\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCache-Control: no-cache\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSec-WebSocket-Key: psuWu4PKpvC5PlimntI1uw==\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSec-WebSocket-Version: 13\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSec-WebSocket-Extensions: x-webkit-deflate-frame\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUser-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/14.1.2 Safari/605.1.15\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eHTTP/1.0 101 Switching Protocols  #Server应答为基于HTTP/1.0，那么Safari将关闭本次WebSocket连接请求\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eServer: SimpleHTTP/0.6 Python/2.7.15\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDate: Wed, 08 Sep 2021 07:26:20 GMT\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUpgrade: websocket\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eConnection: Upgrade\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eSec-WebSocket-Accept: Mwq3JIMwIENZgkjooYLJobX4L90=\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Safari Websocket: Invalid HTTP version string: HTTP/1.0"},{"content":"1、缓存和日志 ~/Library/Caches ~/Library/Logs 这两个可以安全地删除\n2、其他 - Application Support\n里面存放三方App的一些缓存和记录，可以挑选删除。 如 VSCode 相关 ~/Library/Application Support/Code/User/workspaceStorage ~/Library/Application Support/Code/Cache*\n3、Xcode 执行命令 xcrun simctl delete unavailable\n删除 ~/Library/Developer/CoreSimulator/Caches\nhttps://zhuanlan.zhihu.com/p/349862578\n","permalink":"https://blog.z6z8.cn/2021/09/07/macos-%E6%B8%85%E7%90%86%E7%A3%81%E7%9B%98%E7%A9%BA%E9%97%B4/","summary":"\u003cp\u003e1、缓存和日志\n\u003ccode\u003e~/Library/Caches\u003c/code\u003e \u003ccode\u003e~/Library/Logs\u003c/code\u003e\n这两个可以安全地删除\u003c/p\u003e\n\u003cp\u003e2、其他 - Application Support\u003c/p\u003e\n\u003cp\u003e里面存放三方App的一些缓存和记录，可以挑选删除。\n如 VSCode 相关\n\u003ccode\u003e~/Library/Application Support/Code/User/workspaceStorage\u003c/code\u003e \u003ccode\u003e~/Library/Application Support/Code/Cache*\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e3、Xcode\n执行命令\n\u003ccode\u003excrun simctl delete unavailable\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e删除\n\u003ccode\u003e~/Library/Developer/CoreSimulator/Caches\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e\u003ca href=\"https://zhuanlan.zhihu.com/p/349862578\"\u003ehttps://zhuanlan.zhihu.com/p/349862578\u003c/a\u003e\u003c/p\u003e","title":"macOS 清理磁盘空间"},{"content":"https://blog.51cto.com/fengyuzaitu/2060964\n[h264 @ 04241fc0] top block unavailable for requested intra mode [h264 @ 04241fc0] error while decoding MB 2 0, bytestream 243592 [h264 @ 04241fc0] concealing 8160 DC, 8160 AC, 8160 MV errors in I frame [h264 @ 036da7a0] top block unavailable for requested intra mode [h264 @ 036da7a0] error while decoding MB 87 0, bytestream 13676 [h264 @ 036da7a0] concealing 8122 DC, 8122 AC, 8122 MV errors in P frame [swscaler @ 054140c0] deprecated pixel format used, make sure you did set range correctly [h264 @ 0447a540] concealing 7913 DC, 7913 AC, 7913 MV errors in P frame [h264 @ 0447a960] top block unavailable for requested intra modetop block unavailable for requested intra mode -1 [h264 @ 0447a960] error while decoding MB 52 0, bytestream 18938\n背景知识\nIDR: 在H.264中，图像以序列为单位进行组织。一个序列的第一个图像叫做 IDR 图像（立即刷新图像），IDR 图像都是 I 帧图像。H.264 引入 IDR 图像是为了解码的重同步，当×××解码到 IDR 图像时，立即将参考帧队列清空，将已解码的数据全部输出或抛弃，重新查找参数集，开始一个新的序列。这样，如果前一个序列出现重大错误，在这里可以获得重新同步的机会。IDR图像之后的图像永远不会使用IDR之前的图像的数据来解码。IDR 图像一定是 I 图像，但 I 图像不一定是 IDR 图像。I帧之后的图像有可能会使用I帧之前的图像做运动参考。\nNALU类型 标识NAL单元中的RBSP数据类型，其中，nal_unit_type为1， 2， 3， 4， 5及12的NAL单元称为VCL的NAL单元，其他类型的NAL单元为非VCL的NAL单元。 0：未规定 1：非IDR图像中不采用数据划分的片段 2：非IDR图像中A类数据划分片段 3：非IDR图像中B类数据划分片段 4：非IDR图像中C类数据划分片段 5：IDR图像的片段 6：补充增强信息 (SEI) 7：序列参数集 8：图像参数集 9：分割符 10：序列结束符 11：流结束符 12：填充数据 13 – 23：保留 24 – 31：未规定\nav_read_frame函数打印当前接收的NALU单元的类型 nal_unit_type: 7, nal_ref_idc: 3 nal_unit_type: 8, nal_ref_idc: 3 nal_unit_type: 6, nal_ref_idc: 0 nal_unit_type: 5, nal_ref_idc: 3 说明I帧前面就会有SPS/PPS图像参数的相关信息，实际上当收到I帧，也就可以解码出图像（会根据前面的SPS/PPS参数进行解码参数的设置），虽然FFmpeg内部会缓冲几帧，但是缓冲的帧速度还是 很快的根本不需要考虑延时 当然，如果是播放文件的话，在播放结束后，要想取出来就需要传递空的AVPacket进去，需要调用avcodec_send_packet（pAVCodecContext, NULL） 才能够播放完毕\n","permalink":"https://blog.z6z8.cn/2021/09/02/%E8%BD%AC%E8%BD%BDtop-block-unavailable-for-requested-intra-mode/","summary":"\u003cp\u003e\u003ca href=\"https://blog.51cto.com/fengyuzaitu/2060964\"\u003ehttps://blog.51cto.com/fengyuzaitu/2060964\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e[h264 @ 04241fc0] top block unavailable for requested intra mode\n[h264 @ 04241fc0] error while decoding MB 2 0, bytestream 243592\n[h264 @ 04241fc0] concealing 8160 DC, 8160 AC, 8160 MV errors in I frame\n[h264 @ 036da7a0] top block unavailable for requested intra mode\n[h264 @ 036da7a0] error while decoding MB 87 0, bytestream 13676\n[h264 @ 036da7a0] concealing 8122 DC, 8122 AC, 8122 MV errors in P frame\n[swscaler @ 054140c0] deprecated pixel format used, make sure you did set range correctly\n[h264 @ 0447a540] concealing 7913 DC, 7913 AC, 7913 MV errors in P frame\n[h264 @ 0447a960] top block unavailable for requested intra modetop block unavailable for requested intra mode -1\n[h264 @ 0447a960] error while decoding MB 52 0, bytestream 18938\u003c/p\u003e","title":"[转载]top block unavailable for requested intra mode"},{"content":"key平台默认取值范围描述ancommon0整数\u0026ndash;{0,1}禁用音频vncommon0整数\u0026ndash;{0,1}禁用视频nodispcommon0整数\u0026ndash;{0,1}禁用图像显示。和vn的区别是：vn不解码不渲染；nodisp解码不渲染volumecommon100整数\u0026ndash;[0,100]音量loopcommon1整数设置循环播放次数infbufcommon0整数\u0026ndash;{0,1}不限制输入缓冲区大小（对实时流很有用）max-fpscommon31整数\u0026ndash;[-1,121]允许的最大播放帧率，当视频的实际帧率大于这个数值时，将丢弃部分视频帧。framedropcommon0整数\u0026ndash;[-1,120]ijkplaer以音频帧为时间基准，当视频帧和音频帧不同步时，允许丢弃的视频帧数。seek-at-startcommon0非负整数起始播放位置的偏移量，单位毫秒。例如可以设置从第20秒的位置播放subtitlecommon0整数\u0026ndash;{0,1}是否解码字幕数据find_stream_infocommon1整数\u0026ndash;{0,1}读取和解码流以使用启发式方法填充丢失的信息。用来优化播放体验。overlay-formatcommonSDL_FCC_RV32{SDL_FCC_YV12，SDL_FCC_I420，SDL_FCC_RV16，SDL_FCC_RV24，SDL_FCC_RV32}图像颜色空间格式。\nSDL_FCC_YV12 \u0026mdash;- bpp=12, Planar mode: Y + V + U (3 planes)\nSDL_FCC_I420 \u0026mdash;- bpp=12, Planar mode: Y + U + V (3 planes)\nSDL_FCC_RV16 \u0026mdash;- bpp=16, RGB565\nSDL_FCC_RV24 \u0026mdash;- bpp=24, RGB888\nSDL_FCC_RV32 \u0026mdash;- bpp=32, RGBX8888start-on-preparedcommon1整数\u0026ndash;{0,1}如果设置为1的话，播放准备工作完成后自动开始播放video-pictq-sizecommon3整数\u0026ndash;[3,16]视频帧队列大小。max-buffer-sizecommon15 1024 1024整数\u0026ndash;[0,15 1024 1024]预读数据的缓冲区大小。min-framescommon50000整数\u0026ndash;[2,50000]停止预读的最小帧数。即预读帧数大于等于该值时，将停止预读。first-high-water-mark-mscommon100整数\u0026ndash;[100,5000]（缓冲）读取线程的第一次唤醒时间，单位毫秒next-high-water-mark-mscommon1000整数-- [100,5000]（缓冲）读取线程的第二次唤醒时间，单位毫秒last-high-water-mark-mscommon5000整数\u0026ndash;[100,5000]（缓冲）读取线程的第三次唤醒时间，单位毫秒acket-bufferingcommon1整数\u0026ndash;{0,1}暂停输出，直到停止后读取足够的数据包sync-av-startcommon1整数\u0026ndash;{0,1}播放开始时对音视频进行同步操作iformatcommonNULL字符串强制使用指定格式，如RTSP, H264,FLV, MKV, MP4, AVI等no-time-adjustcommon0整数\u0026ndash;{0,1}如果使用实时模式而不是调整模式，则返回流中的位置。这个用例主要是在使用自定义的不可搜索数据源时，该数据源以不是流开头的缓冲区开始。我们希望 get_current_position 返回流中的时间，而不是播放器的内部时间。preset-5-1-center-mix-levelcommon_1/sqrt(2)_双精度浮点数\u0026ndash;[-32,32]为 5.1 声道预设中央混合电平enable-accurate-seekcommon0整数\u0026ndash;{0,1}使用精确寻帧。例如，拖动播放后，会寻找最近的关键帧进行播放，很有可能关键帧的位置不是拖动后的位置，而是较前的位置。可以设置这个参数来解决问题accurate-seek-timeoutcommon5000整数\u0026ndash;[0,5000]设置精确寻帧的超时时间。单位，毫秒skip-calc-frame-ratecommon0整数\u0026ndash;{0,1}不计算真实的帧率async-init-decodercommon0整数\u0026ndash;{0,1}异步创建解码器videotoolboxiOS0{0,1}是否使用videoToolbox框架解码。（非零表示使用）videotoolbox-max-frame-widthiOS0正整数使用videoToolbox框架解码帧画面最大宽度，0表示使用视频原始宽度。当设置大于0的值，且视频原始宽度大于设置值，则会进行相应缩放处理。videotoolbox-asynciOS0{0,1}异步解码模式kVTDecodeFrame_EnableAsynchronousDecompressionvideotoolbox-wait-asynciOS1{0,1}是否调用VTDecompressionSessionWaitForAsynchronousFrames。作用是等待异步解码完成后再返回。例如，在销毁播放器资源前调用，以保证资源能被正确释放。videotoolbox-handle-resolution-changeiOS0{0,1}自动处理分辨率变化\n","permalink":"https://blog.z6z8.cn/2021/08/30/ijkplayer-%E5%88%9D%E5%A7%8B%E5%8C%96%E5%8F%82%E6%95%B0-ijkffoptions/","summary":"\u003cp\u003ekey平台默认取值范围描述ancommon0整数\u0026ndash;{0,1}禁用音频vncommon0整数\u0026ndash;{0,1}禁用视频nodispcommon0整数\u0026ndash;{0,1}禁用图像显示。和vn的区别是：vn不解码不渲染；nodisp解码不渲染volumecommon100整数\u0026ndash;[0,100]音量loopcommon1整数设置循环播放次数infbufcommon0整数\u0026ndash;{0,1}不限制输入缓冲区大小（对实时流很有用）max-fpscommon31整数\u0026ndash;[-1,121]允许的最大播放帧率，当视频的实际帧率大于这个数值时，将丢弃部分视频帧。framedropcommon0整数\u0026ndash;[-1,120]ijkplaer以音频帧为时间基准，当视频帧和音频帧不同步时，允许丢弃的视频帧数。seek-at-startcommon0非负整数起始播放位置的偏移量，单位毫秒。例如可以设置从第20秒的位置播放subtitlecommon0整数\u0026ndash;{0,1}是否解码字幕数据find_stream_infocommon1整数\u0026ndash;{0,1}读取和解码流以使用启发式方法填充丢失的信息。用来优化播放体验。overlay-formatcommonSDL_FCC_RV32{SDL_FCC_YV12，SDL_FCC_I420，SDL_FCC_RV16，SDL_FCC_RV24，SDL_FCC_RV32}图像颜色空间格式。\u003cbr\u003e\nSDL_FCC_YV12 \u0026mdash;- bpp=12, Planar mode: Y + V + U (3 planes)\u003cbr\u003e\nSDL_FCC_I420 \u0026mdash;- bpp=12, Planar mode: Y + U + V (3 planes)\u003cbr\u003e\nSDL_FCC_RV16 \u0026mdash;- bpp=16, RGB565\u003cbr\u003e\nSDL_FCC_RV24 \u0026mdash;- bpp=24, RGB888\u003cbr\u003e\nSDL_FCC_RV32 \u0026mdash;- bpp=32, RGBX8888start-on-preparedcommon1整数\u0026ndash;{0,1}如果设置为1的话，播放准备工作完成后自动开始播放video-pictq-sizecommon3整数\u0026ndash;[3,16]视频帧队列大小。max-buffer-sizecommon15 \u003cem\u003e1024\u003c/em\u003e 1024整数\u0026ndash;[0,15 \u003cem\u003e1024\u003c/em\u003e 1024]预读数据的缓冲区大小。min-framescommon50000整数\u0026ndash;[2,50000]停止预读的最小帧数。即预读帧数大于等于该值时，将停止预读。first-high-water-mark-mscommon100整数\u0026ndash;[100,5000]（缓冲）读取线程的第一次唤醒时间，单位毫秒next-high-water-mark-mscommon1000整数-- [100,5000]（缓冲）读取线程的第二次唤醒时间，单位毫秒last-high-water-mark-mscommon5000整数\u0026ndash;[100,5000]（缓冲）读取线程的第三次唤醒时间，单位毫秒acket-bufferingcommon1整数\u0026ndash;{0,1}暂停输出，直到停止后读取足够的数据包sync-av-startcommon1整数\u0026ndash;{0,1}播放开始时对音视频进行同步操作iformatcommonNULL字符串强制使用指定格式，如RTSP, H264,FLV, MKV, MP4, AVI等no-time-adjustcommon0整数\u0026ndash;{0,1}如果使用实时模式而不是调整模式，则返回流中的位置。这个用例主要是在使用自定义的不可搜索数据源时，该数据源以不是流开头的缓冲区开始。我们希望 get_current_position 返回流中的时间，而不是播放器的内部时间。preset-5-1-center-mix-levelcommon_1/sqrt(2)_双精度浮点数\u0026ndash;[-32,32]为 5.1 声道预设中央混合电平enable-accurate-seekcommon0整数\u0026ndash;{0,1}使用精确寻帧。例如，拖动播放后，会寻找最近的关键帧进行播放，很有可能关键帧的位置不是拖动后的位置，而是较前的位置。可以设置这个参数来解决问题accurate-seek-timeoutcommon5000整数\u0026ndash;[0,5000]设置精确寻帧的超时时间。单位，毫秒skip-calc-frame-ratecommon0整数\u0026ndash;{0,1}不计算真实的帧率async-init-decodercommon0整数\u0026ndash;{0,1}异步创建解码器videotoolboxiOS0{0,1}是否使用videoToolbox框架解码。（非零表示使用）videotoolbox-max-frame-widthiOS0正整数使用videoToolbox框架解码帧画面最大宽度，0表示使用视频原始宽度。当设置大于0的值，且视频原始宽度大于设置值，则会进行相应缩放处理。videotoolbox-asynciOS0{0,1}异步解码模式kVTDecodeFrame_EnableAsynchronousDecompressionvideotoolbox-wait-asynciOS1{0,1}是否调用VTDecompressionSessionWaitForAsynchronousFrames。作用是等待异步解码完成后再返回。例如，在销毁播放器资源前调用，以保证资源能被正确释放。videotoolbox-handle-resolution-changeiOS0{0,1}自动处理分辨率变化\u003c/p\u003e","title":"ijkplayer 初始化参数 IJKFFOptions"},{"content":"Details Unable to install \u0026#34;MyApp\u0026#34; Domain: com.apple.dt.MobileDeviceErrorDomain Code: -402620375 - The code signature version is no longer supported. Domain: com.apple.dt.MobileDeviceErrorDomain Code: -402620375 User Info: { DVTRadarComponentKey = 261622; MobileDeviceErrorCode = \u0026#34;(0xE8008029)\u0026#34;; \u0026#34;com.apple.dtdevicekit.stacktrace\u0026#34; = ( 0 DTDeviceKitBase 0x000000011edd83b8 DTDKCreateNSErrorFromAMDErrorCode + 220 1 DTDeviceKitBase 0x000000011ee16ae1 __90-[DTDKMobileDeviceToken installApplicationBundleAtPath:withOptions:andError:withCallback:]_block_invoke + 155 2 DVTFoundation 0x0000000107881b7c DVTInvokeWithStrongOwnership + 71 3 DTDeviceKitBase 0x000000011ee16822 -[DTDKMobileDeviceToken installApplicationBundleAtPath:withOptions:andError:withCallback:] + 1440 4 IDEiOSSupportCore 0x000000011eccf999 __118-[DVTiOSDevice(DVTiPhoneApplicationInstallation) processAppInstallSet:appUninstallSet:installOptions:completionBlock:]_block_invoke.294 + 3534 5 DVTFoundation 0x00000001079b4931 __DVT_CALLING_CLIENT_BLOCK__ + 7 6 DVTFoundation 0x00000001079b655b __DVTDispatchAsync_block_invoke + 1191 7 libdispatch.dylib 0x00007fff20508603 _dispatch_call_block_and_release + 12 8 libdispatch.dylib 0x00007fff205097e6 _dispatch_client_callout + 8 9 libdispatch.dylib 0x00007fff2050f5ca _dispatch_lane_serial_drain + 606 10 libdispatch.dylib 0x00007fff2051008d _dispatch_lane_invoke + 366 11 libdispatch.dylib 0x00007fff20519bed _dispatch_workloop_worker_thread + 811 12 libsystem_pthread.dylib 0x00007fff206b04c0 _pthread_wqthread + 314 13 libsystem_pthread.dylib 0x00007fff206af493 start_wqthread + 15 ); } - 可能是因为对framework的签名不一致导致，有的是 Do Not Embed, 有的是 Embed and Sign\n可能的解决办法： App 的TARGETS -\u0026gt; General -\u0026gt; Frameworks,Libraries,and EmbeddedContent -\u0026gt; 将 Embed and Sign 修改为 Do Not Embed。\nhttps://developer.apple.com/forums/thread/679182\n","permalink":"https://blog.z6z8.cn/2021/07/30/xcode%E8%B0%83%E8%AF%95iphone%E7%9C%9F%E6%9C%BA-%EF%BC%9Acode-signature-version-is-no-longer-supported/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDetails\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUnable to install \u0026#34;MyApp\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDomain: com.apple.dt.MobileDeviceErrorDomain\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCode: -402620375\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eThe code signature version is no longer supported.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDomain: com.apple.dt.MobileDeviceErrorDomain\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCode: -402620375\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUser Info: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  DVTRadarComponentKey = 261622;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  MobileDeviceErrorCode = \u0026#34;(0xE8008029)\u0026#34;;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026#34;com.apple.dtdevicekit.stacktrace\u0026#34; = (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e0  DTDeviceKitBase           0x000000011edd83b8 DTDKCreateNSErrorFromAMDErrorCode + 220\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e1  DTDeviceKitBase           0x000000011ee16ae1 __90-[DTDKMobileDeviceToken installApplicationBundleAtPath:withOptions:andError:withCallback:]_block_invoke + 155\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e2  DVTFoundation            0x0000000107881b7c DVTInvokeWithStrongOwnership + 71\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e3  DTDeviceKitBase           0x000000011ee16822 -[DTDKMobileDeviceToken installApplicationBundleAtPath:withOptions:andError:withCallback:] + 1440\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e4  IDEiOSSupportCore          0x000000011eccf999 __118-[DVTiOSDevice(DVTiPhoneApplicationInstallation) processAppInstallSet:appUninstallSet:installOptions:completionBlock:]_block_invoke.294 + 3534\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e5  DVTFoundation            0x00000001079b4931 __DVT_CALLING_CLIENT_BLOCK__ + 7\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e6  DVTFoundation            0x00000001079b655b __DVTDispatchAsync_block_invoke + 1191\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e7  libdispatch.dylib          0x00007fff20508603 _dispatch_call_block_and_release + 12\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e8  libdispatch.dylib          0x00007fff205097e6 _dispatch_client_callout + 8\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e9  libdispatch.dylib          0x00007fff2050f5ca _dispatch_lane_serial_drain + 606\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e10 libdispatch.dylib          0x00007fff2051008d _dispatch_lane_invoke + 366\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e11 libdispatch.dylib          0x00007fff20519bed _dispatch_workloop_worker_thread + 811\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e12 libsystem_pthread.dylib       0x00007fff206b04c0 _pthread_wqthread + 314\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e13 libsystem_pthread.dylib       0x00007fff206af493 start_wqthread + 15\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e可能是因为对framework的签名不一致导致，有的是 \u003ccode\u003eDo Not Embed\u003c/code\u003e, 有的是 \u003ccode\u003eEmbed and Sign\u003c/code\u003e\u003c/p\u003e","title":"Xcode调试iPhone真机 ：code signature version is no longer supported"},{"content":"启用/关闭Bitcode Xcode设置路径为 Build Settings -\u0026gt; Build Options -\u0026gt; Enable Bitcode\n设置后，改变的是构建过程中环境变量 ENABLE_BITCODE 的值。\n需要注意的是，这个设置在不同的构建中表现不一样\n平时用于调试、部署的构建，启用Bitcode后，仅进行Bitcode依赖检测，不会生成Bitcode符号到产物中。（项目中即使有非Bitcode库，也不影响调试、部署） 当进行Archive打包时，启用Bitcode后，则要求项目的所有依赖库均启用Bitcode(所有库均要有Bitcode符号) 另外，Xcode构建时也会读取环境变量 HIDE_BITCODE_SYMBOLS，这个变量默认YES。当 HIDE_BITCODE_SYMBOL=NO 且 ENABLE_BITCODE=YES 时，则要求项目的所有依赖库均要有Bitcode符号\n强制所有构建启用Bitcode 添加 -fembed-bitcode 编译标识。设置路径为 Build Settings -\u0026gt; Apple Clang - Custom Compiler Flags -\u0026gt; Other C Flags\n添加后，无论哪种构建，均会强制启用Bitcode。\n而通过 Build Settings -\u0026gt; Build Options -\u0026gt; Enable Bitcode 路径启用Bitcode，本质是添加了编译标识 -fembed-bitcode-marker，区别如下\n-fembed-bitcode ,任何类型的Build都会带上Bitcode符号 -fembed-bitcode-marker, 只是在产物中做标记，表示可以支持Bitcode；而在Archive打包时，才会生成Bitcode符号 XcodeBuild构建如何启用BitCode Shell环境中构建SDK（静态库、动态库）的场景，此时没有Archive构建，那么可以设置 BITCODE_GENERATION_MODE=bitcode 解决。\nBITCODE_GENERATION_MODE可以是 marker，也可以是 bitcode，默认取 marker\n例如:\nxcodebuild BITCODE_GENERATION_MODE=bitcode ..... 如何查看SDK中是否含有Bitcode符号 可以通过 Mach-O View 工具查看，是否含有 Section (__LLVM ,__bitcode ).\n也可以使用 otool 命令查看 命令为 otool -s __LLVM __bitcode mach-o文件.\n","permalink":"https://blog.z6z8.cn/2021/07/01/xcode%E6%9E%84%E5%BB%BA%E5%85%B3%E4%BA%8Ebitcode%E7%9A%84%E8%AF%B4%E6%98%8E/","summary":"\u003ch2 id=\"启用关闭bitcode\"\u003e启用/关闭Bitcode\u003c/h2\u003e\n\u003cp\u003eXcode设置路径为 \u003ccode\u003eBuild Settings -\u0026gt; Build Options -\u0026gt; Enable Bitcode\u003c/code\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2021/07/2.png\"\u003e\u003c/p\u003e\n\u003cp\u003e设置后，改变的是构建过程中环境变量 \u003ccode\u003eENABLE_BITCODE\u003c/code\u003e 的值。\u003c/p\u003e\n\u003cp\u003e需要注意的是，这个设置在不同的构建中表现不一样\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e平时用于调试、部署的构建，启用Bitcode后，仅进行Bitcode依赖检测，不会生成Bitcode符号到产物中。（项目中即使有非Bitcode库，也不影响调试、部署）\u003c/li\u003e\n\u003cli\u003e当进行Archive打包时，启用Bitcode后，则要求项目的所有依赖库均启用Bitcode(所有库均要有Bitcode符号)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e另外，Xcode构建时也会读取环境变量 \u003ccode\u003eHIDE_BITCODE_SYMBOLS\u003c/code\u003e，这个变量默认YES。当 \u003ccode\u003eHIDE_BITCODE_SYMBOL=NO\u003c/code\u003e 且 \u003ccode\u003eENABLE_BITCODE=YES\u003c/code\u003e 时，则要求项目的所有依赖库均要有Bitcode符号\u003c/p\u003e\n\u003ch2 id=\"强制所有构建启用bitcode\"\u003e强制所有构建启用Bitcode\u003c/h2\u003e\n\u003cp\u003e添加 \u003ccode\u003e-fembed-bitcode\u003c/code\u003e 编译标识。设置路径为 \u003ccode\u003eBuild Settings -\u0026gt; Apple Clang - Custom Compiler Flags -\u0026gt; Other C Flags\u003c/code\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2021/07/2.png\"\u003e\u003c/p\u003e\n\u003cp\u003e添加后，无论哪种构建，均会强制启用Bitcode。\u003c/p\u003e\n\u003cp\u003e而通过 Build Settings -\u0026gt; Build Options -\u0026gt; Enable Bitcode 路径启用Bitcode，本质是添加了编译标识 -fembed-bitcode-marker，区别如下\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003e-fembed-bitcode\u003c/code\u003e ,任何类型的Build都会带上Bitcode符号\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003e-fembed-bitcode-marker\u003c/code\u003e, 只是在产物中做标记，表示可以支持Bitcode；而在Archive打包时，才会生成Bitcode符号\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"xcodebuild构建如何启用bitcode\"\u003eXcodeBuild构建如何启用BitCode\u003c/h2\u003e\n\u003cp\u003eShell环境中构建SDK（静态库、动态库）的场景，此时没有Archive构建，那么可以设置 \u003ccode\u003eBITCODE_GENERATION_MODE=bitcode\u003c/code\u003e 解决。\u003c/p\u003e\n\u003cp\u003eBITCODE_GENERATION_MODE可以是 \u003ccode\u003emarker\u003c/code\u003e，也可以是 \u003ccode\u003ebitcode\u003c/code\u003e，默认取 \u003ccode\u003emarker\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e例如:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003excodebuild BITCODE_GENERATION_MODE\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ebitcode .....\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"如何查看sdk中是否含有bitcode符号\"\u003e如何查看SDK中是否含有Bitcode符号\u003c/h2\u003e\n\u003cp\u003e可以通过 \u003ccode\u003eMach-O View\u003c/code\u003e 工具查看，是否含有 \u003ccode\u003eSection (__LLVM ,__bitcode )\u003c/code\u003e.\u003c/p\u003e","title":"Xcode构建关于Bitcode的说明"},{"content":"关于 GENERATE_SOURCEMAP 的作用原理在这篇文章中介绍过。 http://139.155.43.7/2019/10/15/create-react-app-%ef%bc%9a%e4%b8%8d%e4%ba%a7%e7%94%9fsource-map%e6%9d%a5%e7%bc%a9%e5%87%8f%e6%89%93%e5%8c%85%e6%96%87%e4%bb%b6%e4%bd%93%e7%a7%af/\n可以通过创建 .env 环境变量文件影响 react-scripts start/build 等命令。其实还有另一种更灵活的方式设置环境变量,使用 export 可以对不同的命令设置不同的环境变量.\n打开 package.json，找到 scripts 配置项\n\u0026#34;scripts\u0026#34;: { \u0026#34;start\u0026#34;: \u0026#34;react-scripts start\u0026#34;, \u0026#34;build\u0026#34;: \u0026#34;react-scripts build\u0026#34;, \u0026#34;test\u0026#34;: \u0026#34;react-scripts test\u0026#34;, \u0026#34;eject\u0026#34;: \u0026#34;react-scripts eject\u0026#34; }, 添加 export GENERATE_SOURCEMAP=true/false 修改为以下配置\n\u0026#34;scripts\u0026#34;: { \u0026#34;start\u0026#34;: \u0026#34;export GENERATE_SOURCEMAP=true \u0026amp;\u0026amp; react-scripts start\u0026#34;, \u0026#34;build\u0026#34;: \u0026#34;export GENERATE_SOURCEMAP=false \u0026amp;\u0026amp; react-scripts build\u0026#34;, \u0026#34;test\u0026#34;: \u0026#34;react-scripts test\u0026#34;, \u0026#34;eject\u0026#34;: \u0026#34;react-scripts eject\u0026#34; }, 这样，在运行start调试时，产生sourceMap方便调试；运行build命令时，关闭sourceMap减少产物文件大小。\n","permalink":"https://blog.z6z8.cn/2021/06/15/%E8%AE%BE%E7%BD%AE%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F%E5%85%B3%E9%97%ADreact-scripts%E7%9A%84sourcemap%E7%94%9F%E6%88%90/","summary":"\u003cp\u003e关于 \u003ccode\u003eGENERATE_SOURCEMAP\u003c/code\u003e 的作用原理在这篇文章中介绍过。\n\u003ca href=\"http://139.155.43.7/2019/10/15/create-react-app-%ef%bc%9a%e4%b8%8d%e4%ba%a7%e7%94%9fsource-map%e6%9d%a5%e7%bc%a9%e5%87%8f%e6%89%93%e5%8c%85%e6%96%87%e4%bb%b6%e4%bd%93%e7%a7%af/\"\u003ehttp://139.155.43.7/2019/10/15/create-react-app-%ef%bc%9a%e4%b8%8d%e4%ba%a7%e7%94%9fsource-map%e6%9d%a5%e7%bc%a9%e5%87%8f%e6%89%93%e5%8c%85%e6%96%87%e4%bb%b6%e4%bd%93%e7%a7%af/\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e可以通过创建 \u003ccode\u003e.env\u003c/code\u003e 环境变量文件影响 \u003ccode\u003ereact-scripts start/build\u003c/code\u003e 等命令。其实还有另一种更灵活的方式设置环境变量,使用 \u003ccode\u003eexport\u003c/code\u003e 可以对不同的命令设置不同的环境变量.\u003c/p\u003e\n\u003cp\u003e打开 \u003ccode\u003epackage.json\u003c/code\u003e，找到 \u003ccode\u003escripts\u003c/code\u003e 配置项\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;scripts\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;start\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;react-scripts start\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;build\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;react-scripts build\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;test\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;react-scripts test\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;eject\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;react-scripts eject\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e添加 \u003ccode\u003eexport GENERATE_SOURCEMAP=true/false\u003c/code\u003e 修改为以下配置\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;scripts\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;start\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;export GENERATE_SOURCEMAP=true \u0026amp;\u0026amp; react-scripts start\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;build\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;export GENERATE_SOURCEMAP=false \u0026amp;\u0026amp; react-scripts build\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;test\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;react-scripts test\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;eject\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;react-scripts eject\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e这样，在运行start调试时，产生sourceMap方便调试；运行build命令时，关闭sourceMap减少产物文件大小。\u003c/p\u003e","title":"设置环境变量关闭react-scripts的sourceMap生成"},{"content":"https://github.com/gm958spanda/React-ZLView https://gitee.com/gm958spanda/React-ZLView\nZLView ZLView base react , super and sub , coordinate by x-y-width-height；基于react的视图，使用x-y-width-height坐标系\n示例 使用多个div节点绘制正弦曲线 import React from \u0026#39;react\u0026#39;; import * as zl from \u0026#39;react-zlview\u0026#39; class App extends React.Component { private appView : zl.View | undefined; render() { if(this.appView === undefined) { this.appView = new zl.View(); this.appView.x = 200; this.appView.y = 100; this.appView.width = 1000; this.appView.height = 50; this.appView.backgroudColor = \u0026#34;white\u0026#34;; let colors = [\u0026#34;red\u0026#34;,\u0026#34;blue\u0026#34;,\u0026#34;gredd\u0026#34;]; for (let i = 0 ; 999 \u0026gt; i ; i ++) { let sub = new zl.View(); sub.x = i; sub.y = Math.sin(i / 3.14) * 15 + this.appView.height / 2; sub.width = 3; sub.height = 3; sub.backgroudColor = colors[i %3]; this.appView.addSubview(sub); } } // 也可以直接返回 this.appView.reactElement(); // return this.appView.reactElement(); return ( {this.appView.reactElement()} ); } } ZLView的坐标系统 一个ZLView对应一个 React Component，也可说是对 React Component 的封装；ZLView采用固定CSS样式，将 position 设置为 absolute，然后设置 left/right/widht/height。当然ZLView对此作了封装：\n属性含义x以父视图左上定点为原点的坐标系中，x轴位置y以父视图左上定点为原点的坐标系中，y轴位置width宽度height高度left同xrightx+widthtop同ybottomy+heightcenter_x(x+width)/2center_y(y+height)/2center(center_x,center_y)\nZLView的尺寸单位 支持 px 和 rem 两种，默认使用 px 单位。 可以设置 ZLCurrentSizeUnit 值来改变尺寸单位。另外，px和rem的换算，默认使用 1rem=16px，也可以修改 ZLCurrentSizeUnitOneRemToPx 来改变这个换算比例.\nZLView的生命周期 源自React Component的生命周期\n方法含义viewDidMount/addListenViewDidMount/removeListenViewDidMountReact.componentDidMountviewWillUnmount/addListenViewWillUnMount/removeListenViewWillUnMountReact.componentWillUnmount\n父视图和子视图 superView 获取父视图\nremoveFromSuperview 从父图中移除\nsubViews 获取子视图列表\naddSubview 添加子视图\n刷新视图 refresh 刷新视图，本质是调用 React.setState。 ZLView的属性变更后，需要主动调用 refresh 来刷新视图\nlayoutSubViews,是一个通知类型的方法，用于重新布局子视图列表；触发时机是在React.render返回结果前\nZLView获取DOM节点 可以通过实现方法 onReactRefCallback 来获取，也可以调用 addListenOnReactRefCallback 添加新方法获取.\n监听DOM事件 通过 addListenDOMEvent 和 removeListenDOMEvent 可以监听/移除监听DOM事件，例如\nview.addListenDOMEvent(\u0026#34;onClick\u0026#34;, (e:React.SyntheticEvent)=\u0026gt;{ console.log(\u0026#34;clicked\u0026#34;); }) 继承ZLView ZLView支持继承以自定义视图样式，通常需要重写的方法 __reactRender__ 和 __htmlAttributes__，前者用于返回React.render数据，后缀用于修改 CSS样式\n示列:\nclass CustomView extends zl.View { /** * 渲染 React render */ protected __reactRender__(children?:React.ReactNode[]) : React.ReactElement { // html attributes let attr = this.__htmlAttributes__(); return React.createElement(\u0026#34;canvas\u0026#34;/*自定义标签*/, attr.toReactClassAttributes(),children); } /** * 子类可重写 * @returns html attributes */ protected __htmlAttributes__() : ZLHtmlAttribute { let attr = super.__htmlAttributes__(); attr.style.backgroundColor = \u0026#34;white\u0026#34;;//背景色永远是白色 return attr } Transform 封装了matrix2d和matrix3d变换 ZLTransform，内部实现使用了矩阵乘法，支持 translate 平动、 scale 缩放、 rotate 旋转、 skew 倾斜、 refect 翻转。\nlet view:zl.View = new zl.View(); view.width = 200; view.height = 100; view.backgroundColor = \u0026#34;yellow\u0026#34;; let transform = new zl.Transform(); transform.rotate(Math.PI); transform.translate(10,190); view.transform = transform; view.refresh(); 背景色、前景色、不透明度、是否可见 backgroundColor 略 color 略 opacity 略 visibility 略 设置阴影 简单封装了 css box shadow，可以直接设置 ZLView.boxShadow 属性\nview.backgroundColor = \u0026#34;yellow\u0026#34;; let shadow = new zl.BoxShadow(); shadow.color = \u0026#34;green\u0026#34;; view.boxShadow = shadow; 边框 支持简单设置\nborderColor 边框颜色 borderStyle 边框样式 borderWidth 边框宽度 动画 简单封装了CSS动画，直接作用在ZLView上\n/** * 开启一个3秒动画 * 尺寸从(100,200)变化到（200，100） * 背景色从red到yellow * 动画曲线使用cubic-bezier（1,0,0,1) */ let view = new zl.View() view.width = 100; view.height = 200; view.backgroudColor = \u0026#34;red\u0026#34;; view.cssAnimation({to:()=\u0026gt;{ view.backgroudColor = \u0026#34;yellow\u0026#34;; view.x = 100; view.width = 200; view.height = 100; let transform = new zl.Transform(); transform.rotate(Math.PI); transform.translate(10,190); }, duration:3000, timingFunction:zl.CSSAnimationTimingFunction.cubicBezier, cubicBezierValue:[1,0,0,1], end:()=\u0026gt;{ console.log(\u0026#34;animation end\u0026#34;); } }); ZLRouter路由 封装 react-router-dom。引入页面概念 ZLViewPage，一个路由对应一个页面，采用严格模式匹配路由的 path\nclass HomePage extends zl.ViewPage { viewDidLoad() { super.viewDidLoad(); this.view.backgroudColor = \u0026#34;red\u0026#34;; } viewDidMount() { setTimeout(()=\u0026gt;{ this.router?.push(\u0026#34;/other\u0026#34;); },5000); console.log( this.constructor.name + \u0026#34; mount\u0026#34;); } viewWillUnmount() { console.log( this.constructor.name + \u0026#34; unmount\u0026#34;); } } class OtherPage extends zl.ViewPage { viewDidLoad() { super.viewDidLoad(); this.view.backgroudColor = \u0026#34;blue\u0026#34;; } viewDidMount() { console.log( this.constructor.name + \u0026#34; mount\u0026#34;); } viewWillUnmount() { console.log( this.constructor.name + \u0026#34; unmount\u0026#34;); } } class App extends React.Component { private router: zl.Router | undefined; render() { if (this.router === undefined) { this.router = new zl.Router(); this.router.registRoute(\u0026#34;/\u0026#34;,HomePage); this.router.registRoute(\u0026#34;/other\u0026#34;, OtherPage); } return this.router.reactElement(); } } 注册路由 let router = new zl.Router(); router.registRoute(\u0026#34;/\u0026#34;,HomePage); router.registRoute(\u0026#34;/other\u0026#34;,OtherPage); 也可以直接注册 ZLViewPage\n// 等同于 router.registRoute(\u0026#34;/OtherPage\u0026#34;,OtherPage); router.registViewPage(OtherPage); 路由跳转 router.push(\u0026#34;/other\u0026#34;); router.replace(\u0026#34;/\u0026#34;); 也可以直接push ZLViewPage\n// 等同于 router.push(\u0026#34;/OtherPage\u0026#34;); router.pushViewPage(OtherPage); ","permalink":"https://blog.z6z8.cn/2021/05/28/zlview-%E4%BD%BF%E7%94%A8-x-y-width-height%E5%9D%90%E6%A0%87%E5%B8%83%E5%B1%80/","summary":"\u003cp\u003e\u003ca href=\"https://github.com/gm958spanda/React-ZLView\"\u003ehttps://github.com/gm958spanda/React-ZLView\u003c/a\u003e \u003ca href=\"https://gitee.com/gm958spanda/React-ZLView\"\u003ehttps://gitee.com/gm958spanda/React-ZLView\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"zlview\"\u003eZLView\u003c/h1\u003e\n\u003cp\u003eZLView base react , super and sub , coordinate by x-y-width-height；基于react的视图，使用x-y-width-height坐标系\u003c/p\u003e\n\u003ch2 id=\"示例\"\u003e示例\u003c/h2\u003e\n\u003cp\u003e使用多个div节点绘制正弦曲线\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2021/05/1.png\"\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-ts\" data-lang=\"ts\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eReact\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;react\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ezl\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;react-zlview\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eApp\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eReact\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eComponent\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eappView\u003c/span\u003e : \u003cspan style=\"color:#66d9ef\"\u003ezl.View\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eundefined\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003erender\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eappView\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eundefined\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eappView\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ezl\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eView\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eappView\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ex\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e200\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eappView\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eappView\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ewidth\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eappView\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eheight\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e50\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eappView\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ebackgroudColor\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;white\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolors\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;red\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;blue\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;gredd\u0026#34;\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; \u003cspan style=\"color:#ae81ff\"\u003e999\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e ; \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esub\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ezl\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eView\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003esub\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ex\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003esub\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Math.\u003cspan style=\"color:#a6e22e\"\u003esin\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3.14\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e15\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eappView\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eheight\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003esub\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ewidth\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003esub\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eheight\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003esub\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ebackgroudColor\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolors\u003c/span\u003e[\u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eappView\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eaddSubview\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003esub\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 也可以直接返回 this.appView.reactElement();\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#75715e\"\u003e// return  this.appView.reactElement();\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eappView\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ereactElement\u003c/span\u003e()}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"zlview的坐标系统\"\u003eZLView的坐标系统\u003c/h2\u003e\n\u003cp\u003e一个ZLView对应一个 \u003ccode\u003eReact Component\u003c/code\u003e，也可说是对 \u003ccode\u003eReact Component\u003c/code\u003e 的封装；ZLView采用固定CSS样式，将 \u003ccode\u003eposition\u003c/code\u003e 设置为 \u003ccode\u003eabsolute\u003c/code\u003e，然后设置 \u003ccode\u003eleft/right/widht/height\u003c/code\u003e。当然ZLView对此作了封装：\u003c/p\u003e","title":"React-ZLView 使用 x-y-width-height坐标布局"},{"content":"初始化项目 npm init 通过 npm init 初始化项目来创建用户 package.json 文件 也可以 npm init -y 这个是使用的默认的配置，我个人使用的是 npm init\n创建tsconfig.json文件 tsc --init 就会生成一个tsconfig.json文件\n修改tsconfig.json默认文件 把这两个注释打开\n{ \u0026#34;compilerOptions\u0026#34;: { \u0026#34;declaration\u0026#34;: true, //打包之后是否生成声明文件 \u0026#34;outDir\u0026#34;: \u0026#34;./dist\u0026#34;, //输出文件 } } 添加exclude,忽略dist文件 在打包的时候会排除这里面指定的路径文件\n{ \u0026#34;compilerOptions\u0026#34;: { }, \u0026#34;exclude\u0026#34;: [ \u0026#34;./dist\u0026#34; ] } 安装typescript依赖 npm install typescript -D 开始编码 创建xxxxx.ts文件,写入typescript代码 例如\nconst arrayMap = (array: [], callback:(item: any,index: number, arr: any[]) =\u0026gt; any): any =\u0026gt; { let i = -1 const len = array.length let resArray = [] while (++i \u0026lt; len){ resArray.push(callback(array[i],i,array)) } return resArray } export = arrayMap 对代码进行编译 tsc 此时我们的项目就会多了一个dist目录\n登录npm 大家没有npm账号的可以注册一个\n这个是网址\nhttps://www.npmjs.com 然后在编辑器终端里面输入\nnpm login 接着就会出来用户名、密码、邮箱这些依次填一下\n创建.npmignore文件 在项目根目录里创建一个.npmjgnore\n这个其实和.gitignor差不多，就是你发npm包的时候，希望哪些文件或者文件夹不发到这个npm上\n版本号 在package.json里面版本号， 每发布一次都要修改一下\n发布 npm publish 发布成功\n原文https://segmentfault.com/a/1190000021740976\n","permalink":"https://blog.z6z8.cn/2021/05/28/%E3%80%90%E8%BD%AC%E8%BD%BD%E3%80%91%E4%BD%BF%E7%94%A8typescript%E5%BC%80%E5%8F%91%E9%A1%B9%E7%9B%AE%E6%89%93%E5%8C%85%E5%8F%91%E5%B8%83%E5%88%B0npm/","summary":"\u003ch1 id=\"初始化项目\"\u003e初始化项目\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm init\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e通过 \u003ccode\u003enpm init\u003c/code\u003e 初始化项目来创建用户 \u003ccode\u003epackage.json\u003c/code\u003e 文件\n也可以 \u003ccode\u003enpm init -y\u003c/code\u003e 这个是使用的默认的配置，我个人使用的是 \u003ccode\u003enpm init\u003c/code\u003e\u003c/p\u003e\n\u003ch1 id=\"创建tsconfigjson文件\"\u003e创建tsconfig.json文件\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etsc --init\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e就会生成一个tsconfig.json文件\u003c/p\u003e\n\u003cp\u003e修改tsconfig.json默认文件\n把这两个注释打开\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;compilerOptions\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;declaration\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e, \u003cspan style=\"color:#75715e\"\u003e//打包之后是否生成声明文件\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;outDir\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;./dist\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#75715e\"\u003e//输出文件\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e添加exclude,忽略dist文件\n在打包的时候会排除这里面指定的路径文件\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026#34;compilerOptions\u0026#34;: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026#34;exclude\u0026#34;: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026#34;./dist\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"安装typescript依赖\"\u003e安装typescript依赖\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm install typescript -D\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"开始编码\"\u003e开始编码\u003c/h1\u003e\n\u003cp\u003e创建xxxxx.ts文件,写入typescript代码\n例如\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-ts\" data-lang=\"ts\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003earrayMap\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003earray\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e [], \u003cspan style=\"color:#a6e22e\"\u003ecallback\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eitem\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eany\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003enumber\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003earr\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eany\u003c/span\u003e[]) \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eany\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eany\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003elen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003earray\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresArray\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e []\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e (\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003elen\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eresArray\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003epush\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecallback\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003earray\u003c/span\u003e[\u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e],\u003cspan style=\"color:#a6e22e\"\u003ei\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003earray\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresArray\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003earrayMap\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"对代码进行编译\"\u003e对代码进行编译\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etsc\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e此时我们的项目就会多了一个dist目录\u003c/p\u003e","title":"【转载】使用TypeScript开发项目打包发布到npm"},{"content":"需要在 tsconfig.json 中配置以下参数\n{ \u0026#34;noEmit\u0026#34;: false, \u0026#34;declaration\u0026#34;: true, \u0026#34;declarationDir\u0026#34;: \u0026#34;dist/declaration\u0026#34;, \u0026#34;outDir\u0026#34;: \u0026#34;dist\u0026#34; } noEmit , 若要导出 d.ts 文件，必须为false。否则会忽略 declaration 相关参数 declaration,是否导出 d.ts 文件，当为true时且 noEmit 为true时才会进行导出操作. declarationDir， d.ts 文件存放的目录路径。当不设置改参数时，将使用 outDir 的值 outDir，将typescript 转换成js文件、以及 d.ts 文件的存放目录 配置完成后，运行 tsc --build tsconfig.json 即可\n","permalink":"https://blog.z6z8.cn/2021/05/24/typescript-%E5%AF%BC%E5%87%BA-d-ts%E5%A3%B0%E6%98%8E%E6%96%87%E4%BB%B6/","summary":"\u003cp\u003e需要在 \u003ccode\u003etsconfig.json\u003c/code\u003e 中配置以下参数\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;noEmit\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;declaration\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;declarationDir\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;dist/declaration\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;outDir\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;dist\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e\u003ccode\u003enoEmit\u003c/code\u003e , 若要导出 \u003ccode\u003ed.ts\u003c/code\u003e 文件，必须为false。否则会忽略 \u003ccode\u003edeclaration\u003c/code\u003e 相关参数\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003edeclaration\u003c/code\u003e,是否导出 \u003ccode\u003ed.ts\u003c/code\u003e 文件，当为true时且 \u003ccode\u003enoEmit\u003c/code\u003e 为true时才会进行导出操作.\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003edeclarationDir\u003c/code\u003e， \u003ccode\u003ed.ts\u003c/code\u003e 文件存放的目录路径。当不设置改参数时，将使用 \u003ccode\u003eoutDir\u003c/code\u003e 的值\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003eoutDir\u003c/code\u003e，将typescript 转换成js文件、以及 \u003ccode\u003ed.ts\u003c/code\u003e 文件的存放目录\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e配置完成后，运行 \u003ccode\u003etsc --build tsconfig.json\u003c/code\u003e 即可\u003c/p\u003e","title":"typescript 导出 d.ts声明文件"},{"content":"版本依赖宏 当前系统支持的最小版本 __IPHONE_OS_VERSION_MIN_REQUIRED\n当前系统支持的最大版本 __IPHONE_OS_VERSION_MAX_ALLOWED\n@interface ViewA : UIView #if __IPHONE_OS_VERSION_MIN_REQUIRED \u0026gt;= __IPHONE_9_0 。。。 。。。 。。。 #endif @end @available 和版本依赖宏的功能类似，不过是一个编译指令，在运行时失效,用来判断当前运行的版本环境\nif (@available(iOS 9.0,*)) { //iOS 9.0版本及以上系统环境执行此代码块 ..... } DEBUG 和 __DEBUG 用来判断是Release还是Debug运行模式。DEBUG定义为1或者TRUE\n#if DEBUG NSLog(Debug模式) #endi API版本宏 API_AVAILABLE 指定API在最小系统版本中可用\n// 在 iOS 10.0版本及以后可用 API_AVAILABLE(ios(10.0)) @interface StepSlider : UIControl @end // 在 iOS 14.0版本及以后可用 - (instancetype)initWithFrame:(CGRect)frame primaryAction:(nullable UIAction *)primaryAction API_AVAILABLE(ios(14.0)); API降级宏 API_DEPRECATED 指定API在相应版本后不推荐使用\n// 9.0之后，不推荐使用UIAlertView，应使用UIAlertController替换 UIKIT_EXTERN API_DEPRECATED(UIAlertView is deprecated. Use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert instead, ios(2.0, 9.0)) API_UNAVAILABLE(tvos) @interface UIAlertView : UIView @end API不可用宏 API_UNAVAILABLE / OBJC_UNAVAILABLE / NS_UNAVAILABLE // tvos ,watchos平台不可用 @property (nonatomic, readwrite, nullable, copy) NSString *testabcd API_UNAVAILABLE(tvos, watchos); // 方法被删除，不再使用 -(void)funcA API_UNAVAILABLE(unavailable since now) // 方法不可用 -(void)funcB NS_UNAVAILABLE; C/C++ extern 宏 __BEGIN_DECLS 一般在头文件中使用，用来适配 .c 和 .cpp 的不同语法（也就是c/c++的语法差异）\n__BEGIN_DECLS CGSize getStatusBaSize(void); __END_DECLS 区分模拟器和真机宏 TARGET_IPHONE_SIMULATOR TARGET_IPHONE_SIMULATOR \u0026mdash;- iPhone模拟器 类似的还有 TARGET_OS_IPHONE, TARGET_OS_IOS 等等 ","permalink":"https://blog.z6z8.cn/2021/04/27/ios-%E7%BC%96%E8%AF%91%E5%AE%8F%E4%B8%8E%E6%8C%87%E4%BB%A4/","summary":"\u003ch2 id=\"版本依赖宏\"\u003e版本依赖宏\u003c/h2\u003e\n\u003cp\u003e当前系统支持的最小版本 __IPHONE_OS_VERSION_MIN_REQUIRED\u003c/p\u003e\n\u003cp\u003e当前系统支持的最大版本 __IPHONE_OS_VERSION_MAX_ALLOWED\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e@interface ViewA : UIView\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#if __IPHONE_OS_VERSION_MIN_REQUIRED  \u0026gt;=  __IPHONE_9_0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e。。。\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e。。。\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e。。。\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#endif\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e@end\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"available\"\u003e@available\u003c/h2\u003e\n\u003cp\u003e和版本依赖宏的功能类似，不过是一个编译指令，在运行时失效,用来判断当前运行的版本环境\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (@available(iOS \u003cspan style=\"color:#ae81ff\"\u003e9.0\u003c/span\u003e,\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//iOS 9.0版本及以上系统环境执行此代码块\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    .....\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"debug-和-__debug\"\u003eDEBUG 和 __DEBUG\u003c/h2\u003e\n\u003cp\u003e用来判断是Release还是Debug运行模式。DEBUG定义为1或者TRUE\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#if DEBUG\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        NSLog(Debug模式)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#endi\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"api版本宏-api_available\"\u003eAPI版本宏 API_AVAILABLE\u003c/h2\u003e\n\u003cp\u003e指定API在最小系统版本中可用\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 在 iOS 10.0版本及以后可用\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003eAPI_AVAILABLE(ios(\u003cspan style=\"color:#ae81ff\"\u003e10.0\u003c/span\u003e)) \u003cspan style=\"color:#66d9ef\"\u003e@interface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eStepSlider\u003c/span\u003e : \u003cspan style=\"color:#a6e22e\"\u003eUIControl\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 在 iOS 14.0版本及以后可用\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003einstancetype\u003c/span\u003e)initWithFrame:(CGRect)frame primaryAction:(nullable UIAction \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)primaryAction API_AVAILABLE(ios(\u003cspan style=\"color:#ae81ff\"\u003e14.0\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"api降级宏-api_deprecated\"\u003eAPI降级宏 API_DEPRECATED\u003c/h2\u003e\n\u003cp\u003e指定API在相应版本后不推荐使用\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 9.0之后，不推荐使用UIAlertView，应使用UIAlertController替换\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003eUIKIT_EXTERN API_DEPRECATED(UIAlertView is deprecated. Use UIAlertController with a preferredStyle of UIAlertControllerStyleAlert instead, ios(\u003cspan style=\"color:#ae81ff\"\u003e2.0\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e9.0\u003c/span\u003e)) API_UNAVAILABLE(tvos)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@interface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUIAlertView\u003c/span\u003e : \u003cspan style=\"color:#a6e22e\"\u003eUIView\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"api不可用宏-api_unavailable--objc_unavailable--ns_unavailable\"\u003eAPI不可用宏 API_UNAVAILABLE / OBJC_UNAVAILABLE / NS_UNAVAILABLE\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// tvos ,watchos平台不可用\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e@property\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003enonatomic\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003ereadwrite\u003c/span\u003e, nullable, \u003cspan style=\"color:#66d9ef\"\u003ecopy\u003c/span\u003e) NSString \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003etestabcd  API_UNAVAILABLE(tvos, watchos);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 方法被删除，不再使用\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e-(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003efuncA\u003c/span\u003e  API_UNAVAILABLE(unavailable since now)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 方法不可用\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)funcB NS_UNAVAILABLE;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"cc-extern-宏-__begin_decls\"\u003eC/C++ extern 宏 __BEGIN_DECLS\u003c/h2\u003e\n\u003cp\u003e一般在头文件中使用，用来适配 \u003ccode\u003e.c\u003c/code\u003e 和 \u003ccode\u003e.cpp\u003c/code\u003e 的不同语法（也就是c/c++的语法差异）\u003c/p\u003e","title":"iOS 编译宏与指令"},{"content":"ImageOptim 是macOS系统下的图像二次压缩工具集合，支持GUI模式和CLI模式。源码在https://github.com/ImageOptim/ImageOptim\nCLI模式可参考 https://imageoptim.com/command-line.html\n例如 非阻塞模式，异步将当前文件夹下的所有图片进行二次压缩\nopen -a ImageOptim . 阻塞模式,同步将当前文件夹下所有png图片进行二次压缩\n/Applications/ImageOptim.app/Contents/MacOS/ImageOptim *.png ","permalink":"https://blog.z6z8.cn/2021/04/22/imageoptim-cli%EF%BC%88%E5%91%BD%E4%BB%A4%E8%A1%8C%EF%BC%89/","summary":"\u003cp\u003eImageOptim 是macOS系统下的图像二次压缩工具集合，支持GUI模式和CLI模式。源码在https://github.com/ImageOptim/ImageOptim\u003c/p\u003e\n\u003cp\u003eCLI模式可参考\n\u003ca href=\"https://imageoptim.com/command-line.html\"\u003ehttps://imageoptim.com/command-line.html\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e例如\n非阻塞模式，异步将当前文件夹下的所有图片进行二次压缩\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eopen -a ImageOptim .\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e阻塞模式,同步将当前文件夹下所有png图片进行二次压缩\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/Applications/ImageOptim.app/Contents/MacOS/ImageOptim *.png\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"ImageOptim CLI（命令行）"},{"content":"和iOS上的使用方式大致相同\n#import \u0026#34;ViewController.h\u0026#34; #import @interface ViewController() @property (nonatomic,strong) WKWebView *webView; @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; WKWebViewConfiguration *config = [[WKWebViewConfiguration alloc] init]; self.webView = [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config]; [self.view addSubview:self.webView]; [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@\u0026#34;http://www.baidu.com\u0026#34;]]]; } @end 另外，还需要配置下工程文件，以允许WKWebView访问网络。需要配置的地方有两处 ","permalink":"https://blog.z6z8.cn/2021/04/08/macos-app%E4%BD%BF%E7%94%A8wkwebview/","summary":"\u003cp\u003e和iOS上的使用方式大致相同\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-obj-c\" data-lang=\"obj-c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#import \u0026#34;ViewController.h\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#import\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@interface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eViewController\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@property\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003enonatomic\u003c/span\u003e,\u003cspan style=\"color:#66d9ef\"\u003estrong\u003c/span\u003e) WKWebView \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ewebView;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@implementation\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eViewController\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003eviewDidLoad\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [super viewDidLoad];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    WKWebViewConfiguration \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003econfig \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[WKWebViewConfiguration alloc] init];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    self.webView \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[WKWebView alloc] initWithFrame:self.view.bounds configuration:config];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [self.view addSubview:self.webView];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     [self.webView loadRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;http://www.baidu.com\u0026#34;\u003c/span\u003e]]];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e另外，还需要配置下工程文件，以允许WKWebView访问网络。需要配置的地方有两处\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2021/04/%E6%88%AA%E5%B1%8F2021-04-08-%E4%B8%8B%E5%8D%887.17.48.png\"\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2021/04/%E6%88%AA%E5%B1%8F2021-04-08-%E4%B8%8B%E5%8D%887.17.23.png\"\u003e\u003c/p\u003e","title":"macOS App使用WKWebView"},{"content":"使用brew安装telnet时，报错 Error: Your Xcode does not support macOS 11.2. It is either outdated or was modified. Please update your Xcode or delete it if no updates are available.\nbrew install telnet Updating Homebrew... Warning: You are using macOS 11.2. We do not provide support for this pre-release version. You will encounter build failures with some formulae. Please create pull requests instead of asking for help on Homebrew\u0026#39;s GitHub, Twitter or any other official channels. You are responsible for resolving any issues you experience while you are running this pre-release version. ==\u0026gt; Downloading https://opensource.apple.com/tarballs/libtelnet/libtelnet-13.tar Already downloaded: /Users/zxs.zl/Library/Caches/Homebrew/downloads/4fe26613ac3f91bd2fa2ed4e9ca39a043c6fd5960c4e0a3f063c672911900665--libtelnet-13.tar.gz ==\u0026gt; Downloading https://opensource.apple.com/tarballs/remote_cmds/remote_cmds-63 Already downloaded: /Users/zxs.zl/Library/Caches/Homebrew/downloads/557d5b69c452e48e5337f6d80e827514cd2218e1c02dcd42f893bd2cafe7d141--remote_cmds-63.tar.gz Error: Your Xcode does not support macOS 11.2. It is either outdated or was modified. Please update your Xcode or delete it if no updates are available. 将Xcode.app先移动到其他位置，然后在运行 brew install telnet，最后把Xcode.app移动回来\nsudo mv ./Applications/Xcode.app ~/Desktop brew install telnet sudo mv ~/Desktop/Xcode.app ./Applications ","permalink":"https://blog.z6z8.cn/2021/04/08/error-your-xcode-does-not-support-macos-11-2/","summary":"\u003cp\u003e使用brew安装telnet时，报错 \u003ccode\u003eError: Your Xcode does not support macOS 11.2. It is either outdated or was modified. Please update your Xcode or delete it if no updates are available.\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebrew install telnet\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eUpdating Homebrew\u003cspan style=\"color:#f92672\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWarning: You are using macOS \u003cspan style=\"color:#ae81ff\"\u003e11.2\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWe \u003cspan style=\"color:#66d9ef\"\u003edo\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003enot\u003c/span\u003e provide support \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e this pre\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003erelease version\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eYou will encounter build failures with some formulae\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePlease create pull requests instead of asking \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e help on Homebrew\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;s GitHub,\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTwitter \u003cspan style=\"color:#f92672\"\u003eor\u003c/span\u003e any other official channels\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e You are responsible \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e resolving\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eany issues you experience \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e you are running this\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epre\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003erelease version\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e==\u0026gt;\u003c/span\u003e Downloading https:\u003cspan style=\"color:#f92672\"\u003e//\u003c/span\u003eopensource\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eapple\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ecom\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003etarballs\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003elibtelnet\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003elibtelnet\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e13.\u003c/span\u003etar\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAlready downloaded: \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eUsers\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003ezxs\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ezl\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eLibrary\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eCaches\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eHomebrew\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003edownloads\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003efe26613ac3f91bd2fa2ed4e9ca39a043c6fd5960c4e0a3f063c672911900665\u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003elibtelnet\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e13.\u003c/span\u003etar\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003egz\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e==\u0026gt;\u003c/span\u003e Downloading https:\u003cspan style=\"color:#f92672\"\u003e//\u003c/span\u003eopensource\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eapple\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ecom\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003etarballs\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eremote_cmds\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eremote_cmds\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e63\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAlready downloaded: \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eUsers\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003ezxs\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ezl\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eLibrary\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eCaches\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eHomebrew\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003edownloads\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e557\u003c/span\u003ed5b69c452e48e5337f6d80e827514cd2218e1c02dcd42f893bd2cafe7d141\u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003eremote_cmds\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e63.\u003c/span\u003etar\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003egz\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eError: Your Xcode does \u003cspan style=\"color:#f92672\"\u003enot\u003c/span\u003e support macOS \u003cspan style=\"color:#ae81ff\"\u003e11.2\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eIt is either outdated \u003cspan style=\"color:#f92672\"\u003eor\u003c/span\u003e was modified\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePlease update your Xcode \u003cspan style=\"color:#f92672\"\u003eor\u003c/span\u003e delete it \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e no updates are available\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e将Xcode.app先移动到其他位置，然后在运行 \u003ccode\u003ebrew install telnet\u003c/code\u003e，最后把Xcode.app移动回来\u003c/p\u003e","title":"Error: Your Xcode does not support macOS 11.2."},{"content":"基本原理 Contents of (__DATA,__objc_classrefs) section 和 Contents of (__DATA,__objc_superrefs) section 中的类是已经被引用的类， Contents of (__DATA,__objc_classlist) section 中的类是整个应用未启动时已经定义好的类列表，那么从后者剔除前者而剩余的类就是应用未启动时没有使用的类；同时考虑到Objective-C的运行时特性，所以还需要人工确认下。\n基本过程如下：\n解压ipa包 本质是zip包，修改后缀解压就可以了\notool 符号格式化 在mac os shell中运行命令（otool 为Xcode工具包中的工具）\notool -arch armv7 -ov 应用解压后的目录/Payload/应用名/应用二进制文件 \u0026gt; otool.txt 上述命令中指定 armv7 架构，其假设是ipa包一定会有 armv7 的二进制文件\n解析获取 __objc_classlist 类列表 打开 otool.txt 文件，搜索 __objc_classlist ，找到一个class数据，其基本格式如下\n025afc00 0x28b2a24 # 第二个，地址0x28b2a24，是class的唯一地址 isa 0x28b2a38 superclass 0x28b4194 # 父类的地址 cache 0x0 __objc_empty_cache vtable 0x0 data 0x25b5e0c flags 0x194 RO_HAS_CXX_STRUCTORS instanceStart 4 instanceSize 20 ivarLayout 0x2123649 layout map 0x13 name 0x2123610 BCCallMultiVideoController #类名字 baseMethods 0x25b5a88 。。。 我们需要重点关注 类地址、 superclass 父类地址， name 类名，按照这样的格式解析所有的 __objc_classlist 从而获得所有定义好的类集合。\n搜索 __objc_classrefs 和 __objc_superrefs，其基本格式如下\n02896b94 0x0 _OBJC_CLASS_$_UIView 02896b98 0x0 _OBJC_CLASS_$_UIScrollView 02896b9c 0x0 _OBJC_CLASS_$_UIColor 02896ba0 0x0 _OBJC_CLASS_$_NSNumber 02896ba4 0x0 _OBJC_CLASS_$_UIImage 02896ba8 0x0 _OBJC_CLASS_$_NSMutableArray 02896bac 0x28b2a24 # 第二个地址，0x28b2a24，是引用的类 这样我们就获得了应用未启动时所有已经引用的类（从里面剔除系统类）\n然后，就是获取 __objc_classrefs、 __objc_superrefs 和 __objc_classlist 的差集，需要注意下因为继承而间接被引用的情况。例如 __objc_classrefs 集合中有一个 0x28b2a24,而这个地址在 __objc_classlist 中对应 BCCallMultiVideoController,所以 BCCallMultiVideoController 被引用了，而 BCCallMultiVideoController 的父类是 0x28b4194，那么类 0x28b4194 也被引用了，这样追溯直到父类未空或者父类未系统类。\n","permalink":"https://blog.z6z8.cn/2021/04/01/otool-%E5%B7%A5%E5%85%B7%E5%88%86%E6%9E%90%E5%8F%AF%E8%83%BD%E6%B2%A1%E6%9C%89%E4%BD%BF%E7%94%A8%E7%9A%84objective-c%E7%B1%BB/","summary":"\u003ch2 id=\"基本原理\"\u003e基本原理\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003eContents of (__DATA,__objc_classrefs) section\u003c/code\u003e 和 \u003ccode\u003eContents of (__DATA,__objc_superrefs) section\u003c/code\u003e 中的类是已经被引用的类， \u003ccode\u003eContents of (__DATA,__objc_classlist) section\u003c/code\u003e 中的类是整个应用未启动时已经定义好的类列表，那么从后者剔除前者而剩余的类就是应用未启动时没有使用的类；同时考虑到Objective-C的运行时特性，所以还需要人工确认下。\u003c/p\u003e\n\u003cp\u003e基本过程如下：\u003c/p\u003e\n\u003ch2 id=\"解压ipa包\"\u003e解压ipa包\u003c/h2\u003e\n\u003cp\u003e本质是zip包，修改后缀解压就可以了\u003c/p\u003e\n\u003ch2 id=\"otool-符号格式化\"\u003eotool 符号格式化\u003c/h2\u003e\n\u003cp\u003e在mac os shell中运行命令（otool 为Xcode工具包中的工具）\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eotool  -arch armv7 -ov  应用解压后的目录/Payload/应用名/应用二进制文件  \u0026gt;  otool.txt\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e上述命令中指定 \u003ccode\u003earmv7\u003c/code\u003e 架构，其假设是ipa包一定会有 \u003ccode\u003earmv7\u003c/code\u003e 的二进制文件\u003c/p\u003e\n\u003ch2 id=\"解析获取-__objc_classlist-类列表\"\u003e解析获取 __objc_classlist 类列表\u003c/h2\u003e\n\u003cp\u003e打开 \u003ccode\u003eotool.txt\u003c/code\u003e 文件，搜索 \u003ccode\u003e__objc_classlist\u003c/code\u003e ，找到一个class数据，其基本格式如下\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#ae81ff\"\u003e025\u003c/span\u003eafc00 \u003cspan style=\"color:#ae81ff\"\u003e0x28b2a24\u003c/span\u003e     \u003cspan style=\"color:#75715e\"\u003e# 第二个，地址0x28b2a24，是class的唯一地址\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    isa        \u003cspan style=\"color:#ae81ff\"\u003e0x28b2a38\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    superclass \u003cspan style=\"color:#ae81ff\"\u003e0x28b4194\u003c/span\u003e  \u003cspan style=\"color:#75715e\"\u003e# 父类的地址\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    cache      \u003cspan style=\"color:#ae81ff\"\u003e0x0\u003c/span\u003e __objc_empty_cache\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    vtable     \u003cspan style=\"color:#ae81ff\"\u003e0x0\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    data       \u003cspan style=\"color:#ae81ff\"\u003e0x25b5e0c\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        flags          \u003cspan style=\"color:#ae81ff\"\u003e0x194\u003c/span\u003e RO_HAS_CXX_STRUCTORS\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        instanceStart  \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        instanceSize   \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ivarLayout     \u003cspan style=\"color:#ae81ff\"\u003e0x2123649\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout map     \u003cspan style=\"color:#ae81ff\"\u003e0x13\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        name           \u003cspan style=\"color:#ae81ff\"\u003e0x2123610\u003c/span\u003e BCCallMultiVideoController  \u003cspan style=\"color:#75715e\"\u003e#类名字\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        baseMethods    \u003cspan style=\"color:#ae81ff\"\u003e0x25b5a88\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e。。。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e我们需要重点关注 \u003ccode\u003e类地址\u003c/code\u003e、 \u003ccode\u003esuperclass 父类地址\u003c/code\u003e， \u003ccode\u003ename 类名\u003c/code\u003e，按照这样的格式解析所有的 \u003ccode\u003e__objc_classlist\u003c/code\u003e 从而获得所有定义好的类集合。\u003c/p\u003e","title":"otool 工具分析可能没有使用的Objective-C类"},{"content":"当在 podfile 文件中使用 use_frameworks! 指令时，CocoaPod在安装Pod时，会用framework方式组织资源（默认使用lib方式），同时该指令还提供扩展选项，指定动态framework或者静态framework\nuse_frameworks! #使用默认值，根据pod类型自行设置static或者dynamic use_frameworks! :linkage =\u0026gt; :static # 使用静态链接 use_frameworks! :linkage =\u0026gt; :dynamic #使用动态链接 如果在 podfile 中设置 use_frameworks! ，又没有指定 linkage =\u0026gt; :static 或 linkage =\u0026gt; :dynamic 时，则会根据 podspec 文件中的根配置 static_framework = true/false 来设置。\n另外， linkage =\u0026gt; :static 或 linkage =\u0026gt; :dynamic 只对源码Pod有效，对已经是framework的pod不起作用。而且，如果pod中的framework是动态库，那么在 pod install 后，会在相应的target的 Build Phases 设置中添加 [cp] Embed Pods Frameworks 脚本，以动态库的方式将framework输出到最终产物中。\n","permalink":"https://blog.z6z8.cn/2021/03/29/cocoapod-%E6%8C%87%E5%AE%9A%E5%8A%A8%E6%80%81%E6%88%96%E8%80%85%E9%9D%99%E6%80%81%E9%93%BE%E6%8E%A5framework/","summary":"\u003cp\u003e当在 \u003ccode\u003epodfile\u003c/code\u003e 文件中使用 \u003ccode\u003euse_frameworks!\u003c/code\u003e 指令时，CocoaPod在安装Pod时，会用framework方式组织资源（默认使用lib方式），同时该指令还提供扩展选项，指定动态framework或者静态framework\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003euse_frameworks!  #使用默认值，根据pod类型自行设置static或者dynamic\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003euse_frameworks! :linkage =\u0026gt; :static # 使用静态链接\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003euse_frameworks! :linkage =\u0026gt; :dynamic #使用动态链接\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e如果在 \u003ccode\u003epodfile\u003c/code\u003e 中设置 \u003ccode\u003euse_frameworks! \u003c/code\u003e，又没有指定 \u003ccode\u003elinkage =\u0026gt; :static\u003c/code\u003e 或 \u003ccode\u003elinkage =\u0026gt; :dynamic\u003c/code\u003e 时，则会根据 \u003ccode\u003epodspec\u003c/code\u003e 文件中的根配置 \u003ccode\u003estatic_framework = true/false\u003c/code\u003e 来设置。\u003c/p\u003e\n\u003cp\u003e另外， \u003ccode\u003elinkage =\u0026gt; :static\u003c/code\u003e 或 \u003ccode\u003elinkage =\u0026gt; :dynamic\u003c/code\u003e 只对源码Pod有效，对已经是framework的pod不起作用。而且，如果pod中的framework是动态库，那么在 \u003ccode\u003epod install\u003c/code\u003e 后，会在相应的target的 \u003ccode\u003eBuild Phases\u003c/code\u003e 设置中添加 \u003ccode\u003e[cp] Embed Pods Frameworks\u003c/code\u003e 脚本，以动态库的方式将framework输出到最终产物中。\u003c/p\u003e","title":"CocoaPod 指定动态或者静态链接framework"},{"content":"framework是一种头文件和链接库的组织形式，可以通过file命令查看相关信息来判断该链接库是动态库还是静态库，如果输出信息中含有 dynamically linked，则是动态库\nfile ~/ZipArchive.framework/ZipArchive ~/ZipArchive.framework/ZipArchive: Mach-O universal binary with 3 architectures: [arm_v7:Mach-O dynamically linked shared library arm_v7] [x86_64:Mach-O 64-bit dynamically linked shared library x86_64] [arm64:Mach-O 64-bit dynamically linked shared library arm64] ~/ZipArchive.framework/ZipArchive (for architecture armv7): Mach-O dynamically linked shared library arm_v7 ~/ZipArchive.framework/ZipArchive (for architecture x86_64): Mach-O 64-bit dynamically linked shared library x86_64 ~/ZipArchive.framework/ZipArchive (for architecture arm64): Mach-O 64-bit dynamically linked shared library arm64 ","permalink":"https://blog.z6z8.cn/2021/03/29/ios-%E5%88%A4%E6%96%ADframework%E6%98%AF%E5%8A%A8%E6%80%81%E5%BA%93%E8%BF%98%E6%98%AF%E9%9D%99%E6%80%81%E5%BA%93/","summary":"\u003cp\u003eframework是一种头文件和链接库的组织形式，可以通过file命令查看相关信息来判断该链接库是动态库还是静态库，如果输出信息中含有 \u003ccode\u003edynamically linked\u003c/code\u003e，则是动态库\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-sh\" data-lang=\"sh\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efile  ~/ZipArchive.framework/ZipArchive\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/ZipArchive.framework/ZipArchive: Mach-O universal binary with \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e architectures: \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003earm_v7:Mach-O dynamically linked shared library arm_v7\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ex86_64:Mach-O 64-bit dynamically linked shared library x86_64\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003earm64:Mach-O 64-bit dynamically linked shared library arm64\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/ZipArchive.framework/ZipArchive \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e architecture armv7\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: Mach-O dynamically linked shared library arm_v7\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/ZipArchive.framework/ZipArchive \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e architecture x86_64\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e:    Mach-O 64-bit dynamically linked shared library x86_64\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e~/ZipArchive.framework/ZipArchive \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e architecture arm64\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: Mach-O 64-bit dynamically linked shared library arm64\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"ios 判断framework是动态库还是静态库"},{"content":"com.android.tools.build:gradle:3.4.0 3.4.0以后，默认使用R8编译。\n可以在 gradle.properties 添加属性，指定R8是否启用\nandroid.enableR8=true ；// true 启用R8 有时候上述配置并不一定生效，在编译时有可能还是使用 Proguard，这时候可以在App 的 build.gradle 中配置 useProguard false，强制关闭Proguard而启用R8\nandroid { buildTypes { release { minifyEnabled true useProguard false //强制关闭Proguard而启用R8，这时将忽略gradle.properties里关于android.enableR8的设置 } } } ","permalink":"https://blog.z6z8.cn/2021/03/22/android-gradle-build-%E7%94%A8r8%E8%80%8C%E4%B8%8D%E4%BD%BF%E7%94%A8proguard/","summary":"\u003cp\u003e\u003ccode\u003ecom.android.tools.build:gradle:3.4.0\u003c/code\u003e 3.4.0以后，默认使用R8编译。\u003c/p\u003e\n\u003cp\u003e可以在 \u003ccode\u003egradle.properties\u003c/code\u003e 添加属性，指定R8是否启用\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eandroid.enableR8=true ；// true 启用R8\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e有时候上述配置并不一定生效，在编译时有可能还是使用 \u003ccode\u003eProguard\u003c/code\u003e，这时候可以在App 的 \u003ccode\u003ebuild.gradle\u003c/code\u003e 中配置 \u003ccode\u003euseProguard false\u003c/code\u003e，强制关闭Proguard而启用R8\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eandroid {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    buildTypes {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        release {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            minifyEnabled true\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            useProguard false  //强制关闭Proguard而启用R8，这时将忽略gradle.properties里关于android.enableR8的设置\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Android gradle build 用R8而不使用Proguard"},{"content":"原因是引入的CocoaPod仓库，编译后缺少 module.modulemap 文件；通常是因为私有CocoaPod仓库只有声明文件，没有定义实现文件\u0026mdash;\u0026ndash;只有 .h 文件，没有 .m .mm 等文件。 简单的解决办法是在私有仓库添加一个空的 .m 文件，例如添加 cocoapod.m 文件(名字随意)\n/// cocoapod.m #import 然后在 podspec 文件中，将这个文件添加到 source_files 属性里\ns.public_header_files = \u0026#39;公开的头文件\u0026#39; s.source_files = \u0026#39;已有的源文件\u0026#39;,\u0026#39;cocoapod.m\u0026#39; #也可使用通配符写法 ，如 **/*.{h,m} 再次 pod install 即可生成 module.modulemap 文件\n","permalink":"https://blog.z6z8.cn/2021/01/27/%E5%BC%95%E5%85%A5%E7%A7%81%E6%9C%89cocoapod%E7%BC%96%E8%AF%91%E6%8A%A5%E9%94%99include-of-non-modular-header-inside-framework-module/","summary":"\u003cp\u003e原因是引入的CocoaPod仓库，编译后缺少 \u003ccode\u003emodule.modulemap\u003c/code\u003e 文件；通常是因为私有CocoaPod仓库只有声明文件，没有定义实现文件\u0026mdash;\u0026ndash;只有 \u003ccode\u003e.h \u003c/code\u003e 文件，没有 \u003ccode\u003e.m\u003c/code\u003e \u003ccode\u003e.mm\u003c/code\u003e 等文件。\n简单的解决办法是在私有仓库添加一个空的 \u003ccode\u003e.m\u003c/code\u003e 文件，例如添加 \u003ccode\u003ecocoapod.m\u003c/code\u003e 文件(名字随意)\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e/// cocoapod.m\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e#import\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e然后在 \u003ccode\u003epodspec\u003c/code\u003e 文件中，将这个文件添加到 \u003ccode\u003esource_files\u003c/code\u003e 属性里\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-ruby\" data-lang=\"ruby\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003es\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epublic_header_files \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;公开的头文件\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003es\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esource_files \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;已有的源文件\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;cocoapod.m\u0026#39;\u003c/span\u003e   \u003cspan style=\"color:#75715e\"\u003e#也可使用通配符写法 ，如 **/*.{h,m}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e再次 \u003ccode\u003epod install\u003c/code\u003e 即可生成 \u003ccode\u003emodule.modulemap\u003c/code\u003e 文件\u003c/p\u003e","title":"引入私有CocoaPod编译报错include of non-modular header inside framework module"},{"content":"VSCode 打开本地目录或工作空间 命令ID vscode.openFolder ,打开一个目录或者工作空间。可以在当前窗口打开，或者新建窗口打开。 参数\nuri ，Uri类型，可选，目录（工作空间）路径。如果不提供，那么将会弹出一个原生的目录选择对话框 newWindow，可选，是否打开一个新的窗口 // 在新窗口打开/some/path/to/folder let uri = vscode.Uri.file(\u0026#34;/some/path/to/folder\u0026#34;); vscode.commands.executeCommand(\u0026#34;vscode.openFolder\u0026#34;,uri,true); 当前活动的Terminal（Shell终端） 内置方法 vscode.window.activeTerminal\n创建Terminal（Shell终端） 使用内置方法 vscode.window.createTerminal，它有三个重载函数, 返回值均为 vscode.Terminal\ncreateTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): Terminal 参数解释name可选 ，终端创建后显示在UI上的名字shellPath可选，自定义shell终端的执行路径shellArgs可选 ，传递给自定义终端的执行参数。\n只对Windows生效\nshellArgs 详细格式参见https://msdn.microsoft.com/en-au/08dfcab2-eb6e-49a4-80eb-87d4076c98c6\ncreateTerminal(options: TerminalOptions): Terminal 参数解释options必选 ，TerminalOptions配置参数\nTerminalOptions 可用的值\n参数解释占位占位占位占位占位占位占位占位占位占位占位占位占位cwd可选 ，string 或 Uri ，终端的工作目录env可选 ，object ，添加到终端中的环境变量hideFromUser可选 ，boolean ，如果设置为true，终端将正常运行，但直到调用Terminal.show时，才会对用户公开。 通常的用法是在需要运行可能需要交互性，但只想在需要交互时对用户公开name可选 ，string ，终端创建后显示在UI上的名字shellArgs可选 ， string[] 或 string ，传递给自定义终端的执行参数\n只对Windows生效shellPath可选 ， string ，自定义shell终端的执行路径strictEnv可选 ， boolean ，终端环境是否应完全与TerminalOptions.env中提供的一致。 如果为false（默认），则环境将基于窗口的环境，并且还会在顶部应用配置的平台设置，例如terminal.integrated.windows.env。 如果true，则必须提供完整的环境。\ncreateTerminal(options: ExtensionTerminalOptions): Terminal 此方法将创建一个由插件（扩展）控制输入输出的终端环境 参数解释options必选 ，ExtensionTerminalOptions配置参数\nExtensionTerminalOptions 可用的值\n参数解释name必选 ，string ，终端创建后显示在UI上的名字pty必选 ， Pseudoterminal 配置参数\nPseudoterminal 可用的值\n参数解释name必选 ，string ，终端创建后显示在UI上的名字pty必选 ， Pseudoterminal 配置参数\nPseudoterminal 参见https://code.visualstudio.com/api/references/vscode-api#Pseudoterminal\n参考 https://code.visualstudio.com/api/references/commands https://code.visualstudio.com/api/references/vscode-api\n","permalink":"https://blog.z6z8.cn/2021/01/07/vscode%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91-%E6%89%93%E5%BC%80%E6%9C%AC%E5%9C%B0%E7%9B%AE%E5%BD%95%EF%BC%88openfolder%EF%BC%89/","summary":"\u003ch1 id=\"vscode\"\u003eVSCode\u003c/h1\u003e\n\u003ch2 id=\"打开本地目录或工作空间\"\u003e打开本地目录或工作空间\u003c/h2\u003e\n\u003cp\u003e命令ID \u003ccode\u003evscode.openFolder\u003c/code\u003e ,打开一个目录或者工作空间。可以在当前窗口打开，或者新建窗口打开。\n参数\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\u003ccode\u003euri\u003c/code\u003e ，Uri类型，可选，目录（工作空间）路径。如果不提供，那么将会弹出一个原生的目录选择对话框\u003c/li\u003e\n\u003cli\u003e\u003ccode\u003enewWindow\u003c/code\u003e，可选，是否打开一个新的窗口\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 在新窗口打开/some/path/to/folder\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003euri\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evscode\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eUri\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003efile\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/some/path/to/folder\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003evscode\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ecommands\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eexecuteCommand\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;vscode.openFolder\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003euri\u003c/span\u003e,\u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"当前活动的terminalshell终端\"\u003e当前活动的Terminal（Shell终端）\u003c/h2\u003e\n\u003cp\u003e内置方法 \u003ccode\u003evscode.window.activeTerminal\u003c/code\u003e\u003c/p\u003e\n\u003ch2 id=\"创建terminalshell终端\"\u003e创建Terminal（Shell终端）\u003c/h2\u003e\n\u003cp\u003e使用内置方法 \u003ccode\u003evscode.window.createTerminal\u003c/code\u003e，它有三个重载函数, 返回值均为 \u003ccode\u003evscode.Terminal\u003c/code\u003e\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ecreateTerminal(name?: string, shellPath?: string, shellArgs?: string[] | string): Terminal\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e参数解释name可选 ，终端创建后显示在UI上的名字shellPath可选，自定义shell终端的执行路径shellArgs可选 ，传递给自定义终端的执行参数。\u003cbr\u003e\n只对Windows生效\u003c/p\u003e\n\u003cp\u003eshellArgs 详细格式参见https://msdn.microsoft.com/en-au/08dfcab2-eb6e-49a4-80eb-87d4076c98c6\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ecreateTerminal(options: TerminalOptions): Terminal\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e参数解释options必选 ，TerminalOptions配置参数\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eTerminalOptions\u003c/code\u003e 可用的值\u003c/p\u003e\n\u003cp\u003e参数解释占位占位占位占位占位占位占位占位占位占位占位占位占位cwd可选 ，string 或 Uri ，终端的工作目录env可选 ，object ，添加到终端中的环境变量hideFromUser可选 ，boolean ，如果设置为true，终端将正常运行，但直到调用Terminal.show时，才会对用户公开。 通常的用法是在需要运行可能需要交互性，但只想在需要交互时对用户公开name可选 ，string ，终端创建后显示在UI上的名字shellArgs可选 ， string[] 或 string ，传递给自定义终端的执行参数\u003cbr\u003e\n只对Windows生效shellPath可选 ， string ，自定义shell终端的执行路径strictEnv可选 ， boolean ，终端环境是否应完全与TerminalOptions.env中提供的一致。 如果为false（默认），则环境将基于窗口的环境，并且还会在顶部应用配置的平台设置，例如terminal.integrated.windows.env。 如果true，则必须提供完整的环境。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ecreateTerminal(options: ExtensionTerminalOptions): Terminal\n此方法将创建一个由插件（扩展）控制输入输出的终端环境\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e参数解释options必选 ，ExtensionTerminalOptions配置参数\u003c/p\u003e","title":"VSCode插件开发--一些API"},{"content":"先看一张图 在VSCode的文档中，侧边栏按钮入口称之为 Tree View Container，侧边栏面板称之为 Tree View，本文涉及的就是这两个区域。\n创建工程 使用 yo code 脚手架创建一个插件工程，语言选择 TypeScript。具体过程略\n配置侧边栏按钮(Tree View Container)和面板视图(Tree View) 侧边栏按钮(Tree View Container)和面板视图(Tree View)要同时配置，否则不生效。\n打开 package.json，添加以下内容\n\u0026#34;contributes\u0026#34;: { \u0026#34;viewsContainers\u0026#34;: { \u0026#34;activitybar\u0026#34;: [ { \u0026#34;id\u0026#34;:\u0026#34;sidebar_test\u0026#34;, \u0026#34;title\u0026#34;: \u0026#34;侧边栏测试\u0026#34;, \u0026#34;icon\u0026#34;: \u0026#34;入口.svg\u0026#34; } ] }, \u0026#34;views\u0026#34;: { \u0026#34;sidebar_test\u0026#34;:[ { \u0026#34;id\u0026#34;:\u0026#34;sidebar_test_id1\u0026#34;, \u0026#34;name\u0026#34;:\u0026#34;面板区块名称1\u0026#34; }, { \u0026#34;id\u0026#34;:\u0026#34;sidebar_test_id2\u0026#34;, \u0026#34;name\u0026#34;:\u0026#34;面板区块名称2\u0026#34; } ] } } 按钮图片格式，需要使用svg格式。views中key要和activitybar中的属性id保持一致，如sidebar_test在两者中是一致的。\n以上配置了一个 sidebar_test 的侧边栏按钮，点击按钮，会出现 面板区块名称1 和 面板区块名称2 两个区块。\n定义面板内容 以上仅仅是将面板入口添加上了，若添加内容与命令，则需要 registerTreeDataProvider、 TreeDataProvider、 TreeItem 用于内容管理，以及 registerCommand 注册命令\n新建脚本 test.ts,内容如下\nimport * as vscode from \u0026#39;vscode\u0026#39;; // 树节点 export class EntryItem extends vscode.TreeItem { } //树的内容组织管理 export class EntryList implements vscode.TreeDataProvider\u0026lt;EntryItem\u0026gt; { onDidChangeTreeData?: vscode.Event\u0026lt;void | EntryItem | null | undefined\u0026gt; | undefined; getTreeItem(element: EntryItem): vscode.TreeItem | Thenable\u0026lt;vscode.TreeItem\u0026gt; { return element; } getChildren(element?: EntryItem): vscode.ProviderResult\u0026lt;EntryItem[]\u0026gt; { if (element) {//子节点 var childs = []; for (let index = 0; index \u0026lt; 3; index++) { let str = index.toString(); var item = new EntryItem(str,vscode.TreeItemCollapsibleState.None); item.command = {command:\u0026#34;sidebar_test_id1.openChild\u0026#34;, //命令id title:\u0026#34;标题\u0026#34;, arguments:[str] //命令接收的参数 }; childs[index] = item; } return childs; } else { //根节点 return [new EntryItem(\u0026#34;root\u0026#34;,vscode.TreeItemCollapsibleState.Collapsed)]; } } } 然后在 extension.ts 中添加内容\nimport * as vscode from \u0026#39;vscode\u0026#39;; import * as sidebar from \u0026#39;./test\u0026#39;; /// 插件激活时 export function activate(context: vscode.ExtensionContext) { //注册侧边栏面板的实现 const sidebar_test = new sidebar.EntryList(); vscode.window.registerTreeDataProvider(\u0026#34;sidebar_test_id1\u0026#34;,sidebar_test); //注册命令 vscode.commands.registerCommand(\u0026#34;sidebar_test_id1.openChild\u0026#34;,args =\u0026gt; { vscode.window.showInformationMessage(args); }); //// 其他内容保持不变 } 最后，在 package.json，添加面板区块的展示事件，以驱动内容变化\n\u0026#34;activationEvents\u0026#34;: [ \u0026#34;onView:sidebar_test_id1\u0026#34; ], \u0026#34;contributes\u0026#34;: { } 运行结果如下 参考地址 https://code.visualstudio.com/docs/extensionAPI/vscode-api\n","permalink":"https://blog.z6z8.cn/2020/12/15/vscode%E6%8F%92%E4%BB%B6%E5%BC%80%E5%8F%91-%E6%B7%BB%E5%8A%A0%E4%BE%A7%E8%BE%B9%E6%A0%8F%E5%85%A5%E5%8F%A3%E5%92%8C%E9%9D%A2%E6%9D%BF/","summary":"\u003cp\u003e先看一张图\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2020/12/workbench-contribution.png\"\u003e\n在VSCode的文档中，侧边栏按钮入口称之为 \u003ccode\u003eTree View Container\u003c/code\u003e，侧边栏面板称之为 \u003ccode\u003eTree View\u003c/code\u003e，本文涉及的就是这两个区域。\u003c/p\u003e\n\u003ch2 id=\"创建工程\"\u003e创建工程\u003c/h2\u003e\n\u003cp\u003e使用 \u003ccode\u003eyo code\u003c/code\u003e 脚手架创建一个插件工程，语言选择 \u003ccode\u003eTypeScript\u003c/code\u003e。具体过程略\u003c/p\u003e\n\u003ch2 id=\"配置侧边栏按钮tree-view-container和面板视图tree-view\"\u003e配置侧边栏按钮(Tree View Container)和面板视图(Tree View)\u003c/h2\u003e\n\u003cp\u003e侧边栏按钮(Tree View Container)和面板视图(Tree View)要同时配置，否则不生效。\u003c/p\u003e\n\u003cp\u003e打开 \u003ccode\u003epackage.json\u003c/code\u003e，添加以下内容\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;contributes\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;viewsContainers\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;activitybar\u0026#34;\u003c/span\u003e: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e:\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;sidebar_test\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;title\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;侧边栏测试\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;icon\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;入口.svg\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;views\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026#34;sidebar_test\u0026#34;\u003c/span\u003e:[\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e:\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;sidebar_test_id1\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;name\u0026#34;\u003c/span\u003e:\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;面板区块名称1\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;id\u0026#34;\u003c/span\u003e:\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;sidebar_test_id2\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;name\u0026#34;\u003c/span\u003e:\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;面板区块名称2\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cblockquote\u003e\n\u003cp\u003e按钮图片格式，需要使用svg格式。views中key要和activitybar中的属性id保持一致，如sidebar_test在两者中是一致的。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e以上配置了一个 \u003ccode\u003esidebar_test\u003c/code\u003e 的侧边栏按钮，点击按钮，会出现 \u003ccode\u003e面板区块名称1\u003c/code\u003e 和 \u003ccode\u003e面板区块名称2\u003c/code\u003e 两个区块。\u003c/p\u003e","title":"VSCode插件开发--添加侧边栏入口和面板"},{"content":"方法 [[UIBarButtonItem alloc] initWithCustomView:view] 在iOS 高版上如（iOS11，12，13，14），可以自动调整view的大小 在iOS底版本上如（iOS10，9），则采用view自身的大小。\n也就是说，如果view的frame不指定，有可能在导航栏上不可见。\n例如\n// sendButton 默认大小为0 UIButton *sendButton = [UIButton buttonWithType:UIButtonTypeCustom]; [sendButton setBackgroundImage:背景图 forState:UIControlStateDisabled]; // 实测在iOS9.3上，sendButton不显示 self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:sendButton]; ","permalink":"https://blog.z6z8.cn/2020/12/04/ios-uibarbuttonitem-initwithcustomview-%E5%AF%BC%E8%88%AA%E6%8C%89%E9%92%AE%E5%9C%A8%E4%B8%8D%E5%90%8C%E7%89%88%E6%9C%AC%E7%9A%84%E8%A1%A8%E7%8E%B0%E4%B8%8D%E4%B8%80%E8%87%B4/","summary":"\u003cp\u003e方法 \u003ccode\u003e[[UIBarButtonItem alloc] initWithCustomView:view]\u003c/code\u003e\n在iOS 高版上如（iOS11，12，13，14），可以自动调整view的大小\n在iOS底版本上如（iOS10，9），则采用view自身的大小。\u003c/p\u003e\n\u003cp\u003e也就是说，如果view的frame不指定，有可能在导航栏上不可见。\u003c/p\u003e\n\u003cp\u003e例如\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// sendButton 默认大小为0\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        UIButton \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003esendButton \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [UIButton buttonWithType:UIButtonTypeCustom];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        [sendButton setBackgroundImage:\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e背景图\u003c/span\u003e forState:UIControlStateDisabled];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 实测在iOS9.3上，sendButton不显示\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        self.navigationItem.rightBarButtonItem \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[UIBarButtonItem alloc] initWithCustomView:sendButton];\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"iOS UIBarButtonItem.initWithCustomView 导航按钮在不同版本的表现不一致"},{"content":"生成 ssh key $ ssh-keygen -t rsa -C \u0026#34;git服务端留存的邮箱地址\u0026#34; Generating public/private rsa key pair. Enter file in which to save the key (~/.ssh/id_rsa): \u0026#34;这里输入ssh key保存路径，不建议使用默认地址\u0026#34; Enter passphrase (empty for no passphrase): \u0026#34;这里输入密码，建议输入空（方便后续配置）\u0026#34; Enter same passphrase again: \u0026#34;再输入一遍密码,建议输入空（方便后续配置）\u0026#34; 应生成两个文件，公钥和私钥，文件名形式为 xxx(私钥)， xxx_pub 或者 xxx.pub(公钥)。记住ssh key生成的文件路径。\n默认情况下，ssh会使用 ~/.ssh/id_rsa 这个私钥，但无法处理访问多个ssh远端的场景。\n配置本地ssh访问git使用的私钥 打开 ~/.ssh/config 文件，如果没有则创建一个文本文件，添加如下内容\n# 请保证 Host 和 HostName 的值相同 （macos11 实测不相同时，git ssh 访问失败） # 远端ssh主机别名 Host bitbucket.cmbc.com.cn # 远端ssh主机名（域名或者ip都可以） HostName bitbucket.cmbc.com.cn # 鉴权文件 ，这填写ssh私钥文件路径 IdentityFile \u0026#34;ssh 私钥文件路径\u0026#34; # 使用公钥算法进行鉴权 PreferredAuthentications publickey 关于 ssh config 更多细节参考 https://linux.die.net/man/5/ssh_config\n配置git上的鉴权公钥 不同的git服务方式不一样，以bitbucket为例： 登录bitbucket，依次点击头像 -\u0026gt; Manage account -\u0026gt; SSH keys -\u0026gt; Add key ，\n将ssh 公钥文件内容复制到在输入框中，然后 保存(点击 \u0026ldquo;Add key\u0026rdquo; 按钮)\nssh 公钥形式通常是ssh-rsa + base64编码的公钥 + 邮箱地址\n配置本地已有git仓库的访问协议 # 查询远程仓库地址 git remote -v # 添加ssh协议 地址需要访问网页版的bitbucket仓库获取 git remote set-url --add origin ssh://git@bitbucket.cmbc.com.cn:7999/xxx/xxx.git # 删除http协议 地址由git remote -v获得 git remote set-url --delete origin http://usernamge@bitbucket.cmbc.com.cn:7999/scm/xxx/xxx.git ","permalink":"https://blog.z6z8.cn/2020/11/27/macos-%E9%85%8D%E7%BD%AE-git-ssh%E8%AE%BF%E9%97%AE%E6%96%B9%E5%BC%8F/","summary":"\u003ch2 id=\"生成-ssh-key\"\u003e生成 ssh key\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ ssh-keygen -t rsa -C \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;git服务端留存的邮箱地址\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eGenerating public/private rsa key pair.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eEnter file in which to save the key \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003e~/.ssh/id_rsa\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;这里输入ssh key保存路径，不建议使用默认地址\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eEnter passphrase \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eempty \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e no passphrase\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;这里输入密码，建议输入空（方便后续配置）\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eEnter same passphrase again: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;再输入一遍密码,建议输入空（方便后续配置）\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e应生成两个文件，公钥和私钥，文件名形式为 \u003ccode\u003exxx\u003c/code\u003e(私钥)， \u003ccode\u003exxx_pub\u003c/code\u003e 或者 \u003ccode\u003exxx.pub\u003c/code\u003e(公钥)。记住ssh key生成的文件路径。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e默认情况下，ssh会使用 \u003ccode\u003e~/.ssh/id_rsa\u003c/code\u003e 这个私钥，但无法处理访问多个ssh远端的场景。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch2 id=\"配置本地ssh访问git使用的私钥\"\u003e配置本地ssh访问git使用的私钥\u003c/h2\u003e\n\u003cp\u003e打开 \u003ccode\u003e~/.ssh/config\u003c/code\u003e 文件，如果没有则创建一个文本文件，添加如下内容\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 请保证 Host 和 HostName 的值相同 （macos11 实测不相同时，git ssh 访问失败）\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 远端ssh主机别名\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eHost bitbucket.cmbc.com.cn\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e# 远端ssh主机名（域名或者ip都可以）\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    HostName bitbucket.cmbc.com.cn\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e# 鉴权文件 ，这填写ssh私钥文件路径\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    IdentityFile \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ssh 私钥文件路径\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e# 使用公钥算法进行鉴权\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    PreferredAuthentications publickey\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e关于 ssh config 更多细节参考 \u003ca href=\"https://linux.die.net/man/5/ssh_config\"\u003ehttps://linux.die.net/man/5/ssh_config\u003c/a\u003e\u003c/p\u003e","title":"macos 配置 git ssh访问方式"},{"content":"苹果app的进程是否运行在转译模式（Rosetta translation），通过调用 sysctlbyname 函数，传入 sysctl.proc_translated 标识来判断\n/// 返回 1 表示在Rosetta translation模式 ；返回 0 表示在Native Code模式；返回 -1，表示发生错误 int processIsTranslated() { int ret = 0; size_t size = sizeof(ret); if (sysctlbyname(\u0026#34;sysctl.proc_translated\u0026#34;, \u0026amp;ret, \u0026amp;size, NULL, 0) == -1) { if (errno == ENOENT) return 0; return -1; } return ret; } 参考地址https://developer.apple.com/documentation/apple_silicon/about_the_rosetta_translation_environment#3616845\n","permalink":"https://blog.z6z8.cn/2020/11/20/%E5%88%A4%E6%96%AD%E8%8B%B9%E6%9E%9Capp%E6%98%AF%E5%90%A6%E4%BB%A5%E8%BD%AC%E8%AF%91%E6%A8%A1%E5%BC%8F%E8%BF%90%E8%A1%8C%EF%BC%88rosetta-translation%EF%BC%89/","summary":"\u003cp\u003e苹果app的进程是否运行在转译模式（Rosetta translation），通过调用 \u003ccode\u003esysctlbyname\u003c/code\u003e 函数，传入 \u003ccode\u003esysctl.proc_translated\u003c/code\u003e 标识来判断\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e/// 返回 1 表示在Rosetta translation模式 ；返回 0 表示在Native Code模式；返回 -1，表示发生错误\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocessIsTranslated\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e ret \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#66d9ef\"\u003esize_t\u003c/span\u003e size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(ret);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003esysctlbyname\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;sysctl.proc_translated\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eret, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003esize, NULL, \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (errno \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e ENOENT)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ret;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e参考地址https://developer.apple.com/documentation/apple_silicon/about_the_rosetta_translation_environment#3616845\u003c/p\u003e","title":"判断苹果app是否以转译模式运行（Rosetta translation）"},{"content":"除非只支持单个屏幕方向，否侧shouldAutorotate，viewWillTransitionToSize等方法应被调用。\n不被调用的原因，可能是配置文件错误（info.plist），也可能是被Appdelegate或父ViewController拦截了。\n1、info.plist配置错误\nIPad 上的相关旋转方法都不执行，可能是info中的Supported interface orientations (iPad)项与General-\u0026gt;Deployment Info下的Device Orientation配置不一致导致的。\n删除不一致项应可以解决问题。\n2、被Appdelegate或父ViewController拦截\n有点类似触摸事件传递，屏幕旋转也是一层一层的询问。\nAppdelegate ---\u0026gt; UIWindow.rootViewController ----\u0026gt; rootViewController的子ViewController\n父子ViewController的概念，可以参考 UIViewController.addChildViewController 相关方法。\n具体来说 Appdelegate关于旋转的方法\n- (UIInterfaceOrientationMask)supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window; - (UIInterfaceOrientationMask)application:(UIApplication *)application supportedInterfaceOrientationsForWindow:(nullable UIWindow *)window; rootViewController关于旋转的方法\n# rootViewController 是UINavigationController -(UIInterfaceOrientationMask)navigationControllerSupportedInterfaceOrientations:(UINavigationController *)navigationController; - (BOOL)shouldAutorotate; 子ViewController\n- (BOOL) shouldAutorotate; -(UIInterfaceOrientationMask)supportedInterfaceOrientations; - (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration; - (void)didRotateFromInterfaceOrientation:(UIInterfaceOrientation)fromInterfaceOrientation; - (void)viewWillTransitionToSize:(CGSize)size withTransitionCoordinator:(id \u0026lt;UIViewControllerTransitionCoordinator\u0026gt;)coordinator; 参考 https://www.jianshu.com/p/b1ebaad87a80 参考https://www.jianshu.com/p/7c1d214adcbd 参考https://www.jianshu.com/p/73be6d0e152f\n","permalink":"https://blog.z6z8.cn/2020/11/05/ios-shouldautorotate-supportedinterfaceorientations-viewwilltransitiontosize%E4%B8%8D%E8%B0%83%E7%94%A8%E9%97%AE%E9%A2%98/","summary":"\u003cp\u003e除非只支持单个屏幕方向，否侧shouldAutorotate，viewWillTransitionToSize等方法应被调用。\u003c/p\u003e\n\u003cp\u003e不被调用的原因，可能是配置文件错误（info.plist），也可能是被Appdelegate或父ViewController拦截了。\u003c/p\u003e\n\u003cp\u003e1、info.plist配置错误\u003c/p\u003e\n\u003cp\u003eIPad 上的相关旋转方法都不执行，可能是info中的Supported interface orientations (iPad)项与General-\u0026gt;Deployment Info下的Device Orientation配置不一致导致的。\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"http://139.155.43.7/wp-content/uploads/2020/11/%E6%88%AA%E5%B1%8F2020-11-05-%E4%B8%8B%E5%8D%887.43.28-300x47.png\"\u003e\u003c/p\u003e\n\u003cp\u003e删除不一致项应可以解决问题。\u003c/p\u003e\n\u003cp\u003e2、被Appdelegate或父ViewController拦截\u003c/p\u003e\n\u003cp\u003e有点类似触摸事件传递，屏幕旋转也是一层一层的询问。\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eAppdelegate  ---\u0026gt;  UIWindow.rootViewController  ----\u0026gt; rootViewController的子ViewController\u003c/code\u003e\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e父子ViewController的概念，可以参考 \u003ccode\u003eUIViewController.addChildViewController\u003c/code\u003e 相关方法。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003e具体来说\nAppdelegate关于旋转的方法\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (UIInterfaceOrientationMask)\u003cspan style=\"color:#a6e22e\"\u003esupportedInterfaceOrientationsForWindow:\u003c/span\u003e(nullable UIWindow \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)window;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (UIInterfaceOrientationMask)\u003cspan style=\"color:#a6e22e\"\u003eapplication:\u003c/span\u003e(UIApplication \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)application \u003cspan style=\"color:#a6e22e\"\u003esupportedInterfaceOrientationsForWindow:\u003c/span\u003e(nullable UIWindow \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)window;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003erootViewController关于旋转的方法\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# rootViewController 是UINavigationController\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e-(UIInterfaceOrientationMask)\u003cspan style=\"color:#a6e22e\"\u003enavigationControllerSupportedInterfaceOrientations:\u003c/span\u003e(UINavigationController \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)navigationController;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (\u003cspan style=\"color:#66d9ef\"\u003eBOOL\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003eshouldAutorotate\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e子ViewController\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (\u003cspan style=\"color:#66d9ef\"\u003eBOOL\u003c/span\u003e) \u003cspan style=\"color:#a6e22e\"\u003eshouldAutorotate\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-(UIInterfaceOrientationMask)\u003cspan style=\"color:#a6e22e\"\u003esupportedInterfaceOrientations\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003ewillRotateToInterfaceOrientation:\u003c/span\u003e(UIInterfaceOrientation)toInterfaceOrientation \u003cspan style=\"color:#a6e22e\"\u003eduration:\u003c/span\u003e(NSTimeInterval)duration;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003edidRotateFromInterfaceOrientation:\u003c/span\u003e(UIInterfaceOrientation)fromInterfaceOrientation;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003eviewWillTransitionToSize:\u003c/span\u003e(CGSize)size \u003cspan style=\"color:#a6e22e\"\u003ewithTransitionCoordinator:\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eid\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUIViewControllerTransitionCoordinator\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e)coordinator;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e参考 \u003ca href=\"https://www.jianshu.com/p/b1ebaad87a80\"\u003ehttps://www.jianshu.com/p/b1ebaad87a80\u003c/a\u003e\n参考https://www.jianshu.com/p/7c1d214adcbd\n参考https://www.jianshu.com/p/73be6d0e152f\u003c/p\u003e","title":"iOS  shouldAutorotate , supportedInterfaceOrientations , viewWillTransitionToSize不调用问题"},{"content":"可修改info.plist文件中的NSExtensionAttributes .NSExtensionActivationRule 值，例如\n\u0026lt;key\u0026gt;NSExtensionAttributes\u0026lt;/key\u0026gt; \u0026lt;dict\u0026gt; \u0026lt;key\u0026gt;NSExtensionActivationRule\u0026lt;/key\u0026gt; \u0026lt;dict\u0026gt; \u0026lt;key\u0026gt;NSExtensionActivationSupportsImageWithMaxCount\u0026lt;/key\u0026gt; \u0026lt;integer\u0026gt;10\u0026lt;/integer\u0026gt; \u0026lt;key\u0026gt;NSExtensionActivationSupportsMovieWithMaxCount\u0026lt;/key\u0026gt; \u0026lt;integer\u0026gt;1\u0026lt;/integer\u0026gt; \u0026lt;key\u0026gt;NSExtensionActivationSupportsWebURLWithMaxCount\u0026lt;/key\u0026gt; \u0026lt;integer\u0026gt;1\u0026lt;/integer\u0026gt; \u0026lt;/dict\u0026gt; \u0026lt;/dict\u0026gt; 更多参见 https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW8\n","permalink":"https://blog.z6z8.cn/2020/11/05/ios-%E5%88%86%E4%BA%AB%E6%89%A9%E5%B1%95%EF%BC%88shareextension%EF%BC%89%E6%8C%87%E5%AE%9A%E5%8F%AF%E4%BB%A5%E5%88%86%E4%BA%AB%E7%9A%84%E6%95%B0%E6%8D%AE%E7%B1%BB%E5%9E%8B/","summary":"\u003cp\u003e可修改info.plist文件中的NSExtensionAttributes .NSExtensionActivationRule 值，例如\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;key\u0026gt;\u003c/span\u003eNSExtensionAttributes\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/key\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;dict\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;key\u0026gt;\u003c/span\u003eNSExtensionActivationRule\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/key\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;dict\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;key\u0026gt;\u003c/span\u003eNSExtensionActivationSupportsImageWithMaxCount\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/key\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;integer\u0026gt;\u003c/span\u003e10\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/integer\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;key\u0026gt;\u003c/span\u003eNSExtensionActivationSupportsMovieWithMaxCount\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/key\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;integer\u0026gt;\u003c/span\u003e1\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/integer\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;key\u0026gt;\u003c/span\u003eNSExtensionActivationSupportsWebURLWithMaxCount\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/key\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e\u0026lt;integer\u0026gt;\u003c/span\u003e1\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/integer\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/dict\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/dict\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e更多参见 \u003ca href=\"https://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW8\"\u003ehttps://developer.apple.com/library/archive/documentation/General/Conceptual/ExtensibilityPG/ExtensionScenarios.html#//apple_ref/doc/uid/TP40014214-CH21-SW8\u003c/a\u003e\u003c/p\u003e","title":"iOS 分享扩展（ShareExtension）指定可以分享的数据类型"},{"content":"adb命令\nadb usb ==== 重启 adb的 usb连接 adb shell pm list packages ==== 列举所有应用包名 adb shell am monitor ==== 监控手机上的应用启动 adb shell pm uninstall -k --user 0 包名 ==== 删除包（屏蔽包） ","permalink":"https://blog.z6z8.cn/2020/11/05/adb-%E9%81%8D%E5%8E%86android%E5%BA%94%E7%94%A8%E5%8C%85%E5%90%8D%E5%B9%B6%E5%88%A0%E9%99%A4/","summary":"\u003cp\u003eadb命令\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadb usb ==== 重启 adb的 usb连接\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadb shell pm list packages   ==== 列举所有应用包名\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadb shell am monitor  ==== 监控手机上的应用启动\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eadb shell pm uninstall -k  --user 0 包名  ==== 删除包（屏蔽包）\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"adb  遍历Android应用包名并删除"},{"content":"1、创建工程文件夹 并进入 mkdir my-electron-app \u0026amp;\u0026amp; cd my-electron-app\n2、初始化npm npm init -y\n3、安装electron npm i --save-dev electron\n自动化脚本\n#!/bin/bash # -*- coding:utf-8 -*- import os import sys import json if (len(sys.argv) \u0026lt; 2 ): print(\u0026#34;缺少electron工程名字 ； python create-electron-app name\u0026#34;) exit(0) CURRENT_PATH = sys.path[0] APP_NAME = sys.argv[1] APP_DIR = os.path.join(CURRENT_PATH,APP_NAME) if os.path.exists( APP_DIR ): print(\u0026#34;目录\u0026#34; + APP_NAME + \u0026#34;已存在\u0026#34;) exit(0) # 创建工程目录 os.system(\u0026#34;cd {} \u0026amp;\u0026amp; mkdir {}\u0026#34;.format(CURRENT_PATH,APP_NAME)) # 初始化npm os.system(\u0026#34;cd {} \u0026amp;\u0026amp; npm init -y\u0026#34;.format(APP_DIR)) #安装electron os.system(\u0026#34;cd {} \u0026amp;\u0026amp; npm i --save-dev electron\u0026#34;.format(APP_DIR)) #创建主脚本 mainjs = \u0026#34;\u0026#34;\u0026#34; const { app, BrowserWindow } = require(\u0026#39;electron\u0026#39;) function createWindow () { const win = new BrowserWindow({ width: 800, height: 600, webPreferences: { nodeIntegration: true } }) win.loadFile(\u0026#39;main.html\u0026#39;) win.webContents.openDevTools() } app.whenReady().then(createWindow) app.on(\u0026#39;window-all-closed\u0026#39;, () =\u0026gt; { if (process.platform !== \u0026#39;darwin\u0026#39;) { app.quit() } }) app.on(\u0026#39;activate\u0026#39;, () =\u0026gt; { if (BrowserWindow.getAllWindows().length === 0) { createWindow() } }) \u0026#34;\u0026#34;\u0026#34; fs = open(os.path.join(APP_DIR,\u0026#34;main.js\u0026#34;),\u0026#34;w\u0026#34;) fs.write(mainjs) fs.close() #创建主html mainhtml = \u0026#34;\u0026#34;\u0026#34; \u0026lt;OCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta charset=\u0026#34;UTF-8\u0026#34;\u0026gt; \u0026lt;title\u0026gt;Hello World!\u0026lt;/title\u0026gt; \u0026lt;meta http-equiv=\u0026#34;Content-Security-Policy\u0026#34; content=\u0026#34;script-src \u0026#39;self\u0026#39; \u0026#39;unsafe-inline\u0026#39;;\u0026#34; /\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;h1\u0026gt;Hello World！\u0026lt;/h1\u0026gt; \u0026lt;p\u0026gt;世界你好\u0026lt;/p\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; \u0026#34;\u0026#34;\u0026#34; fs = open(os.path.join(APP_DIR,\u0026#34;main.html\u0026#34;),\u0026#34;w\u0026#34;) fs.write(mainhtml) fs.close() # 添加快捷启动方式 fs = open(os.path.join(APP_DIR,\u0026#34;package.json\u0026#34;),\u0026#34;r\u0026#34;) jsondata = fs.read() fs.close() jsonobj = json.loads(jsondata) jsonobj[\u0026#34;scripts\u0026#34;][\u0026#34;start\u0026#34;] = \u0026#34;electron .\u0026#34; jsonobj[\u0026#34;main\u0026#34;]= \u0026#34;main.js\u0026#34; jsondata = json.dumps(jsonobj,indent=4) fs = open(os.path.join(APP_DIR,\u0026#34;package.json\u0026#34;),\u0026#34;w\u0026#34;) fs.write(jsondata) fs.close() # 启动 os.system(\u0026#34;cd {} \u0026amp;\u0026amp; npm start\u0026#34;.format(APP_DIR)) 参考 https://www.electronjs.org/docs/tutorial/quick-start\n","permalink":"https://blog.z6z8.cn/2020/10/28/%E6%89%8B%E5%8A%A8%E5%88%9B%E5%BB%BA%E4%B8%80%E4%B8%AAelectron%E5%B7%A5%E7%A8%8B/","summary":"\u003cp\u003e1、创建工程文件夹 并进入\n\u003ccode\u003emkdir my-electron-app \u0026amp;\u0026amp; cd my-electron-app\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e2、初始化npm\n\u003ccode\u003enpm init -y\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e3、安装electron\n\u003ccode\u003enpm i --save-dev electron\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e自动化脚本\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#!/bin/bash\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# -*- coding:utf-8 -*-\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e os\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e sys\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e json\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (len(sys\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eargv) \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e ):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    print(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;缺少electron工程名字 ； python create-electron-app name\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    exit(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCURRENT_PATH \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e sys\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epath[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAPP_NAME \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e sys\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eargv[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAPP_DIR \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e os\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epath\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ejoin(CURRENT_PATH,APP_NAME)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e os\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epath\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eexists( APP_DIR ):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    print(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;目录\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e APP_NAME \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;已存在\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    exit(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 创建工程目录\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eos\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esystem(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;cd \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e \u0026amp;\u0026amp; mkdir \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eformat(CURRENT_PATH,APP_NAME))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 初始化npm\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eos\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esystem(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;cd \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e \u0026amp;\u0026amp; npm init -y\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eformat(APP_DIR))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#安装electron\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eos\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esystem(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;cd \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e \u0026amp;\u0026amp; npm i --save-dev electron\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eformat(APP_DIR))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#创建主脚本\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emainjs \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003econst { app, BrowserWindow } = require(\u0026#39;electron\u0026#39;)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003efunction createWindow () {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e  const win = new BrowserWindow({\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    width: 800,\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    height: 600,\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    webPreferences: {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e      nodeIntegration: true\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e  })\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e  win.loadFile(\u0026#39;main.html\u0026#39;)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e  win.webContents.openDevTools()\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003eapp.whenReady().then(createWindow)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003eapp.on(\u0026#39;window-all-closed\u0026#39;, () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e  if (process.platform !== \u0026#39;darwin\u0026#39;) {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    app.quit()\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e})\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003eapp.on(\u0026#39;activate\u0026#39;, () =\u0026gt; {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e  if (BrowserWindow.getAllWindows().length === 0) {\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    createWindow()\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e})\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efs \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e open(os\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epath\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ejoin(APP_DIR,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;main.js\u0026#34;\u003c/span\u003e),\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;w\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efs\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ewrite(mainjs)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efs\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eclose()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#创建主html\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emainhtml \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026lt;OCTYPE html\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026lt;html\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026lt;head\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    \u0026lt;meta charset=\u0026#34;UTF-8\u0026#34;\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    \u0026lt;title\u0026gt;Hello World!\u0026lt;/title\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    \u0026lt;meta http-equiv=\u0026#34;Content-Security-Policy\u0026#34; content=\u0026#34;script-src \u0026#39;self\u0026#39; \u0026#39;unsafe-inline\u0026#39;;\u0026#34; /\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026lt;/head\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026lt;body\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    \u0026lt;h1\u0026gt;Hello World！\u0026lt;/h1\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e    \u0026lt;p\u0026gt;世界你好\u0026lt;/p\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026lt;/body\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026lt;/html\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efs \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e open(os\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epath\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ejoin(APP_DIR,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;main.html\u0026#34;\u003c/span\u003e),\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;w\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efs\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ewrite(mainhtml)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efs\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eclose()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 添加快捷启动方式\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efs \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e open(os\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epath\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ejoin(APP_DIR,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;package.json\u0026#34;\u003c/span\u003e),\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;r\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ejsondata \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e fs\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eread()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efs\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eclose()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ejsonobj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e json\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eloads(jsondata)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ejsonobj[\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;scripts\u0026#34;\u003c/span\u003e][\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;start\u0026#34;\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;electron .\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ejsonobj[\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;main\u0026#34;\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;main.js\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ejsondata \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e json\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003edumps(jsonobj,indent\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efs \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e open(os\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003epath\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ejoin(APP_DIR,\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;package.json\u0026#34;\u003c/span\u003e),\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;w\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efs\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ewrite(jsondata)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efs\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eclose()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 启动\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eos\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003esystem(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;cd \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e{}\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e \u0026amp;\u0026amp; npm start\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eformat(APP_DIR))\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e参考 \u003ca href=\"https://www.electronjs.org/docs/tutorial/quick-start\"\u003ehttps://www.electronjs.org/docs/tutorial/quick-start\u003c/a\u003e\u003c/p\u003e","title":"手动创建一个electron工程"},{"content":"CSS 7 种基础的选择器：\nID 选择器， 如 #id{}\n类选择器， 如 .class{}\n属性选择器， 如 a[href=\u0026ldquo;segmentfault.com\u0026rdquo;]{}\n伪类选择器， 如 :hover{}\n伪元素选择器， 如 ::before{}\n标签选择器， 如 span{}\n通配选择器， 如 *{}\nCSS 优先规则3：优先级关系：内联样式 \u0026gt; ID 选择器 \u0026gt; 类选择器 = 属性选择器 = 伪类选择器 \u0026gt; 标签选择器 = 伪元素选择器\n参考 https://www.runoob.com/w3cnote/css-style-priority.html\n","permalink":"https://blog.z6z8.cn/2020/09/30/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A%EF%BC%88%E8%BD%AC%EF%BC%89css%E6%A0%B7%E5%BC%8F%E9%80%89%E6%8B%A9%E5%99%A8%E4%BC%98%E5%85%88%E7%BA%A7/","summary":"\u003cp\u003eCSS 7 种基础的选择器：\u003c/p\u003e\n\u003cp\u003eID 选择器， 如 #id{}\u003c/p\u003e\n\u003cp\u003e类选择器， 如 .class{}\u003c/p\u003e\n\u003cp\u003e属性选择器， 如 a[href=\u0026ldquo;segmentfault.com\u0026rdquo;]{}\u003c/p\u003e\n\u003cp\u003e伪类选择器， 如 :hover{}\u003c/p\u003e\n\u003cp\u003e伪元素选择器， 如 ::before{}\u003c/p\u003e\n\u003cp\u003e标签选择器， 如 span{}\u003c/p\u003e\n\u003cp\u003e通配选择器， 如 *{}\u003c/p\u003e\n\u003cp\u003eCSS 优先规则3：优先级关系：内联样式 \u0026gt; ID 选择器 \u0026gt; 类选择器 = 属性选择器 = 伪类选择器 \u0026gt; 标签选择器 = 伪元素选择器\u003c/p\u003e\n\u003cp\u003e参考 \u003ca href=\"https://www.runoob.com/w3cnote/css-style-priority.html\"\u003ehttps://www.runoob.com/w3cnote/css-style-priority.html\u003c/a\u003e\u003c/p\u003e","title":"学习笔记：（转）CSS样式选择器优先级"},{"content":"如题 如果cell中有TextView或者TextField，tableview reload后会是TextView/TextField失去焦点。使用beginUpdates/endUpdates，则会保持焦点\n","permalink":"https://blog.z6z8.cn/2020/09/14/uitablview-reload%E4%BC%9A%E6%98%AFtextview%E5%A4%B1%E5%8E%BB%E7%84%A6%E7%82%B9%EF%BC%8C%E5%8F%AF%E4%BD%BF%E7%94%A8beginupdates-endupdates%E6%9B%BF%E4%BB%A3/","summary":"\u003cp\u003e如题\n如果cell中有TextView或者TextField，tableview reload后会是TextView/TextField失去焦点。使用beginUpdates/endUpdates，则会保持焦点\u003c/p\u003e","title":"UITablView Reload会是TextView失去焦点，可使用beginUpdates/endUpdates替代"},{"content":"static inline BOOL isChineseC(u_long ch) { /// https://www.qqxiuzi.cn/zh/hanzi-unicode-bianma.php return ( (/ 基本汉字/ ch \u0026gt;= 0x4E00 \u0026amp;\u0026amp; ch \u0026lt;= 0x9FA5) || (/ 基本汉字补充/ ch \u0026gt;= 0x9FA6 \u0026amp;\u0026amp; ch \u0026lt;= 0x9FEF) || (/ 扩展A/ ch \u0026gt;= 0x3400 \u0026amp;\u0026amp; ch \u0026lt;= 0x4DB5) || (/ 扩展B/ ch \u0026gt;= 0x20000 \u0026amp;\u0026amp; ch \u0026lt;= 0x2A6D6) || (/ 扩展C/ ch \u0026gt;= 0x2A700 \u0026amp;\u0026amp; ch \u0026lt;= 0x2B734) || (/ 扩展D/ ch \u0026gt;= 0x2B740 \u0026amp;\u0026amp; ch \u0026lt;= 0x2B81D) || (/ 扩展E/ ch \u0026gt;= 0x2B820 \u0026amp;\u0026amp; ch \u0026lt;= 0x2CEA1) || (/ 扩展F/ ch \u0026gt;= 0x2CEB0 \u0026amp;\u0026amp; ch \u0026lt;= 0x2EBE0) || (/ 扩展G/ ch \u0026gt;= 0x30000 \u0026amp;\u0026amp; ch \u0026lt;= 0x3134A) || (/ 康熙部首/ ch \u0026gt;= 0x2F00 \u0026amp;\u0026amp; ch \u0026lt;= 0x2FD5) || (/ 部首扩展/ ch \u0026gt;= 0x2E80 \u0026amp;\u0026amp; ch \u0026lt;= 0x2EF3) || (/ 兼容汉/ ch \u0026gt;= 0xF900 \u0026amp;\u0026amp; ch \u0026lt;= 0xFAD9) || (/ 兼容扩展/ ch \u0026gt;= 0x2F800 \u0026amp;\u0026amp; ch \u0026lt;= 0x2FA1D) || (/ PUA(GBK)部件/ ch \u0026gt;= 0xE815 \u0026amp;\u0026amp; ch \u0026lt;= 0xE86F) || (/ 部件扩展/ ch \u0026gt;= 0xE400 \u0026amp;\u0026amp; ch \u0026lt;= 0xE5E8) || (/ PUA增补/ ch \u0026gt;= 0xE600 \u0026amp;\u0026amp; ch \u0026lt;= 0xE6CF) || (/ 汉字笔画/ ch \u0026gt;= 0x31C0 \u0026amp;\u0026amp; ch \u0026lt;= 0x31E3) || (/ 汉字结构/ ch \u0026gt;= 0x2FF0 \u0026amp;\u0026amp; ch \u0026lt;= 0x2FFB) || (/ 汉语注音/ ch \u0026gt;= 0x3105 \u0026amp;\u0026amp; ch \u0026lt;= 0x312F) || (/ 注音扩展/ ch \u0026gt;= 0x31A0 \u0026amp;\u0026amp; ch \u0026lt;= 0x31BA) || (/ 〇/ ch == 0x3007) ); }\n","permalink":"https://blog.z6z8.cn/2020/09/04/%E5%88%A4%E6%96%ADunicode%E7%A0%81%E6%98%AF%E5%90%A6%E8%90%BD%E5%9C%A8%E4%BA%86%E4%B8%AD%E6%96%87%E5%8C%BA%E9%97%B4/","summary":"\u003cp\u003estatic inline BOOL isChineseC(u_long ch)\n{\n/// \u003ca href=\"https://www.qqxiuzi.cn/zh/hanzi-unicode-bianma.php\"\u003ehttps://www.qqxiuzi.cn/zh/hanzi-unicode-bianma.php\u003c/a\u003e\nreturn (\n(/ \u003cem\u003e基本汉字\u003c/em\u003e/ ch \u0026gt;= 0x4E00 \u0026amp;\u0026amp; ch \u0026lt;= 0x9FA5) ||\n(/ \u003cem\u003e基本汉字补充\u003c/em\u003e/ ch \u0026gt;= 0x9FA6 \u0026amp;\u0026amp; ch \u0026lt;= 0x9FEF) ||\n(/ \u003cem\u003e扩展A\u003c/em\u003e/ ch \u0026gt;= 0x3400 \u0026amp;\u0026amp; ch \u0026lt;= 0x4DB5) ||\n(/ \u003cem\u003e扩展B\u003c/em\u003e/ ch \u0026gt;= 0x20000 \u0026amp;\u0026amp; ch \u0026lt;= 0x2A6D6) ||\n(/ \u003cem\u003e扩展C\u003c/em\u003e/ ch \u0026gt;= 0x2A700 \u0026amp;\u0026amp; ch \u0026lt;= 0x2B734) ||\n(/ \u003cem\u003e扩展D\u003c/em\u003e/ ch \u0026gt;= 0x2B740 \u0026amp;\u0026amp; ch \u0026lt;= 0x2B81D) ||\n(/ \u003cem\u003e扩展E\u003c/em\u003e/ ch \u0026gt;= 0x2B820 \u0026amp;\u0026amp; ch \u0026lt;= 0x2CEA1) ||\n(/ \u003cem\u003e扩展F\u003c/em\u003e/ ch \u0026gt;= 0x2CEB0 \u0026amp;\u0026amp; ch \u0026lt;= 0x2EBE0) ||\n(/ \u003cem\u003e扩展G\u003c/em\u003e/ ch \u0026gt;= 0x30000 \u0026amp;\u0026amp; ch \u0026lt;= 0x3134A) ||\n(/ \u003cem\u003e康熙部首\u003c/em\u003e/ ch \u0026gt;= 0x2F00 \u0026amp;\u0026amp; ch \u0026lt;= 0x2FD5) ||\n(/ \u003cem\u003e部首扩展\u003c/em\u003e/ ch \u0026gt;= 0x2E80 \u0026amp;\u0026amp; ch \u0026lt;= 0x2EF3) ||\n(/ \u003cem\u003e兼容汉\u003c/em\u003e/ ch \u0026gt;= 0xF900 \u0026amp;\u0026amp; ch \u0026lt;= 0xFAD9) ||\n(/ \u003cem\u003e兼容扩展\u003c/em\u003e/ ch \u0026gt;= 0x2F800 \u0026amp;\u0026amp; ch \u0026lt;= 0x2FA1D) ||\n(/ \u003cem\u003ePUA(GBK)部件\u003c/em\u003e/ ch \u0026gt;= 0xE815 \u0026amp;\u0026amp; ch \u0026lt;= 0xE86F) ||\n(/ \u003cem\u003e部件扩展\u003c/em\u003e/ ch \u0026gt;= 0xE400 \u0026amp;\u0026amp; ch \u0026lt;= 0xE5E8) ||\n(/ \u003cem\u003ePUA增补\u003c/em\u003e/ ch \u0026gt;= 0xE600 \u0026amp;\u0026amp; ch \u0026lt;= 0xE6CF) ||\n(/ \u003cem\u003e汉字笔画\u003c/em\u003e/ ch \u0026gt;= 0x31C0 \u0026amp;\u0026amp; ch \u0026lt;= 0x31E3) ||\n(/ \u003cem\u003e汉字结构\u003c/em\u003e/ ch \u0026gt;= 0x2FF0 \u0026amp;\u0026amp; ch \u0026lt;= 0x2FFB) ||\n(/ \u003cem\u003e汉语注音\u003c/em\u003e/ ch \u0026gt;= 0x3105 \u0026amp;\u0026amp; ch \u0026lt;= 0x312F) ||\n(/ \u003cem\u003e注音扩展\u003c/em\u003e/ ch \u0026gt;= 0x31A0 \u0026amp;\u0026amp; ch \u0026lt;= 0x31BA) ||\n(/ \u003cem\u003e〇\u003c/em\u003e/ ch == 0x3007)\n);\n}\u003c/p\u003e","title":"判断Unicode码是否落在了中文区间"},{"content":"默认情况下，使用UICollectionViewFlowLayout布局的UICollectionView 的 添加元素，没多一行就会会有自动向上滚动。UITableView的效果也是类似的。 （相对于用户来说）为了保持屏幕定位不变，也就是用户操作的某个cell在屏幕上的位置不变，可以这样做： 获取一行的高度，设置UICollectionView的contentOffset，使向反方向滚动一行，然后立即添加元素\n示意代码\n//在performBatchUpdates中批量执行 [collectionView performBatchUpdates:^{ // 禁用动画效果 [UIView setAnimationsEnabled:NO]; //添加元素 [collectionView insertItemsAtIndexPaths:@[addIndp]]; if (新增一行) { // 计算一行高度 CGFloat oneLineHeight= 1000; CGFloat oneTop = 0; for (UICollectionViewCell * cell in _collectionView.visibleCells) { if (oneTop \u0026lt;= 0 ) { oneTop = cell.top; } else if (oneTop != cell.top) { CGFloat tmp = (cell.top - oneTop); tmp = ABS(tmp); if (tmp \u0026gt; 1 \u0026amp;\u0026amp; oneLineHeight \u0026gt; tmp ) { oneLineHeight = tmp; } } } //向上滚动一行 CGPoint offset = collectionView.contentOffset; offset.y += oneLineHeight; collectionView.contentOffset = offset; } } completion:^(BOOL finished) { //开启动画效果 [UIView setAnimationsEnabled:YES]; }]; ","permalink":"https://blog.z6z8.cn/2020/07/17/uicollectionview-%EF%BC%88uicollectionviewflowlayout%EF%BC%89%E6%B7%BB%E5%8A%A0%E5%85%83%E7%B4%A0%E6%97%B6%E4%BF%9D%E6%8C%81%E5%B1%8F%E5%B9%95%E5%AE%9A%E4%BD%8D%E4%B8%8D%E5%8F%98/","summary":"\u003cp\u003e默认情况下，使用UICollectionViewFlowLayout布局的UICollectionView 的 添加元素，没多一行就会会有自动向上滚动。UITableView的效果也是类似的。\n（相对于用户来说）为了保持屏幕定位不变，也就是用户操作的某个cell在屏幕上的位置不变，可以这样做：\n\u003ccode\u003e获取一行的高度，设置UICollectionView的contentOffset，使向反方向滚动一行，然后立即添加元素\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e示意代码\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//在performBatchUpdates中批量执行\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e[collectionView performBatchUpdates:\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#75715e\"\u003e// 禁用动画效果\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    [UIView setAnimationsEnabled:NO];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#75715e\"\u003e//添加元素\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    [collectionView insertItemsAtIndexPaths:\u003cspan style=\"color:#ae81ff\"\u003e@[\u003c/span\u003eaddIndp\u003cspan style=\"color:#ae81ff\"\u003e]\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e新增一行\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#75715e\"\u003e//  计算一行高度\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                        CGFloat oneLineHeight\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        CGFloat oneTop \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (UICollectionViewCell  \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e cell \u003cspan style=\"color:#66d9ef\"\u003ein\u003c/span\u003e _collectionView.visibleCells)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (oneTop \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                oneTop \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e cell.top;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (oneTop \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e cell.top)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                CGFloat tmp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (cell.top \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e oneTop);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                tmp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ABS(tmp);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (tmp \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e oneLineHeight \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e tmp )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                    oneLineHeight \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e tmp;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#75715e\"\u003e//向上滚动一行\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                        CGPoint offset \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e collectionView.contentOffset;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        offset.y \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e oneLineHeight;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        collectionView.contentOffset \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e offset;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                } completion:\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eBOOL\u003c/span\u003e finished) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#75715e\"\u003e//开启动画效果\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    [UIView setAnimationsEnabled:YES];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }];\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"UICollectionView （UICollectionViewFlowLayout）添加元素时保持屏幕定位不变"},{"content":"生成patch 1、生成当前分支的patch\n生成当前分支指定节点之后的所有patch 生成的patch，会根据节点顺序自动编号，一个commit生成一个patch文件\ngit format-patch 404777e8586393d5eb6581485fc1bb2bf2e8eb2a //这里长短commit id都可以 2、生成两个节点之间的patch\ngit format-patch 节点开始..节点结束 //这里长短commit id都可以 //例如 git format-patch aed12..ecf3a 更多详细 https://blog.csdn.net/sunnylgz/article/details/7661920\n使用patch 生成patch相对容易，使用时却有些麻烦，尤其是有冲突的时候。 对于有冲突的patch，用搜索引擎搜索出的结果大都是\ngit apply --reject patch文件 //对于冲突，会生成.rej文件，然后手动解决所有冲突 这种办法在有冲突时，并不好用（因为根据.rej文件手动解决冲突比较麻烦） 我尝试的一个简单方法是\ngit am --3way patch文件 //解决冲突后 git am --continue --3way，会尝试合并冲突到目标文件，而不是另生成.rej文件，这样的好处是可以使用成熟的冲突解决工具\n","permalink":"https://blog.z6z8.cn/2020/07/06/git-patch-%E6%96%87%E4%BB%B6%E7%9A%84%E4%BD%BF%E7%94%A8%E6%96%B9%E6%B3%95/","summary":"\u003ch2 id=\"生成patch\"\u003e生成patch\u003c/h2\u003e\n\u003cp\u003e1、生成当前分支的patch\u003c/p\u003e\n\u003cp\u003e生成当前分支指定节点之后的所有patch\n生成的patch，会根据节点顺序自动编号，一个commit生成一个patch文件\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit format-patch 404777e8586393d5eb6581485fc1bb2bf2e8eb2a //这里长短commit id都可以\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e2、生成两个节点之间的patch\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit format-patch  节点开始..节点结束 //这里长短commit id都可以\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e//例如\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit format-patch aed12..ecf3a\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e更多详细 \u003ca href=\"https://blog.csdn.net/sunnylgz/article/details/7661920\"\u003ehttps://blog.csdn.net/sunnylgz/article/details/7661920\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"使用patch\"\u003e使用patch\u003c/h2\u003e\n\u003cp\u003e生成patch相对容易，使用时却有些麻烦，尤其是有冲突的时候。\n对于有冲突的patch，用搜索引擎搜索出的结果大都是\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit apply --reject patch文件\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e//对于冲突，会生成.rej文件，然后手动解决所有冲突\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e这种办法在有冲突时，并不好用（因为根据.rej文件手动解决冲突比较麻烦）\n我尝试的一个简单方法是\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit am --3way patch文件\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e//解决冲突后\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit am --continue\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003ccode\u003e--3way\u003c/code\u003e，会尝试合并冲突到目标文件，而不是另生成.rej文件，这样的好处是可以使用成熟的冲突解决工具\u003c/p\u003e","title":"git patch 文件冲突时的解决办法"},{"content":"读取/var/log/secure，查找关键字 Failed，例如：\nSep 17 09:08:09 localhost sshd[29087]: Failed password for root from 13.7.3.6 port 44367 ssh2 Sep 17 09:08:20 localhost sshd[29087]: Failed password for root from 13.7.3.6 port 44367 ssh2 Sep 17 09:10:02 localhost sshd[29223]: Failed password for root from 13.7.3.6 port 56482 ssh2 Sep 17 09:10:14 localhost sshd[29223]: Failed password for root from 13.7.3.6 port 56482 ssh2\n从这些行中提取IP地址，如果次数达到10次(脚本中判断次数字符长度是否大于1)则将该IP写到 /etc/hosts.deny 中。\n步骤：\n1、先把始终允许的IP填入 /etc/hosts.allow ，这很重要！比如： sshd:19.16.18.1:allow sshd:19.16.18.2:allow\n2、脚本 /usr/local/bin/secure_ssh.sh\n#! /bin/bash cat /var/log/secure|awk \u0026#39;/Failed/{print $(NF-3)}\u0026#39;|sort|uniq -c|awk \u0026#39;{print $2\u0026#34;=\u0026#34;$1;}\u0026#39; \u0026gt; /usr/local/bin/black.list for i in \u0026lt;code\u0026gt;cat /usr/local/bin/black.list\u0026lt;/code\u0026gt; do IP=\u0026lt;code\u0026gt;echo $i |awk -F= \u0026#39;{print $1}\u0026#39;\u0026lt;/code\u0026gt; NUM=\u0026lt;code\u0026gt;echo $i|awk -F= \u0026#39;{print $2}\u0026#39;\u0026lt;/code\u0026gt; if [ ${#NUM} -gt 1 ]; then grep $IP /etc/hosts.deny \u0026gt; /dev/null if [ $? -gt 0 ];then echo \u0026#34;sshd:$IP:deny\u0026#34; \u0026gt;\u0026gt; /etc/hosts.deny fi fi done 3、将secure_ssh.sh脚本放入cron计划任务，每1分钟执行一次。\ncrontab -e /1 \\* sh /usr/local/bin/secure_ssh.sh\n原文： https://www.cnblogs.com/panblack/p/secure_ssh_auto_block.html\n","permalink":"https://blog.z6z8.cn/2020/06/27/%E3%80%90%E8%BD%AC%E3%80%91ssh%E8%AE%BF%E9%97%AE%E6%8E%A7%E5%88%B6%EF%BC%8C%E5%A4%9A%E6%AC%A1%E5%A4%B1%E8%B4%A5%E7%99%BB%E5%BD%95%E5%8D%B3%E5%B0%81%E6%8E%89ip%EF%BC%8C%E9%98%B2%E6%AD%A2%E6%9A%B4/","summary":"\u003cp\u003e读取/var/log/secure，查找关键字 Failed，例如：\u003c/p\u003e\n\u003cp\u003eSep 17 09:08:09 localhost sshd[29087]: Failed password for root from 13.7.3.6 port 44367 ssh2\nSep 17 09:08:20 localhost sshd[29087]: Failed password for root from 13.7.3.6 port 44367 ssh2\nSep 17 09:10:02 localhost sshd[29223]: Failed password for root from 13.7.3.6 port 56482 ssh2\nSep 17 09:10:14 localhost sshd[29223]: Failed password for root from 13.7.3.6 port 56482 ssh2\u003c/p\u003e\n\u003cp\u003e从这些行中提取IP地址，如果次数达到10次(脚本中判断次数字符长度是否大于1)则将该IP写到 \u003ccode\u003e/etc/hosts.deny\u003c/code\u003e 中。\u003c/p\u003e\n\u003cp\u003e步骤：\u003c/p\u003e\n\u003cp\u003e1、先把始终允许的IP填入 /etc/hosts.allow ，这很重要！比如：\nsshd:19.16.18.1:allow\nsshd:19.16.18.2:allow\u003c/p\u003e\n\u003cp\u003e2、脚本 /usr/local/bin/secure_ssh.sh\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-bash\" data-lang=\"bash\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#! /bin/bash\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003ecat /var/log/secure|awk \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;/Failed/{print $(NF-3)}\u0026#39;\u003c/span\u003e|sort|uniq -c|awk \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;{print $2\u0026#34;=\u0026#34;$1;}\u0026#39;\u003c/span\u003e \u0026gt; /usr/local/bin/black.list\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e i in \u0026lt;code\u0026gt;cat  /usr/local/bin/black.list\u0026lt;/code\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  IP\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u0026lt;code\u0026gt;echo $i |awk -F\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;{print $1}\u0026#39;\u003c/span\u003e\u0026lt;/code\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  NUM\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u0026lt;code\u0026gt;echo $i|awk -F\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;{print $2}\u0026#39;\u003c/span\u003e\u0026lt;/code\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e${#\u003c/span\u003eNUM\u003cspan style=\"color:#e6db74\"\u003e}\u003c/span\u003e -gt \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e; \u003cspan style=\"color:#66d9ef\"\u003ethen\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    grep $IP /etc/hosts.deny \u0026gt; /dev/null\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e $? -gt \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\u003cspan style=\"color:#66d9ef\"\u003ethen\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      echo \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;sshd:\u003c/span\u003e$IP\u003cspan style=\"color:#e6db74\"\u003e:deny\u0026#34;\u003c/span\u003e \u0026gt;\u0026gt; /etc/hosts.deny\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efi\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003efi\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003edone\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e3、将secure_ssh.sh脚本放入cron计划任务，每1分钟执行一次。\u003c/p\u003e","title":"【转】ssh访问控制，多次失败登录即封掉IP，防止暴力破解"},{"content":"安装环境:\nUbuntu MySql Php Nginx 如果没有安装mysql、PHP、Nginx（或Apache）还是直接使用官方提供的一键安装包吧https://www.zentao.net/book/zentaopmshelp/90.html\n相比一键安装包，源码安装也挺简单的。\n下载开源版源码： https://www.zentao.net/download/zentaopms12.3.2-80227.html 然后解压缩到服务器上的某个目录，假设目录为 ~/zentaopms\n配置nginx，新建一个配置文件 /etc/nginx/sites-available/zentaopms.conf，内容如下\nserver { server_tokens off; server_name zentaopms.你的域名; listen 80; listen [::]:80; root ~/zentaopms/www; //这里的目录参考禅道源码解压目录 index index.php index.html index.htm; client_max_body_size 5M; location / { try_files $uri $uri/ /index.php?$args; } location ~ \\.php$ { include snippets/fastcgi-php.conf; #unix socket 路径参见 /etc/php/7.3/fpm/pool.d/www.conf fastcgi_pass unix:/run/php/php7.3-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } 创建软链接，重启nginx\ncd /etc/nginx/sites-enabled ln -s zentaopms.conf ./../sites-available/zentaopms.conf sudo systemctl retart nginx 用浏览器打开 http://zentaopms.你的域名/ 安装提示引导就好了；其中有个步骤是需要提供mysql的用户名和密码的，我们新建个就好了 新建mysql用户和数据库\n#以root用户进入mysql环境 sudo mysql -u root -p #创建数据库 需要记录下数据库名称 \u0026gt; CREATE DATABASE zentaopmsDBName; Query OK, 1 row affected (0.00 sec) # 创建用户 需要记录下用户名和密码 \u0026gt; GRANT ALL PRIVILEGES ON zentaopmsDBName.* TO \u0026#34;zentaopmsUserName\u0026#34;@\u0026#34;localhost\u0026#34; (输入到这，按回车键) -\u0026gt; IDENTIFIED BY \u0026#34;密码\u0026#34;; Query OK, 0 rows affected (0.00 sec) #提交 mysql\u0026gt; FLUSH PRIVILEGES; Query OK, 0 rows affected (0.01 sec) #退出 mysql\u0026gt; EXIT Bye ","permalink":"https://blog.z6z8.cn/2020/06/25/ubuntu18%E4%B8%8A%E4%BB%8E%E6%BA%90%E7%A0%81%E9%83%A8%E7%BD%B2%E7%A6%85%E9%81%93%E9%A1%B9%E7%9B%AE%E7%AE%A1%E7%90%86%E7%B3%BB%E7%BB%9F/","summary":"\u003cp\u003e安装环境:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eUbuntu\u003c/li\u003e\n\u003cli\u003eMySql\u003c/li\u003e\n\u003cli\u003ePhp\u003c/li\u003e\n\u003cli\u003eNginx\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e如果没有安装mysql、PHP、Nginx（或Apache）还是直接使用官方提供的一键安装包吧https://www.zentao.net/book/zentaopmshelp/90.html\u003c/p\u003e\n\u003cp\u003e相比一键安装包，源码安装也挺简单的。\u003c/p\u003e\n\u003cp\u003e下载开源版源码：\n\u003ca href=\"https://www.zentao.net/download/zentaopms12.3.2-80227.html\"\u003ehttps://www.zentao.net/download/zentaopms12.3.2-80227.html\u003c/a\u003e\n然后解压缩到服务器上的某个目录，假设目录为 \u003ccode\u003e~/zentaopms\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e配置nginx，新建一个配置文件 \u003ccode\u003e/etc/nginx/sites-available/zentaopms.conf\u003c/code\u003e，内容如下\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eserver {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    server_tokens off;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    server_name  zentaopms.你的域名;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    listen 80;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    listen [::]:80;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    root  ~/zentaopms/www; //这里的目录参考禅道源码解压目录\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    index  index.php index.html index.htm;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    client_max_body_size 5M;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    location / {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        try_files $uri $uri/ /index.php?$args;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    location ~ \\.php$ {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         include snippets/fastcgi-php.conf;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         #unix socket 路径参见 /etc/php/7.3/fpm/pool.d/www.conf\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         fastcgi_pass unix:/run/php/php7.3-fpm.sock;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         include fastcgi_params;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e创建软链接，重启nginx\u003c/p\u003e","title":"Ubuntu18上从源码部署禅道项目管理系统"},{"content":"UITableView的默认Cell，是有点击选中的高亮背景色的，UIButton也可以通过设置不同状态的背景图片来实现高亮，那么如何给自定义视图添加高亮呢？\n一个技术上可行的方法就是重写UIView的各种touches方法，自己记录点击选中，点击取消等状态，不过很繁琐。\n还有一个是重写UIControl的下面四个方法，下面四个方法将点击选中，取消等状态处理简化了\n//是否可以开始追踪事件 - (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(nullable UIEvent *)event; //是否持续追踪事件 - (BOOL)continueTrackingWithTouch:(UITouch *)touch withEvent:(nullable UIEvent *)event; //事件追踪结束 - (void)endTrackingWithTouch:(nullable UITouch *)touch withEvent:(nullable UIEvent *)event; // touch is sometimes nil if cancelTracking calls through to this. //事件追踪取消 - (void)cancelTrackingWithEvent:(nullable UIEvent *)event; // event may be nil if cancelled for non-event reasons, e.g. 具体示例\n- (BOOL)beginTrackingWithTouch:(UITouch *)touch withEvent:(nullable UIEvent *)event { BOOL b = [super beginTrackingWithTouch:touch withEvent:event]; if (b) { 如果开始追踪，那么就高亮显示 [super setBackgroundColor:高亮色]; } return b; } - (void)endTrackingWithTouch:(nullable UITouch *)touch withEvent:(nullable UIEvent *)event { [super endTrackingWithTouch:touch withEvent:event]; //结束追踪 恢复原始背景色 [super setBackgroundColor:原始背景色]; } - (void)cancelTrackingWithEvent:(nullable UIEvent *)event { [super cancelTrackingWithEvent:event]; //取消追踪 恢复原始背景色 [super setBackgroundColor:原始背景色]; } ","permalink":"https://blog.z6z8.cn/2020/06/16/ios-%E7%BB%99%E8%87%AA%E5%AE%9A%E4%B9%89%E8%A7%86%E5%9B%BE%E6%B7%BB%E5%8A%A0%E9%AB%98%E4%BA%AE%E8%83%8C%E6%99%AF%E8%89%B2/","summary":"\u003cp\u003eUITableView的默认Cell，是有点击选中的高亮背景色的，UIButton也可以通过设置不同状态的背景图片来实现高亮，那么如何给自定义视图添加高亮呢？\u003c/p\u003e\n\u003cp\u003e一个技术上可行的方法就是重写UIView的各种touches方法，自己记录点击选中，点击取消等状态，不过很繁琐。\u003c/p\u003e\n\u003cp\u003e还有一个是重写UIControl的下面四个方法，下面四个方法将点击选中，取消等状态处理简化了\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//是否可以开始追踪事件\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e- (\u003cspan style=\"color:#66d9ef\"\u003eBOOL\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003ebeginTrackingWithTouch:\u003c/span\u003e(UITouch \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)touch \u003cspan style=\"color:#a6e22e\"\u003ewithEvent:\u003c/span\u003e(nullable UIEvent \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)event;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//是否持续追踪事件\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e- (\u003cspan style=\"color:#66d9ef\"\u003eBOOL\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003econtinueTrackingWithTouch:\u003c/span\u003e(UITouch \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)touch \u003cspan style=\"color:#a6e22e\"\u003ewithEvent:\u003c/span\u003e(nullable UIEvent \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)event;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//事件追踪结束\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e- (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003eendTrackingWithTouch:\u003c/span\u003e(nullable UITouch \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)touch \u003cspan style=\"color:#a6e22e\"\u003ewithEvent:\u003c/span\u003e(nullable UIEvent \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)event; \u003cspan style=\"color:#75715e\"\u003e// touch is sometimes nil if cancelTracking calls through to this.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//事件追踪取消\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e- (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003ecancelTrackingWithEvent:\u003c/span\u003e(nullable UIEvent \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)event;   \u003cspan style=\"color:#75715e\"\u003e// event may be nil if cancelled for non-event reasons, e.g.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e具体示例\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (\u003cspan style=\"color:#66d9ef\"\u003eBOOL\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003ebeginTrackingWithTouch:\u003c/span\u003e(UITouch \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)touch \u003cspan style=\"color:#a6e22e\"\u003ewithEvent:\u003c/span\u003e(nullable UIEvent \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)event\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eBOOL\u003c/span\u003e b \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [super beginTrackingWithTouch:touch withEvent:event];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (b) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e如果开始追踪，那么就高亮显示\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        [super setBackgroundColor:\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e高亮色\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e b;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003eendTrackingWithTouch:\u003c/span\u003e(nullable UITouch \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)touch \u003cspan style=\"color:#a6e22e\"\u003ewithEvent:\u003c/span\u003e(nullable UIEvent \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)event\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [super endTrackingWithTouch:touch withEvent:event];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//结束追踪 恢复原始背景色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    [super setBackgroundColor:\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e原始背景色\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003ecancelTrackingWithEvent:\u003c/span\u003e(nullable UIEvent \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)event\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [super cancelTrackingWithEvent:event];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//取消追踪 恢复原始背景色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    [super setBackgroundColor:\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e原始背景色\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"iOS 给自定义视图添加高亮背景色"},{"content":"虽然提示是删除一个section，但不一定显式调用了deleteSection接口，还有可能是reloadSection，一个复现的场景就是reload了一个不存在的section。 例如\n//以下为示意代码 tableview = [UITableView alloc] initWithFrame:CGRectMake(0,0,100,400) style:UITableViewStylePlain]; //添加一个section [tableview.dataSource addObject:section]; //此时，只有一个section，我们reload第二个section [tableview reloadSections:[NSIndexSet indexSetWithIndex:1] withRowAnimation:UITableViewRowAnimationNone]; //崩溃 详细堆栈\nAssertion failure in -[UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore/UIKit-3901.4.5/UITableView.m:2040 2020-05-14 15:17:07.597057+0800 AppTest[33419:3092839] *** Terminating app due to uncaught exception \u0026#39;NSInternalInconsistencyException\u0026#39;, reason: \u0026#39;attempt to delete section 1, but there are only 1 sections before the update\u0026#39; *** First throw call stack: (0x187a92a48 0x1877b9fa4 0x187994e88 0x187dca654 0x18bcc5f44 0x18bcdf9d8 0x18bce0044 0x1021422a0 0x1021420bc 0x1019194e0 0x1019193b0 0x10223d8b4 0x1075817fc 0x107582bd8 0x107590c34 0x187a105e4 0x187a0b5d8 0x187a0aadc 0x1919ab328 0x18bb1863c 0x100e9cfcc 0x187894360) ","permalink":"https://blog.z6z8.cn/2020/05/15/uitableview-attempt-to-delete-section-1-but-there-are-only-1-sections-before-the-update/","summary":"\u003cp\u003e虽然提示是删除一个section，但不一定显式调用了deleteSection接口，还有可能是reloadSection，一个复现的场景就是reload了一个不存在的section。\n例如\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-obj-c\" data-lang=\"obj-c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//以下为示意代码\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etableview \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [UITableView alloc] initWithFrame:CGRectMake(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e400\u003c/span\u003e) style:UITableViewStylePlain];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//添加一个section\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e[tableview.dataSource addObject:section];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//此时，只有一个section，我们reload第二个section\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e[tableview reloadSections:[NSIndexSet indexSetWithIndex:\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e] withRowAnimation:UITableViewRowAnimationNone];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//崩溃\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e详细堆栈\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAssertion failure in -[UITableView _endCellAnimationsWithContext:], /BuildRoot/Library/Caches/com.apple.xbs/Sources/UIKitCore/UIKit-3901.4.5/UITableView.m:2040\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e2020-05-14 15:17:07.597057+0800 AppTest[33419:3092839] *** Terminating app due to uncaught exception \u0026#39;NSInternalInconsistencyException\u0026#39;, reason: \u0026#39;attempt to delete section 1, but there are only 1 sections before the update\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e*** First throw call stack:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(0x187a92a48 0x1877b9fa4 0x187994e88 0x187dca654 0x18bcc5f44 0x18bcdf9d8 0x18bce0044 0x1021422a0 0x1021420bc 0x1019194e0 0x1019193b0 0x10223d8b4 0x1075817fc 0x107582bd8 0x107590c34 0x187a105e4 0x187a0b5d8 0x187a0aadc 0x1919ab328 0x18bb1863c 0x100e9cfcc 0x187894360)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"UITableView attempt to delete section 1, but there are only 1 sections before the update"},{"content":"官方地址下载速度有点慢，这里备个份。 jd-gui-osx-1.6.6\n","permalink":"https://blog.z6z8.cn/2020/05/05/java%E5%8F%8D%E7%BC%96%E8%AF%91%E5%B7%A5%E5%85%B7macos%E7%89%88-jd-gui-osx-1-6-6/","summary":"\u003cp\u003e官方地址下载速度有点慢，这里备个份。\n\u003ca href=\"/wp-content/uploads/2020/05/jd-gui-osx-1.6.6.zip\" title=\"jd-gui-osx-1.6.6\"\u003ejd-gui-osx-1.6.6\u003c/a\u003e\u003c/p\u003e","title":"Java反编译工具MacOS版--JD-GUI-OSX-1.6.6"},{"content":"日志格式 先说日志格式，常见的日志格式: 日志头 + 线程堆栈 + 映像加载信息\n日志头（截取我们需要的部分）\n# 软硬件信息 Hardware Model: iPhone9,1 Code Type: ARM-64 (Native) OS Version: iPhone OS 13.3.1 (17D50) # 崩溃原因 Exception Type: EXC_GUARD Exception Subtype: GUARD_TYPE_FD Exception Message: CLOSE on file descriptor 66 (guarded with 0x534b434869d9c32f) Exception Note: SIMULATED (this is NOT a crash) # 崩溃线程 Triggered by Thread: 44 崩溃线程信息（截取我们需要的部分）\nThread 44 name: MHD-worker Thread 44 Crashed: # 调用堆栈 # 栈号 模块名 方法地址 加载地址 偏移量 0 libsystem_kernel.dylib 0x00000001aa54ae8c close + 8 1 iQiYiPhoneVideo 0x0000000100cceda0 0x1005e0000 + 7269792 2 iQiYiPhoneVideo 0x0000000100ccbde4 0x1005e0000 + 7257572 3 iQiYiPhoneVideo 0x0000000100ccc83c 0x1005e0000 + 7260220 4 iQiYiPhoneVideo 0x0000000100ccdc00 0x1005e0000 + 7265280 5 libsystem_pthread.dylib 0x00000001aa46dd8c _pthread_start + 156 6 libsystem_pthread.dylib 0x00000001aa47176c thread_start + 8 Thread 44 crashed with ARM Thread State (64-bit): x0: 0x0000000000000001 x1: 0x0000000000000000 x2: 0x0000000171516bdc x3: 0x0000000171516e00 x4: 0x0000000000000000 x5: 0x0000000000000400 x6: 0x0000000000000000 x7: 0x0000000000000000 x8: 0x0000000000000005 x9: 0x0000000000000006 x10: 0x0000000000000001 x11: 0x0000000000000000 x12: 0x0000000000000001 x13: 0x0000000000000002 x14: 0x0000000000000000 x15: 0x0000000000006dc2 x16: 0x0000000000000006 x17: 0x0000000055800000 x18: 0x0000000000000000 x19: 0x0000000109d900e0 x20: 0x0000000000000042 x21: 0x0000000171516e80 x22: 0x0000000171516f00 x23: 0x0000000000000000 x24: 0x0000000000000000 x25: 0x0000000000000000 x26: 0x0000000000000000 x27: 0x0000000000000000 x28: 0x0000000000000000 fp: 0x0000000171516c20 lr: 0x0000000100cceda0 sp: 0x0000000171516c00 pc: 0x00000001aa54ae8c cpsr: 0x60000000 esr: 0x00000000 Address size fault 二进制映像加载信息（截取我们需要的部分）\nBinary Images: # 模块的地址范围 模块UUID 指令集架构 模块路径 0x1005e0000 - 0x1070abfff iQiYiPhoneVideo arm64 \u0026lt;f26ad8c2b7083876944b1f6602d11caa\u0026gt; /var/containers/Bundle/Application/A9DAE6D8-A1D0-4EF1-AE5A-6F6795EDCD58/iQiYiPhoneVideo.app/iQiYiPhoneVideo 崩溃所在模块的UUID 1、崩溃日志中App的UUID 2、Xcode打包时dSYM的UUID\n1和2要匹配上才能对崩溃日志符号话\n崩溃日志中App的UUID需要从二进制映像加载信息中获取，在尖括号内,本文为 f26ad8c2b7083876944b1f6602d11caa\n# 模块的地址范围 模块UUID 指令集架构 模块路径 0x1005e0000 - 0x1070abfff iQiYiPhoneVideo arm64 \u0026lt;f26ad8c2b7083876944b1f6602d11caa\u0026gt; /var/containers/Bundle/Application/A9DAE6D8-A1D0-4EF1-AE5A-6F6795EDCD58/iQiYiPhoneVideo.app/iQiYiPhoneVideo Xcode打包时dSYM的UUID，使用命令 dwarfdump 获取\ndwarfdump --uuid XXX.app.dSYM 符号化 命令为 atos, 重要参数为\natos -o 符号表路径 -arch 指令集架构 -l 模块加载地址 方法地址A 方法地址B 方法地址C .... 符号表文件，在dSYM里面 Contents/Resources/DWARF/xxx 指令集架构，在崩溃日志的信息头，或者二进制映像加载信息中都可以获取，本文为arm64 模块加载地址，也叫模块基地址，从二进制映像加载信息中的地址范围获取，本文为0x1005e0000 方法地址，在崩溃堆栈信息中获取 例如\natos -o xxx.app.dSYM/Contents/Resources/DWARF/xxx -arch arm64 -l 0x1005e0000 0x0000000100cceda0 模块地址 有时候，自定义的崩溃日志只有崩溃堆栈信息，那么模块的加载地址如何获取呢？\n例如一些堆栈\n1 iQiYiPhoneVideo 0x0000000100cceda0 xxxxx + 7269792 按照 方法地址 = 模块地址 + 偏移量 那么 模块地址 = 0x0000000100cceda0 - 7269792 = 0x1005e0000\n","permalink":"https://blog.z6z8.cn/2020/04/15/ios%E5%B4%A9%E6%BA%83%E6%97%A5%E5%BF%97%E5%AE%9A%E4%BD%8D/","summary":"\u003ch2 id=\"日志格式\"\u003e日志格式\u003c/h2\u003e\n\u003cp\u003e先说日志格式，常见的日志格式: 日志头 + 线程堆栈 + 映像加载信息\u003c/p\u003e\n\u003cp\u003e日志头（截取我们需要的部分）\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 软硬件信息\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eHardware Model:      iPhone9,1\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCode Type:           ARM-64 (Native)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eOS Version:          iPhone OS 13.3.1 (17D50)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 崩溃原因\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eException Type:  EXC_GUARD\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eException Subtype: GUARD_TYPE_FD\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eException Message: CLOSE on file descriptor 66 (guarded with 0x534b434869d9c32f)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eException Note:  SIMULATED (this is NOT a crash)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 崩溃线程\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTriggered by Thread:  44\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e崩溃线程信息（截取我们需要的部分）\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eThread 44 name:  MHD-worker\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eThread 44 Crashed:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 调用堆栈\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 栈号  模块名   方法地址   加载地址  偏移量\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e0   libsystem_kernel.dylib          0x00000001aa54ae8c close + 8\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e1   iQiYiPhoneVideo                 0x0000000100cceda0 0x1005e0000 + 7269792\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e2   iQiYiPhoneVideo                 0x0000000100ccbde4 0x1005e0000 + 7257572\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e3   iQiYiPhoneVideo                 0x0000000100ccc83c 0x1005e0000 + 7260220\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e4   iQiYiPhoneVideo                 0x0000000100ccdc00 0x1005e0000 + 7265280\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e5   libsystem_pthread.dylib         0x00000001aa46dd8c _pthread_start + 156\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e6   libsystem_pthread.dylib         0x00000001aa47176c thread_start + 8\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eThread 44 crashed with ARM Thread State (64-bit):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    x0: 0x0000000000000001   x1: 0x0000000000000000   x2: 0x0000000171516bdc   x3: 0x0000000171516e00\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    x4: 0x0000000000000000   x5: 0x0000000000000400   x6: 0x0000000000000000   x7: 0x0000000000000000\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    x8: 0x0000000000000005   x9: 0x0000000000000006  x10: 0x0000000000000001  x11: 0x0000000000000000\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   x12: 0x0000000000000001  x13: 0x0000000000000002  x14: 0x0000000000000000  x15: 0x0000000000006dc2\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   x16: 0x0000000000000006  x17: 0x0000000055800000  x18: 0x0000000000000000  x19: 0x0000000109d900e0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   x20: 0x0000000000000042  x21: 0x0000000171516e80  x22: 0x0000000171516f00  x23: 0x0000000000000000\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   x24: 0x0000000000000000  x25: 0x0000000000000000  x26: 0x0000000000000000  x27: 0x0000000000000000\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   x28: 0x0000000000000000   fp: 0x0000000171516c20   lr: 0x0000000100cceda0\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    sp: 0x0000000171516c00   pc: 0x00000001aa54ae8c cpsr: 0x60000000\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   esr: 0x00000000  Address size fault\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e二进制映像加载信息（截取我们需要的部分）\u003c/p\u003e","title":"iOS崩溃日志定位"},{"content":"用TypeScript开发React项目，在父子组件间传值时发生错误提示\nclass Page extends React.Component { render() { return \u0026lt;div\u0026gt; \u0026lt;NavigationBar title=\u0026#34;标题\u0026#34;/\u0026gt; \u0026lt;/div\u0026gt; } } class NavigationBar extends React.Component { render() { return \u0026lt;div\u0026gt; \u0026#34;返回标题\u0026#34; \u0026lt;/div\u0026gt; } } 错误提示\nNo overload matches this call. Overload 1 of 2, \u0026#39;(props: Readonly\u0026lt;{}\u0026gt;): NavigationBar\u0026#39;, gave the following error. Type \u0026#39;{ title: string; }\u0026#39; is not assignable to type \u0026#39;IntrinsicAttributes \u0026amp; IntrinsicClassAttributes\u0026lt;NavigationBar\u0026gt; \u0026amp; Readonly\u0026lt;{}\u0026gt; \u0026amp; Readonly\u0026lt;{ children?: ReactNode; }\u0026gt;\u0026#39;. Property \u0026#39;title\u0026#39; does not exist on type \u0026#39;IntrinsicAttributes \u0026amp; IntrinsicClassAttributes\u0026lt;NavigationBar\u0026gt; \u0026amp; Readonly\u0026lt;{}\u0026gt; \u0026amp; Readonly\u0026lt;{ children?: ReactNode; }\u0026gt;\u0026#39;. Overload 2 of 2, \u0026#39;(props: {}, context?: any): NavigationBar\u0026#39;, gave the following error. Type \u0026#39;{ title: string; }\u0026#39; is not assignable to type \u0026#39;IntrinsicAttributes \u0026amp; IntrinsicClassAttributes\u0026lt;NavigationBar\u0026gt; \u0026amp; Readonly\u0026lt;{}\u0026gt; \u0026amp; Readonly\u0026lt;{ children?: ReactNode; }\u0026gt;\u0026#39;. Property \u0026#39;title\u0026#39; does not exist on type \u0026#39;IntrinsicAttributes \u0026amp; IntrinsicClassAttributes\u0026lt;NavigationBar\u0026gt; \u0026amp; Readonly\u0026lt;{}\u0026gt; \u0026amp; Readonly\u0026lt;{ children?: ReactNode; }\u0026gt;\u0026#39;. TS2769 原因是Typescript是强类型语言，如果要给组件传值，需要在接受值组的地方声明值类型，就本例而言，需要明确定义 props,本例为 NavigationBarProps\nclass Page extends React.Component { render() { return \u0026lt;div\u0026gt; \u0026lt;NavigationBar title=\u0026#34;标题\u0026#34;/\u0026gt; \u0026lt;/div\u0026gt; } } // 定义props类型 interface NavigationBarProps { title:string; } class NavigationBar extends React.Component\u0026lt;NavigationBarProps\u0026gt; { render() { return \u0026lt;div\u0026gt; \u0026#34;返回标题\u0026#34; \u0026lt;/div\u0026gt; } } ","permalink":"https://blog.z6z8.cn/2020/04/05/ts2769-property-xxx-does-not-exist-on-type-intrinsicattributes-intrinsicclassattributes-readonly-readonly/","summary":"\u003cp\u003e用TypeScript开发React项目，在父子组件间传值时发生错误提示\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-ts\" data-lang=\"ts\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePage\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eReact\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eComponent\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003erender\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u0026lt;\u003cspan style=\"color:#f92672\"\u003eNavigationBar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etitle\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;标题\u0026#34;\u003c/span\u003e/\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eNavigationBar\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eReact\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eComponent\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003erender\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;返回标题\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e错误提示\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eNo overload matches this call.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  Overload \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e of 2, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;(props: Readonly\u0026lt;{}\u0026gt;): NavigationBar\u0026#39;\u003c/span\u003e, gave the following error.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Type \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;{ title: string; }\u0026#39;\u003c/span\u003e is not assignable to type \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;IntrinsicAttributes \u0026amp; IntrinsicClassAttributes\u0026lt;NavigationBar\u0026gt; \u0026amp; Readonly\u0026lt;{}\u0026gt; \u0026amp; Readonly\u0026lt;{ children?: ReactNode; }\u0026gt;\u0026#39;\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      Property \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;title\u0026#39;\u003c/span\u003e does not exist on type \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;IntrinsicAttributes \u0026amp; IntrinsicClassAttributes\u0026lt;NavigationBar\u0026gt; \u0026amp; Readonly\u0026lt;{}\u0026gt; \u0026amp; Readonly\u0026lt;{ children?: ReactNode; }\u0026gt;\u0026#39;\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  Overload \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e of 2, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;(props: {}, context?: any): NavigationBar\u0026#39;\u003c/span\u003e, gave the following error.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Type \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;{ title: string; }\u0026#39;\u003c/span\u003e is not assignable to type \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;IntrinsicAttributes \u0026amp; IntrinsicClassAttributes\u0026lt;NavigationBar\u0026gt; \u0026amp; Readonly\u0026lt;{}\u0026gt; \u0026amp; Readonly\u0026lt;{ children?: ReactNode; }\u0026gt;\u0026#39;\u003c/span\u003e.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      Property \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;title\u0026#39;\u003c/span\u003e does not exist on type \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;IntrinsicAttributes \u0026amp; IntrinsicClassAttributes\u0026lt;NavigationBar\u0026gt; \u0026amp; Readonly\u0026lt;{}\u0026gt; \u0026amp; Readonly\u0026lt;{ children?: ReactNode; }\u0026gt;\u0026#39;\u003c/span\u003e.  TS2769\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e原因是Typescript是强类型语言，如果要给组件传值，需要在接受值组的地方声明值类型，就本例而言，需要明确定义 \u003ccode\u003eprops\u003c/code\u003e,本例为 \u003ccode\u003eNavigationBarProps\u003c/code\u003e\u003c/p\u003e","title":"TS2769: Property 'xxx' does not exist on type 'IntrinsicAttributes \u0026 IntrinsicClassAttributes \u0026 Readonly\u003c{}\u003e \u0026 Readonly\u003c{ children?: ReactNode; }\u003e"},{"content":"# 初始化npm项目 mkdir projectName cd projectName npm init # 初始化TypeScript项目 tsc --init #安装 node的ts符号生命（用于ts的静态编译检查、语法提示） npm i @types/node ","permalink":"https://blog.z6z8.cn/2020/04/05/%E5%9F%BA%E4%BA%8Enpm%E9%A1%B9%E7%9B%AE%E5%88%9D%E5%A7%8B%E5%8C%96typescript%E9%A1%B9%E7%9B%AE/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 初始化npm项目\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir projectName\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd projectName\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm init\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 初始化TypeScript项目\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etsc --init\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#安装 node的ts符号生命（用于ts的静态编译检查、语法提示）\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpm i @types/node\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"基于npm项目初始化TypeScript项目"},{"content":"JavaScript如何实现sleep？ 一般的， sleep 是将当前上下文所在的线程从执行状态转化为挂起状态，直到指定的一段实时时间过去后，再从挂起状态转化为执行状态，在sleep执行结束前，线程不会执行其他任务。\n该函数使当前进程从执行状态转化为挂起状态，直到参数seconds所指定的一段实时时间过去后，或者是一个唤醒信号跟踪功能或终止进程功能的信号到来。该挂起时间由于系统的其他调度活动可能会比要求的时间长。\n在ES标准中，JavaScript代码的执行环境是一个单线程环境，所以 JavaScript如何实现sleep 的本质是如何将一个线程阻塞一段时间然后继续工作。\n这里的重点是 阻塞。所以，使用 promise、 generator 之类的实现是不满足这个需求的，任务调度机制本质不同，因为 promise、 generator 的本质是延迟，而不是阻塞。\n在不扩展JavaScript语言底层能力的情况下，实现阻塞方式：\n计算阻塞 IO阻塞 计算阻塞 也就是消耗CPU资源进行阻塞，通常是一段循环计算，在循环期间，JavaScript代码执行线程不会执行其他任务，从而达到模拟 sleep 的效果\n\u0026lt;script type=\u0026#34;text/javascript\u0026#34;\u0026gt; // bad implementation function sleep(milliSeconds){ var startTime = new Date().getTime(); // get the current time while (new Date().getTime() \u0026lt; startTime + milliSeconds); // hog cpu } } \u0026lt;/script\u0026gt; 这种方式在任何标准的ES环境中都可以实现，阻塞和计时在同一个线程中完成。\nIO阻塞 也就是消耗IO资源进行阻塞，通常是消耗网络IO，如 XMLHttpRequest 的同步通信。\n\u0026lt;script type=\u0026#34;text/javascript\u0026#34;\u0026gt; function sleep(milliSeconds) { var resource; var response; if(typeof ActiveXObject == \u0026#39;undefined\u0026#39;){ resource = new XMLHttpRequest(); } else{ resource = new ActiveXObject(\u0026#34;Microsoft.XMLHTTP\u0026#34;); } try{ resource.open(\u0026#39;GET\u0026#39;, \u0026#39;sleep?milliSeconds=\u0026#39; + milliSeconds, false); resource.send(null); response = resource.responseText; // JavaScript waits for response } catch(e){ alert(e); } } \u0026lt;/script\u0026gt; 这种方式是基于BS模型，Server负责计时，在指定的时间后返回响应，Browser负责阻塞。\n引入扩展阻塞 参考 http://devcheater.com/，还可以引入其他语言能力实现 sleep，如 Java Applet、 Flash的sleep\n","permalink":"https://blog.z6z8.cn/2020/03/30/javascript%E5%A6%82%E4%BD%95%E5%AE%9E%E7%8E%B0sleep%EF%BC%9F/","summary":"\u003ch1 id=\"javascript如何实现sleep\"\u003eJavaScript如何实现sleep？\u003c/h1\u003e\n\u003cp\u003e一般的， \u003ccode\u003esleep\u003c/code\u003e 是将当前上下文所在的线程从执行状态转化为挂起状态，直到指定的一段实时时间过去后，再从挂起状态转化为执行状态，在sleep执行结束前，线程不会执行其他任务。\u003c/p\u003e\n\u003cp\u003e该函数使当前进程从执行状态转化为挂起状态，直到参数seconds所指定的一段实时时间过去后，或者是一个唤醒信号跟踪功能或终止进程功能的信号到来。该挂起时间由于系统的其他调度活动可能会比要求的时间长。\u003c/p\u003e\n\u003cp\u003e在ES标准中，JavaScript代码的执行环境是一个单线程环境，所以 \u003ccode\u003eJavaScript如何实现sleep\u003c/code\u003e 的本质是如何将一个线程阻塞一段时间然后继续工作。\u003c/p\u003e\n\u003cp\u003e这里的重点是 \u003ccode\u003e阻塞\u003c/code\u003e。所以，使用 \u003ccode\u003epromise\u003c/code\u003e、 \u003ccode\u003egenerator\u003c/code\u003e 之类的实现是不满足这个需求的，任务调度机制本质不同，因为 \u003ccode\u003epromise\u003c/code\u003e、 \u003ccode\u003egenerator\u003c/code\u003e 的本质是延迟，而不是阻塞。\u003c/p\u003e\n\u003cp\u003e在不扩展JavaScript语言底层能力的情况下，实现阻塞方式：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e计算阻塞\u003c/li\u003e\n\u003cli\u003eIO阻塞\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"计算阻塞\"\u003e计算阻塞\u003c/h1\u003e\n\u003cp\u003e也就是消耗CPU资源进行阻塞，通常是一段循环计算，在循环期间，JavaScript代码执行线程不会执行其他任务，从而达到模拟 \u003ccode\u003esleep\u003c/code\u003e 的效果\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003escript\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;text/javascript\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// bad implementation\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esleep\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003emilliSeconds\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estartTime\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Date().\u003cspan style=\"color:#a6e22e\"\u003egetTime\u003c/span\u003e(); \u003cspan style=\"color:#75715e\"\u003e// get the current time\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e Date().\u003cspan style=\"color:#a6e22e\"\u003egetTime\u003c/span\u003e() \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estartTime\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emilliSeconds\u003c/span\u003e); \u003cspan style=\"color:#75715e\"\u003e// hog cpu\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/script\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e这种方式在任何标准的ES环境中都可以实现，阻塞和计时在同一个线程中完成。\u003c/p\u003e\n\u003ch1 id=\"io阻塞\"\u003eIO阻塞\u003c/h1\u003e\n\u003cp\u003e也就是消耗IO资源进行阻塞，通常是消耗网络IO，如 \u003ccode\u003eXMLHttpRequest\u003c/code\u003e 的同步通信。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003escript\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;text/javascript\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esleep\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003emilliSeconds\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresource\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresponse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003etypeof\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eActiveXObject\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;undefined\u0026#39;\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresource\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eXMLHttpRequest\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresource\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eActiveXObject\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Microsoft.XMLHTTP\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003etry\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresource\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eopen\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;GET\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;sleep?milliSeconds=\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emilliSeconds\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresource\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esend\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eresponse\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresource\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eresponseText\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e// JavaScript waits for response\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ecatch\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ee\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ealert\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ee\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/script\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e这种方式是基于BS模型，Server负责计时，在指定的时间后返回响应，Browser负责阻塞。\u003c/p\u003e","title":"JavaScript如何实现sleep？"},{"content":"问题 对于Native WebView而言，Andoird/iOS都提供相应的方法/代理监听页面URL的变化。例如，Android可以重写 doUpdateVisitedHistory 方法监听URL变化，iOS可以实现 shouldStartLoadWithRequest、 decidePolicyForNavigationAction 代理监听URL变化\n@Override public boolean shouldOverrideUrlLoading(WebView view, String url) { //此处检测url是否有变化 return super.shouldOverrideUrlLoading(view, url); } //UIWebView - (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType { //此处检测url是否有变化 return YES; } //WKWebView - (void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { //此处检测url是否有变化 decisionHandler(WKNavigationActionPolicyAllow); } 上述技术实现对一些前端应用能正常工作。然而，遇到单页应用（SPA）时，以上方法并不会被触发\u0026ndash;这里涉及单页应用的实现原理，尤其是基于 hash 路由的单页应用，其 前进/后退 的问题更为突出。\n解决思路 对于前端应用而言，如果开发者使用固定的框架，那么在框架的路由层面拦截监听应较为容易做到。但是实际情况是开发者使用的前端框架不确定，甚至开发者连前端框架都不用，所以我们在前端框架层面截获路由器变得不那么容易。\n经过调研，要监听前端页面的URL变化，大致有两种模式：\n定时器模式 观察者模式 定时器模式 定期监测URL是否变化，如100毫秒监测一次，与上次监测值对比来判断URL是否变化。定时器，前端可以使用 setInterval 来实现\nvar oldUrl = window.location.href; setInterval(function(){ if (oldUrl !== window.location.href) { //通知Native Url变化 oldUrl = window.location.href; } },100); 当然，Native也可以开启定时器监测 window.location.href。\n定时器模式的特点是实现简单，适用范围广；缺点也显而易见，监测结果不是十分准确，性能耗用高。而其性能耗用问题在移动端将会放大，故此我们不采用此模式。\n观察者模式 上面提到的 doUpdateVisitedHistory、 shouldStartLoadWithRequest、 decidePolicyForNavigationAction 的实现可以算作观察者模式。\n前面提到，单页应用页面切换在移动端webview的行为表现，并不会每次都通知Native，我们要做的就是通过某种方法来完善这个页面切换的事件通知。\n对于观察者模式，iOS中有KVO（key-value-observing）机制，遍历UIWebView和WKWebView的属性发现：\nWKWebView的 URL 属性能够响应KVO机制，当前端页面（包括单页应用的页面）URL有变化时，KVO机制可以监测到。 UIWebView的 request 属性并不能响应KVO机制，不能用它检测URL变化。也就是说，单纯使用UIWebView的能力接口不能完全监测URL变化 至此，在Native侧建立观察者的思路并不适用所有情况，我们需要再返回前端侧研究下单页应用的URL变化。\n单页应用，通过 hash 或 window.history 可以做到改变URL，使得不刷新页面的情况下重新渲染。我们只要监测 hash 和 window.history，当它们发生变化时去检测URL的变化：\n通过 hash 改变URL，会触发 hashchange 事件。当监听到 hashchange 事件时，去检测URL的变化。\nwindow.history 相关的事件为 popstate。当监听到 popstate 事件时，去检测URL的变化。\nHistory.back()、 History.forward()、 History.go() 会触发 popstate 事件\n另外， History.pushState() 和 History.replaceState() 不会触发 popstate 事件，所以我们要hook这两个方法，以检测URL的变化。\n方案实现 结合以上，最终我们可以采用的可行方案如下 :\nAndroid WebViewiOS UIWebViewiOS WKWebView前端监测 hash 和 window.history，通知Native前端监测 hash 和 window.history，通知NativeNative监测 WKWebView.URL\n注意：上述方案并不是唯一方案，但确实是一个可行方案\nWKWebView监测URL部分实现 //添加观察者 [self addObserver:wkwebview forKeyPath:@\u0026#34;URL\u0026#34; options:NSKeyValueObservingOptionNew context:nil]; //接收观察事件 - (void) observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary\u0026lt;NSKeyValueChangeKey,id\u0026gt; *)change context:(void *)context { //url变化，触发相应动作 } //使用完毕后移除观察者 [self removeObserver:wkwebview forKeyPath:@\u0026#34;URL\u0026#34;]; 前端监测URL部分实现 //监听hash变化 window.addEventListener(\u0026#39;hashchange\u0026#39;,function(event){ //通过bridge通知Native URL变化 }); //监听history变化,popstate只能监听History.back(),History.forward()、History.go() window.addEventListener(\u0026#39;popstate\u0026#39;,function(event){ //通过bridge通知Native URL变化 }); //hook History.pushState() History.replaceState() var _wr = function(type) { var orig = history[type]; return function() { var rv = orig.apply(this, arguments); var e = new Event(\u0026#39;ffpd\u0026#39;+type); e.arguments = arguments; window.dispatchEvent(e); return rv; }; }; history.pushState = _wr(\u0026#39;pushState\u0026#39;); history.replaceState = _wr(\u0026#39;replaceState\u0026#39;); window.addEventListener(\u0026#39;ffpdpushState\u0026#39;,function(event){ //通过bridge通知Native URL变化 }); window.addEventListener(\u0026#39;ffpdreplaceState\u0026#39;,function(event){ //通过bridge通知Native URL变化 }); 参考： https://stackoverflow.com/questions/4570093/how-to-get-notified-about-changes-of-the-history-via-history-pushstate\n","permalink":"https://blog.z6z8.cn/2020/03/19/%E7%A7%BB%E5%8A%A8%E7%AB%AF%E7%9B%91%E5%90%AC%E5%8D%95%E9%A1%B5%E5%BA%94%E7%94%A8%E7%9A%84url%E5%8F%98%E5%8C%96/","summary":"\u003ch1 id=\"问题\"\u003e问题\u003c/h1\u003e\n\u003cp\u003e对于Native WebView而言，Andoird/iOS都提供相应的方法/代理监听页面URL的变化。例如，Android可以重写 \u003ccode\u003edoUpdateVisitedHistory\u003c/code\u003e 方法监听URL变化，iOS可以实现 \u003ccode\u003eshouldStartLoadWithRequest\u003c/code\u003e、 \u003ccode\u003edecidePolicyForNavigationAction\u003c/code\u003e 代理监听URL变化\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003e@Override\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eboolean\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eshouldOverrideUrlLoading\u003c/span\u003e(WebView view, String url) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e//此处检测url是否有变化\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003esuper\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eshouldOverrideUrlLoading\u003c/span\u003e(view, url);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//UIWebView\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e- (\u003cspan style=\"color:#66d9ef\"\u003eBOOL\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003ewebView:\u003c/span\u003e(UIWebView \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)webView \u003cspan style=\"color:#a6e22e\"\u003eshouldStartLoadWithRequest:\u003c/span\u003e(NSURLRequest \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)request \u003cspan style=\"color:#a6e22e\"\u003enavigationType:\u003c/span\u003e(UIWebViewNavigationType)navigationType\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//此处检测url是否有变化\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e YES;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//WKWebView\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e- (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003ewebView:\u003c/span\u003e(WKWebView \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)webView \u003cspan style=\"color:#a6e22e\"\u003edecidePolicyForNavigationAction:\u003c/span\u003e(WKNavigationAction \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)navigationAction \u003cspan style=\"color:#a6e22e\"\u003edecisionHandler:\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e (\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e)(WKNavigationActionPolicy))decisionHandler\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//此处检测url是否有变化\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    decisionHandler(WKNavigationActionPolicyAllow);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e上述技术实现对一些前端应用能正常工作。然而，遇到单页应用（SPA）时，以上方法并不会被触发\u0026ndash;这里涉及单页应用的实现原理，尤其是基于 \u003ccode\u003ehash\u003c/code\u003e 路由的单页应用，其 \u003ccode\u003e前进/后退\u003c/code\u003e 的问题更为突出。\u003c/p\u003e\n\u003ch1 id=\"解决思路\"\u003e解决思路\u003c/h1\u003e\n\u003cp\u003e对于前端应用而言，如果开发者使用固定的框架，那么在框架的路由层面拦截监听应较为容易做到。但是实际情况是开发者使用的前端框架不确定，甚至开发者连前端框架都不用，所以我们在前端框架层面截获路由器变得不那么容易。\u003c/p\u003e\n\u003cp\u003e经过调研，要监听前端页面的URL变化，大致有两种模式：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e定时器模式\u003c/li\u003e\n\u003cli\u003e观察者模式\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"定时器模式\"\u003e定时器模式\u003c/h2\u003e\n\u003cp\u003e定期监测URL是否变化，如100毫秒监测一次，与上次监测值对比来判断URL是否变化。定时器，前端可以使用 \u003ccode\u003esetInterval\u003c/code\u003e 来实现\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-js\" data-lang=\"js\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eoldUrl\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e window.\u003cspan style=\"color:#a6e22e\"\u003elocation\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ehref\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003esetInterval\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eoldUrl\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e window.\u003cspan style=\"color:#a6e22e\"\u003elocation\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ehref\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//通知Native Url变化\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#a6e22e\"\u003eoldUrl\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e window.\u003cspan style=\"color:#a6e22e\"\u003elocation\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ehref\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e},\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e当然，Native也可以开启定时器监测 \u003ccode\u003ewindow.location.href\u003c/code\u003e。\u003c/p\u003e\n\u003cp\u003e定时器模式的特点是实现简单，适用范围广；缺点也显而易见，监测结果不是十分准确，性能耗用高。而其性能耗用问题在移动端将会放大，故此我们不采用此模式。\u003c/p\u003e\n\u003ch2 id=\"观察者模式\"\u003e观察者模式\u003c/h2\u003e\n\u003cp\u003e上面提到的 \u003ccode\u003edoUpdateVisitedHistory\u003c/code\u003e、 \u003ccode\u003eshouldStartLoadWithRequest\u003c/code\u003e、 \u003ccode\u003edecidePolicyForNavigationAction\u003c/code\u003e 的实现可以算作观察者模式。\u003c/p\u003e","title":"移动端监听单页应用的URL变化"},{"content":"No WebAssembly support found. Build with -s WASM=0 to target JavaScript instead. 也就是\nemcc -s WASM=0 c/c++文件 ","permalink":"https://blog.z6z8.cn/2020/03/13/emcc-%E5%B0%86c-c%E7%BC%96%E8%AF%91%E6%88%90%E6%B2%A1%E6%9C%89webassembly%E6%94%AF%E6%8C%81%E7%9A%84javascript/","summary":"\u003cp\u003eNo WebAssembly support found. Build with -s WASM=0 to target JavaScript instead.\n也就是\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eemcc   -s WASM\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e  c/c++文件\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"emcc 将C/C++编译成没有WebAssembly支持的JavaScript"},{"content":"系统 : iOS 13.3.1 机型： iPhone7\ndispatch_async(_jsContextQueue, ^{ JSContext *jscontent = [[JSContext alloc] init]; [UIWebView class]; }); 看代码，按照正常思维理解， [UIWebView class]是无论如何都不应崩溃的。\n起初按照惯性思维去查找僵尸变量，忙活了半天没有定位。 最终定位结果如下： 在没有调用过UIWebView的任何函数时，先在非主线程调用UIWebView方法，则会导致崩溃\n本文的相关代码如下\n#import \u0026#34;ViewController.h\u0026#34; #import \u0026lt;JavaScriptCore/JavaScriptCore.h\u0026gt; @interface ViewController ()\u0026lt;UITableViewDelegate,UITableViewDataSource\u0026gt; { dispatch_queue_t _jsContextQueue; } @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; _jsContextQueue = dispatch_queue_create(\u0026#34;jscontext\u0026#34;, NULL); dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{ dispatch_async(_jsContextQueue, ^{ JSContext *jscontent = [[JSContext alloc] init]; [UIWebView class]; }); }); } @end ","permalink":"https://blog.z6z8.cn/2020/03/10/ios-%E8%AF%A1%E5%BC%82%E7%9A%84%E5%B4%A9%E6%BA%83exc_breakpoint-code1-subcode0x1c5691d2c/","summary":"\u003cp\u003e系统 : iOS 13.3.1\n机型： iPhone7\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2020/03/jscore_uiwebview_crash.png\"\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  dispatch_async(_jsContextQueue, \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        JSContext \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ejscontent \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[JSContext alloc] init];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        [UIWebView \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    });\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e看代码，按照正常思维理解， [UIWebView class]是无论如何都不应崩溃的。\u003c/p\u003e\n\u003cp\u003e起初按照惯性思维去查找僵尸变量，忙活了半天没有定位。\n最终定位结果如下：\n\u003ccode\u003e在没有调用过UIWebView的任何函数时，先在非主线程调用UIWebView方法，则会导致崩溃\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e本文的相关代码如下\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#import \u0026#34;ViewController.h\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#import \u0026lt;JavaScriptCore/JavaScriptCore.h\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@interface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eViewController\u003c/span\u003e ()\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eUITableViewDelegate,UITableViewDataSource\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    dispatch_queue_t _jsContextQueue;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@implementation\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eViewController\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003eviewDidLoad\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [super viewDidLoad];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    _jsContextQueue \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e dispatch_queue_create(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;jscontext\u0026#34;\u003c/span\u003e, NULL);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e NSEC_PER_SEC)), dispatch_get_main_queue(), \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        dispatch_async(_jsContextQueue, \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            JSContext \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ejscontent \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[JSContext alloc] init];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            [UIWebView \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"iOS 诡异的崩溃EXC_BREAKPOINT (code=1, subcode=0x1c5691d2c)"},{"content":"简单的配置代理 # 在 http.conf中设置 #加载 mod_proxy.so LoadModule proxy_module modules/mod_proxy.so #设置代理 ProxyPass /xxx1 https://a.b.c/xxx2 ProxyPassReverse /yyy1 https://a.b.c/yyy2 AH01144 启动后访问服务遇到错误\nAH01144: No protocol handler was valid for the URL /yyy1 (scheme \u0026#39;https\u0026#39;). If you are using a DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule. 原因没有我访问的http服务，代理时也需要加载mod_proxy_http.so\nLoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so AH01961 \u0026amp; AH00961 AH01961: SSL Proxy requested for localhost:80 but not enabled [Hint: SSLProxyEngine] AH00961: HTTPS: failed to enable ssl support for 223.71.128.153:443 (yyy2) 如果是用于测试，那么需要配置SSL，以忽略证书问题。\nSSLProxyEngine On SSLProxyVerify none SSLProxyCheckPeerCN off SSLProxyCheckPeerName off 最后完整的 测试配置\n# 在 http.conf中设置 #加载 mod_proxy.so LoadModule proxy_module modules/mod_proxy.so LoadModule proxy_http_module modules/mod_proxy_http.so #设置代理 ProxyPass /xxx1 https://a.b.c/xxx2 ProxyPassReverse /yyy1 https://a.b.c/yyy2 SSLProxyEngine On SSLProxyVerify none SSLProxyCheckPeerCN off SSLProxyCheckPeerName off ","permalink":"https://blog.z6z8.cn/2020/03/03/apache-%E9%85%8D%E7%BD%AE%E4%BB%A3%E7%90%86%E8%BD%AC%E5%8F%91%E6%97%B6%E9%81%87%E5%88%B0%E7%9A%84%E9%94%99%E8%AF%AF%E8%AE%B0%E5%BD%95/","summary":"\u003ch1 id=\"简单的配置代理\"\u003e简单的配置代理\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 在 http.conf中设置\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#加载 mod_proxy.so\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eLoadModule proxy_module modules/mod_proxy.so\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#设置代理\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eProxyPass   /xxx1   https://a.b.c/xxx2\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eProxyPassReverse  /yyy1  https://a.b.c/yyy2\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"ah01144\"\u003eAH01144\u003c/h1\u003e\n\u003cp\u003e启动后访问服务遇到错误\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e AH01144: No protocol handler was valid for the URL /yyy1 (scheme \u0026#39;https\u0026#39;). If you are using a DSO version of mod_proxy, make sure the proxy submodules are included in the configuration using LoadModule.\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e原因没有我访问的http服务，代理时也需要加载mod_proxy_http.so\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eLoadModule proxy_module modules/mod_proxy.so\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eLoadModule proxy_http_module modules/mod_proxy_http.so\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"ah01961--ah00961\"\u003eAH01961 \u0026amp; AH00961\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAH01961: SSL Proxy requested for localhost:80 but not enabled [Hint: SSLProxyEngine]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAH00961: HTTPS: failed to enable ssl support for 223.71.128.153:443 (yyy2)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003ccode\u003e如果是用于测试\u003c/code\u003e，那么需要配置SSL，以忽略证书问题。\u003c/p\u003e","title":"apache 配置代理转发时遇到的错误记录"},{"content":"1、下载源码\n#克隆git仓库 我在gitee上上传了一份代码https://gitee.com/gm958spanda/wireguard-apple.git git clone https://git.zx2c4.com/wireguard-apple #进入git仓库文件夹 cd wireguard-apple 2、设置 apple team ID :\n#将开发者模版文件复制一份 cp WireGuard/WireGuard/Config/Developer.xcconfig.template WireGuard/WireGuard/Config/Developer.xcconfig #编辑开发者文件（这步骤其实最好用Xcode打开工程文件编辑） $ vim WireGuard/WireGuard/Config/Developer.xcconfig 3、安装swiftlint 和 go\n#先更改文件的访问权限（安装时需要写权限） sudo chown -R $(whoami) /usr/local/lib /usr/local/lib/pkgconfig /usr/local/lib/python3.7/site-packages #安装 brew install swiftlint go 4、用Xcode编译打包 用Xcode打开工程文件 open ./WireGuard/WireGuard.xcodeproj 然后就是常规的编译打包动作了\n文章参考https://git.zx2c4.com/wireguard-apple/about/ 其他平台的客户端参考https://www.wireguard.com/repositories/\n","permalink":"https://blog.z6z8.cn/2020/02/22/%E4%BB%8E%E6%BA%90%E7%A0%81%E7%BC%96%E8%AF%91wireguard-for-ios-and-macos/","summary":"\u003cp\u003e1、下载源码\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#克隆git仓库 我在gitee上上传了一份代码https://gitee.com/gm958spanda/wireguard-apple.git\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone https://git.zx2c4.com/wireguard-apple\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#进入git仓库文件夹\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd wireguard-apple\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e2、设置 apple team ID :\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#将开发者模版文件复制一份\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecp\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWireGuard/WireGuard/Config/Developer.xcconfig.template WireGuard/WireGuard/Config/Developer.xcconfig\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#编辑开发者文件（这步骤其实最好用Xcode打开工程文件编辑）\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ vim WireGuard/WireGuard/Config/Developer.xcconfig\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e3、安装swiftlint 和 go\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#先更改文件的访问权限（安装时需要写权限）\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo chown -R \u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003ewhoami\u003cspan style=\"color:#66d9ef\"\u003e)\u003c/span\u003e /usr/local/lib /usr/local/lib/pkgconfig /usr/local/lib/python3.7/site-packages\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#安装\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebrew install swiftlint go\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e4、用Xcode编译打包\n用Xcode打开工程文件\nopen ./WireGuard/WireGuard.xcodeproj\n然后就是常规的编译打包动作了\u003c/p\u003e\n\u003cp\u003e文章参考https://git.zx2c4.com/wireguard-apple/about/\n其他平台的客户端参考https://www.wireguard.com/repositories/\u003c/p\u003e","title":"从源码编译WireGuard for iOS and macOS"},{"content":"wireguard是一款vpn服务 wireguard.com是官方 脚本连接如下 可用一： https://github.com/angristan/wireguard-install 可用二： https://github.com/teddysun/across/blob/master/wireguard.sh\n客户端安装 客户端参考https://www.wireguard.com/repositories/\n","permalink":"https://blog.z6z8.cn/2020/02/22/%E3%80%90%E8%BD%AC%E3%80%91%E4%B8%80%E9%94%AE%E5%AE%89%E8%A3%85wireguard%E7%9A%84%E8%84%9A%E6%9C%AC/","summary":"\u003cp\u003ewireguard是一款vpn服务\nwireguard.com是官方\n脚本连接如下\n可用一： \u003ca href=\"https://github.com/angristan/wireguard-install\"\u003ehttps://github.com/angristan/wireguard-install\u003c/a\u003e\n可用二： \u003ca href=\"https://github.com/teddysun/across/blob/master/wireguard.sh\"\u003ehttps://github.com/teddysun/across/blob/master/wireguard.sh\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e客户端安装\n客户端参考https://www.wireguard.com/repositories/\u003c/p\u003e","title":"【转】一键安装wireguard的脚本"},{"content":"找个地方记录，有备无患\nwget https://git.io/vpn -O openvpn-install.sh \u0026amp;\u0026amp; bash openvpn-install.sh 转自https://github.com/Nyr/openvpn-install\n","permalink":"https://blog.z6z8.cn/2020/02/22/%E8%BD%AClinux%E4%B8%8A%E7%9A%84openvpn-server%E7%9A%84%E7%AE%A1%E7%90%86%E8%84%9A%E6%9C%AC/","summary":"\u003cp\u003e找个地方记录，有备无患\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ewget https://git.io/vpn -O openvpn-install.sh \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e bash openvpn-install.sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e转自https://github.com/Nyr/openvpn-install\u003c/p\u003e","title":"[转]linux上的openvpn server的管理脚本"},{"content":"我是为了解决访问github越来越不稳定问题。 详细参考https://github.com/pritunl/pritunl\n安装 使用包管理器安装 #mongodb源 sudo tee /etc/yum.repos.d/mongodb-org-4.2.repo \u0026lt;\u0026lt; EOF [mongodb-org-4.2] name=MongoDB Repository baseurl=https://repo.mongodb.org/yum/redhat/7/mongodb-org/4.2/x86_64/ gpgcheck=1 enabled=1 gpgkey=https://www.mongodb.org/static/pgp/server-4.2.asc EOF #pritunl源 sudo tee /etc/yum.repos.d/pritunl.repo \u0026lt;\u0026lt; EOF [pritunl] name=Pritunl Repository baseurl=https://repo.pritunl.com/stable/yum/centos/7/ gpgcheck=1 enabled=1 EOF #安装 sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 7568D9BB55FF9E5287D586017AE645C0CF8E292A gpg --armor --export 7568D9BB55FF9E5287D586017AE645C0CF8E292A \u0026gt; key.tmp; sudo rpm --import key.tmp; rm -f key.tmp sudo yum -y install pritunl mongodb-org #启动父亲 sudo systemctl start mongod pritunl sudo systemctl enable mongod pritunl 从源码安装 如果已经安装了pip，建议先升级pip\npip install --upgrade pip 按照下面的命令一行行敲。\n# 设置pritunl的版本，我用的是1.29.2276.91 export VERSION=X.XX.XX.XX #安装必要基础环境与编译器 sudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm sudo yum -y install git bzr python2 python-devel python-pip net-tools openvpn bridge-utils psmisc gcc-c++ #下载go语言组件 wget https://dl.google.com/go/go1.12.1.linux-amd64.tar.gz sudo tar -C /usr/local -xf go1.12.1.linux-amd64.tar.gz rm -f go1.12.1.linux-amd64.tar.gz #将go写入环境变量 tee -a ~/.bashrc \u0026lt;\u0026lt; EOF export GOPATH=\\$HOME/go export PATH=/usr/local/go/bin:\\$PATH EOF source ~/.bashrc #下载dns，web服务组件 go get -u github.com/pritunl/pritunl-dns go get -u github.com/pritunl/pritunl-web sudo ln -s ~/go/bin/pritunl-dns /usr/bin/pritunl-dns sudo ln -s ~/go/bin/pritunl-web /usr/bin/pritunl-web #下载源码并编译安装 wget https://github.com/pritunl/pritunl/archive/$VERSION.tar.gz tar xf $VERSION.tar.gz cd pritunl-$VERSION python2 setup.py build pip install -r requirements.txt sudo python2 setup.py install #以系统服务形式启动 sudo systemctl daemon-reload sudo systemctl start mongod pritunl sudo systemctl enable mongod pritunl 配置 增加打开文件的上限 #查看上限 sudo lsof -p \u0026lt;code\u0026gt;pgrep pritunl-web\u0026lt;/code\u0026gt; | wc -l` #修改 sudo sh -c \u0026#39;echo \u0026#34;* hard nofile 64000\u0026#34; \u0026gt;\u0026gt; /etc/security/limits.conf\u0026#39; sudo sh -c \u0026#39;echo \u0026#34;* soft nofile 64000\u0026#34; \u0026gt;\u0026gt; /etc/security/limits.conf\u0026#39; sudo sh -c \u0026#39;echo \u0026#34;root hard nofile 64000\u0026#34; \u0026gt;\u0026gt; /etc/security/limits.conf\u0026#39; sudo sh -c \u0026#39;echo \u0026#34;root soft nofile 64000\u0026#34; \u0026gt;\u0026gt; /etc/security/limits.conf\u0026#39; 修改web服务端口为943 修改pritunl web服务的端口为943（其他没有被占用的端口都行）,并将943端口添加到防火墙白名单中\n#修改下面文件中的port字段 nano /etc/pritunl.conf #添加到防火墙白名单中 943端口/tcp协议 firewall-cmd --permanent --add-port=943/tcp #重启防火墙(修改配置后要重启防火墙) firewall-cmd --reload 访问pritunl web服务 需要填写mongdb的地址和setup key，其中mongdb的地址默认填写好的。setup key使用如下命令获取\npritunl setup-key 填好后，保存。\npritunl web服务的默认用户和密码 默认用户 pritunl 默认密码 使用 sudo pritunl default-password 获取\n","permalink":"https://blog.z6z8.cn/2020/02/22/%E5%9C%A8centos7%E4%B8%8A%E5%AE%89%E8%A3%85pritunl-%E5%9F%BA%E4%BA%8Eopenvpn%E5%8D%8F%E8%AE%AE%E6%9E%84%E5%BB%BA%E7%9A%84%E6%9C%8D%E5%8A%A1%E5%99%A8/","summary":"\u003cp\u003e我是为了解决访问github越来越不稳定问题。\n详细参考https://github.com/pritunl/pritunl\u003c/p\u003e\n\u003ch1 id=\"安装\"\u003e安装\u003c/h1\u003e\n\u003ch2 id=\"使用包管理器安装\"\u003e使用包管理器安装\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#mongodb源\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo tee /etc/yum.repos.d/mongodb-org-4.2.repo \u003cspan style=\"color:#e6db74\"\u003e\u0026lt;\u0026lt; EOF\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e[mongodb-org-4.2]\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003ename=MongoDB Repository\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003ebaseurl=https://repo.mongodb.org/yum/redhat/7/mongodb-org/4.2/x86_64/\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003egpgcheck=1\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003eenabled=1\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003egpgkey=https://www.mongodb.org/static/pgp/server-4.2.asc\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003eEOF\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#pritunl源\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo tee /etc/yum.repos.d/pritunl.repo \u003cspan style=\"color:#e6db74\"\u003e\u0026lt;\u0026lt; EOF\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e[pritunl]\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003ename=Pritunl Repository\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003ebaseurl=https://repo.pritunl.com/stable/yum/centos/7/\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003egpgcheck=1\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003eenabled=1\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003eEOF\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#安装\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo rpm -Uvh https://dl.fedoraproject.org/pub/epel/epel-release-latest-7.noarch.rpm\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egpg --keyserver hkp://keyserver.ubuntu.com --recv-keys 7568D9BB55FF9E5287D586017AE645C0CF8E292A\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egpg --armor --export 7568D9BB55FF9E5287D586017AE645C0CF8E292A \u0026gt; key.tmp; sudo rpm --import key.tmp; rm -f key.tmp\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo yum -y install pritunl mongodb-org\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#启动父亲\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl start mongod pritunl\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl enable mongod pritunl\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"从源码安装\"\u003e从源码安装\u003c/h2\u003e\n\u003cp\u003e如果已经安装了pip，建议先升级pip\u003c/p\u003e","title":"在centos7上安装pritunl--基于OpenVPN协议构建的服务器"},{"content":"let colorNameMap = { aliceblue : \u0026#39;#f0f8ff\u0026#39;, antiquewhite : \u0026#39;#faebd7\u0026#39;, aqua : \u0026#39;#00ffff\u0026#39;, aquamarine : \u0026#39;#7fffd4\u0026#39;, azure : \u0026#39;#f0ffff\u0026#39;, beige : \u0026#39;#f5f5dc\u0026#39;, bisque : \u0026#39;#ffe4c4\u0026#39;, black : \u0026#39;#000000\u0026#39;, blanchedalmond : \u0026#39;#ffebcd\u0026#39;, blue : \u0026#39;#0000ff\u0026#39;, blueviolet : \u0026#39;#8a2be2\u0026#39;, brown : \u0026#39;#a52a2a\u0026#39;, burlywood : \u0026#39;#deb887\u0026#39;, cadetblue : \u0026#39;#5f9ea0\u0026#39;, chartreuse : \u0026#39;#7fff00\u0026#39;, chocolate : \u0026#39;#d2691e\u0026#39;, coral : \u0026#39;#ff7f50\u0026#39;, cornflowerblue : \u0026#39;#6495ed\u0026#39;, cornsilk : \u0026#39;#fff8dc\u0026#39;, crimson : \u0026#39;#dc143c\u0026#39;, cyan : \u0026#39;#00ffff\u0026#39;, darkblue : \u0026#39;#00008b\u0026#39;, darkcyan : \u0026#39;#008b8b\u0026#39;, darkgoldenrod : \u0026#39;#b8860b\u0026#39;, darkgray : \u0026#39;#a9a9a9\u0026#39;, darkgrey : \u0026#39;#a9a9a9\u0026#39;, darkgreen : \u0026#39;#006400\u0026#39;, darkkhaki : \u0026#39;#bdb76b\u0026#39;, darkmagenta : \u0026#39;#8b008b\u0026#39;, darkolivegreen : \u0026#39;#556b2f\u0026#39;, darkorange : \u0026#39;#ff8c00\u0026#39;, darkorchid : \u0026#39;#9932cc\u0026#39;, darkred : \u0026#39;#8b0000\u0026#39;, darksalmon : \u0026#39;#e9967a\u0026#39;, darkseagreen : \u0026#39;#8fbc8f\u0026#39;, darkslateblue : \u0026#39;#483d8b\u0026#39;, darkslategray : \u0026#39;#2f4f4f\u0026#39;, darkslategrey : \u0026#39;#2f4f4f\u0026#39;, darkturquoise : \u0026#39;#00ced1\u0026#39;, darkviolet : \u0026#39;#9400d3\u0026#39;, deeppink : \u0026#39;#ff1493\u0026#39;, deepskyblue : \u0026#39;#00bfff\u0026#39;, dimgray : \u0026#39;#696969\u0026#39;, dimgrey : \u0026#39;#696969\u0026#39;, dodgerblue : \u0026#39;#1e90ff\u0026#39;, firebrick : \u0026#39;#b22222\u0026#39;, floralwhite : \u0026#39;#fffaf0\u0026#39;, forestgreen : \u0026#39;#228b22\u0026#39;, fuchsia : \u0026#39;#ff00ff\u0026#39;, gainsboro : \u0026#39;#dcdcdc\u0026#39;, ghostwhite : \u0026#39;#f8f8ff\u0026#39;, gold : \u0026#39;#ffd700\u0026#39;, goldenrod : \u0026#39;#daa520\u0026#39;, gray : \u0026#39;#808080\u0026#39;, grey : \u0026#39;#808080\u0026#39;, green : \u0026#39;#008000\u0026#39;, greenyellow : \u0026#39;#adff2f\u0026#39;, honeydew : \u0026#39;#f0fff0\u0026#39;, hotpink : \u0026#39;#ff69b4\u0026#39;, indianred : \u0026#39;#cd5c5c\u0026#39;, indigo : \u0026#39;#4b0082\u0026#39;, ivory : \u0026#39;#fffff0\u0026#39;, khaki : \u0026#39;#f0e68c\u0026#39;, lavender : \u0026#39;#e6e6fa\u0026#39;, lavenderblush : \u0026#39;#fff0f5\u0026#39;, lawngreen : \u0026#39;#7cfc00\u0026#39;, lemonchiffon : \u0026#39;#fffacd\u0026#39;, lightblue : \u0026#39;#add8e6\u0026#39;, lightcoral : \u0026#39;#f08080\u0026#39;, lightcyan : \u0026#39;#e0ffff\u0026#39;, lightgoldenrodyellow : \u0026#39;#fafad2\u0026#39;, lightgray : \u0026#39;#d3d3d3\u0026#39;, lightgrey : \u0026#39;#d3d3d3\u0026#39;, lightgreen : \u0026#39;#90ee90\u0026#39;, lightpink : \u0026#39;#ffb6c1\u0026#39;, lightsalmon : \u0026#39;#ffa07a\u0026#39;, lightseagreen : \u0026#39;#20b2aa\u0026#39;, lightskyblue : \u0026#39;#87cefa\u0026#39;, lightslategray : \u0026#39;#778899\u0026#39;, lightslategrey : \u0026#39;#778899\u0026#39;, lightsteelblue : \u0026#39;#b0c4de\u0026#39;, lightyellow : \u0026#39;#ffffe0\u0026#39;, lime : \u0026#39;#00ff00\u0026#39;, limegreen : \u0026#39;#32cd32\u0026#39;, linen : \u0026#39;#faf0e6\u0026#39;, magenta : \u0026#39;#ff00ff\u0026#39;, maroon : \u0026#39;#800000\u0026#39;, mediumaquamarine : \u0026#39;#66cdaa\u0026#39;, mediumblue : \u0026#39;#0000cd\u0026#39;, mediumorchid : \u0026#39;#ba55d3\u0026#39;, mediumpurple : \u0026#39;#9370db\u0026#39;, mediumseagreen : \u0026#39;#3cb371\u0026#39;, mediumslateblue : \u0026#39;#7b68ee\u0026#39;, mediumspringgreen : \u0026#39;#00fa9a\u0026#39;, mediumturquoise : \u0026#39;#48d1cc\u0026#39;, mediumvioletred : \u0026#39;#c71585\u0026#39;, midnightblue : \u0026#39;#191970\u0026#39;, mintcream : \u0026#39;#f5fffa\u0026#39;, mistyrose : \u0026#39;#ffe4e1\u0026#39;, moccasin : \u0026#39;#ffe4b5\u0026#39;, navajowhite : \u0026#39;#ffdead\u0026#39;, navy : \u0026#39;#000080\u0026#39;, oldlace : \u0026#39;#fdf5e6\u0026#39;, olive : \u0026#39;#808000\u0026#39;, olivedrab : \u0026#39;#6b8e23\u0026#39;, orange : \u0026#39;#ffa500\u0026#39;, orangered : \u0026#39;#ff4500\u0026#39;, orchid : \u0026#39;#da70d6\u0026#39;, palegoldenrod : \u0026#39;#eee8aa\u0026#39;, palegreen : \u0026#39;#98fb98\u0026#39;, paleturquoise : \u0026#39;#afeeee\u0026#39;, palevioletred : \u0026#39;#db7093\u0026#39;, papayawhip : \u0026#39;#ffefd5\u0026#39;, peachpuff : \u0026#39;#ffdab9\u0026#39;, peru : \u0026#39;#cd853f\u0026#39;, pink : \u0026#39;#ffc0cb\u0026#39;, plum : \u0026#39;#dda0dd\u0026#39;, powderblue : \u0026#39;#b0e0e6\u0026#39;, purple : \u0026#39;#800080\u0026#39;, rebeccapurple : \u0026#39;#663399\u0026#39;, red : \u0026#39;#ff0000\u0026#39;, rosybrown : \u0026#39;#bc8f8f\u0026#39;, royalblue : \u0026#39;#4169e1\u0026#39;, saddlebrown : \u0026#39;#8b4513\u0026#39;, salmon : \u0026#39;#fa8072\u0026#39;, sandybrown : \u0026#39;#f4a460\u0026#39;, seagreen : \u0026#39;#2e8b57\u0026#39;, seashell : \u0026#39;#fff5ee\u0026#39;, sienna : \u0026#39;#a0522d\u0026#39;, silver : \u0026#39;#c0c0c0\u0026#39;, skyblue : \u0026#39;#87ceeb\u0026#39;, slateblue : \u0026#39;#6a5acd\u0026#39;, slategray : \u0026#39;#708090\u0026#39;, slategrey : \u0026#39;#708090\u0026#39;, snow : \u0026#39;#fffafa\u0026#39;, springgreen : \u0026#39;#00ff7f\u0026#39;, steelblue : \u0026#39;#4682b4\u0026#39;, tan : \u0026#39;#d2b48c\u0026#39;, teal : \u0026#39;#008080\u0026#39;, thistle : \u0026#39;#d8bfd8\u0026#39;, tomato : \u0026#39;#ff6347\u0026#39;, turquoise : \u0026#39;#40e0d0\u0026#39;, violet : \u0026#39;#ee82ee\u0026#39;, wheat : \u0026#39;#f5deb3\u0026#39;, white : \u0026#39;#ffffff\u0026#39;, whitesmoke : \u0026#39;#f5f5f5\u0026#39;, yellow : \u0026#39;#ffff00\u0026#39;, yellowgreen : \u0026#39;#9acd32\u0026#39;, } // 5种模式 全部转换程 \u0026#39;RRGGBBAA\u0026#39;的小写表示 // 1、颜色名，如\u0026#39;red\u0026#39;，\u0026#39;black\u0026#39; // 2、三位十六进制，如\u0026#39;#fba\u0026#39; // 3、六位十六进制, 如\u0026#39;#ffbbaa\u0026#39; // 4、rgb ,如rgb(255,220,123) // 5、rgba，如rgba(255,220,123,30) function convertStringToHexColor(colorStr) { let BLACK = \u0026#39;000000ff\u0026#39; if (typeof colorStr !== \u0026#39;string\u0026#39; || colorStr.length \u0026lt;= 1) { return BLACK; //非法，返回黑色 } colorStr = colorStr.toLowerCase(); if ( colorStr.slice(0,1) === \u0026#39;#\u0026#39;) //十六进制 { colorStr = colorStr.slice(1) if(colorStr.length \u0026lt; 4) //三位 FFF { if(colorStr.length \u0026lt; 3){ colorStr = (\u0026#39;000\u0026#39; + colorStr).slice(-3); } return colorStr.charAt(0).concat(colorStr.charAt(0), colorStr.charAt(1), colorStr.charAt(1), colorStr.charAt(2), colorStr.charAt(2), \u0026#39;ff\u0026#39;); } else //六位 ffbbaa { if(colorStr.length \u0026lt; 3){ colorStr = (\u0026#39;000000\u0026#39; + colorStr).slice(-6); } return colorStr + \u0026#39;ff\u0026#39;; } } else if ( colorStr.length \u0026gt; 4 \u0026amp;\u0026amp; colorStr.slice(0,4) === \u0026#39;rgba\u0026#39;) // rgba(1,2,3,4) { let start = colorStr.indexOf(\u0026#39;(\u0026#39;); let end = colorStr.indexOf(\u0026#39;)\u0026#39;); if (start === -1 || end === -1 || (start+1) \u0026gt;= end ) { return BLACK } rgb = colorStr.slice(start + 1,end).split(\u0026#39;,\u0026#39;); if (rgb.length !== 4) { return BLACK; } return \u0026#39;\u0026#39;.concat(parseInt(rgb[0]).toString(16).slice(-2), parseInt(rgb[1]).toString(16).slice(-2), parseInt(rgb[2]).toString(16).slice(-2), parseInt(rgb[3]).toString(16).slice(-2)); } else if ( colorStr.length \u0026gt; 3 \u0026amp;\u0026amp; colorStr.slice(0,3) === \u0026#39;rgb\u0026#39; ) //rgb(1,2,3) { let start = colorStr.indexOf(\u0026#39;(\u0026#39;); let end = colorStr.indexOf(\u0026#39;)\u0026#39;); if (start === -1 || end === -1 || (start+1) \u0026gt;= end ) { return BLACK } rgb = colorStr.slice(start + 1,end).split(\u0026#39;,\u0026#39;); if (rgb.length !== 3) { return BLACK; } return \u0026#39;\u0026#39;.concat(parseInt(rgb[0]).toString(16).slice(-2), parseInt(rgb[1]).toString(16).slice(-2), parseInt(rgb[2]).toString(16).slice(-2), \u0026#39;ff\u0026#39;); } else if (colorNameMap[colorStr] !== undefined) { colorStr = colorNameMap[colorStr].slice(1); return colorStr + \u0026#39;ff\u0026#39;; } else{ return BLACK; //非法，返回黑色 } } console.log(convertStringToHexColor(\u0026#39;\u0026#39;)) console.log(convertStringToHexColor(\u0026#39;#\u0026#39;)) console.log(convertStringToHexColor(\u0026#39;red\u0026#39;)) console.log(convertStringToHexColor(\u0026#39;#FBA\u0026#39;)) console.log(convertStringToHexColor(\u0026#39;#FFBBAA\u0026#39;)) console.log(convertStringToHexColor(\u0026#39;rgb(255,254,253)\u0026#39;)) console.log(convertStringToHexColor(\u0026#39;rgba(255,254,253,100)\u0026#39;)) ","permalink":"https://blog.z6z8.cn/2020/02/15/js-%E5%B0%86html%E7%9A%845%E7%A7%8D%E9%A2%9C%E8%89%B2%E8%A1%A8%E7%A4%BA%EF%BC%8C%E8%A7%A3%E6%9E%90%E4%B8%BArrggbbaa/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorNameMap\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ealiceblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#f0f8ff\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eantiquewhite\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#faebd7\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eaqua\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#00ffff\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eaquamarine\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#7fffd4\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eazure\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#f0ffff\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ebeige\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#f5f5dc\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ebisque\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffe4c4\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eblack\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#000000\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eblanchedalmond\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffebcd\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#0000ff\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eblueviolet\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#8a2be2\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ebrown\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#a52a2a\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eburlywood\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#deb887\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecadetblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#5f9ea0\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003echartreuse\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#7fff00\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003echocolate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#d2691e\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecoral\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ff7f50\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecornflowerblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#6495ed\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecornsilk\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#fff8dc\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecrimson\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#dc143c\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ecyan\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#00ffff\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#00008b\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkcyan\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#008b8b\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkgoldenrod\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#b8860b\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkgray\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#a9a9a9\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkgrey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#a9a9a9\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkgreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#006400\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkkhaki\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#bdb76b\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkmagenta\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#8b008b\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkolivegreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#556b2f\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkorange\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ff8c00\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkorchid\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#9932cc\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkred\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#8b0000\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarksalmon\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#e9967a\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkseagreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#8fbc8f\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkslateblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#483d8b\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkslategray\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#2f4f4f\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkslategrey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#2f4f4f\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkturquoise\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#00ced1\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edarkviolet\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#9400d3\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edeeppink\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ff1493\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edeepskyblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#00bfff\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edimgray\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#696969\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edimgrey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#696969\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003edodgerblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#1e90ff\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003efirebrick\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#b22222\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003efloralwhite\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#fffaf0\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eforestgreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#228b22\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003efuchsia\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ff00ff\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003egainsboro\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#dcdcdc\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eghostwhite\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#f8f8ff\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003egold\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffd700\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003egoldenrod\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#daa520\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003egray\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#808080\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003egrey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#808080\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003egreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#008000\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003egreenyellow\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#adff2f\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ehoneydew\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#f0fff0\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ehotpink\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ff69b4\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eindianred\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#cd5c5c\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eindigo\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#4b0082\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eivory\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#fffff0\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ekhaki\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#f0e68c\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elavender\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#e6e6fa\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elavenderblush\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#fff0f5\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elawngreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#7cfc00\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elemonchiffon\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#fffacd\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#add8e6\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightcoral\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#f08080\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightcyan\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#e0ffff\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightgoldenrodyellow\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#fafad2\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightgray\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#d3d3d3\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightgrey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#d3d3d3\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightgreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#90ee90\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightpink\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffb6c1\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightsalmon\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffa07a\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightseagreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#20b2aa\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightskyblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#87cefa\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightslategray\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#778899\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightslategrey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#778899\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightsteelblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#b0c4de\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elightyellow\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffffe0\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elime\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#00ff00\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elimegreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#32cd32\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003elinen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#faf0e6\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emagenta\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ff00ff\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emaroon\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#800000\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emediumaquamarine\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#66cdaa\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emediumblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#0000cd\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emediumorchid\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ba55d3\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emediumpurple\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#9370db\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emediumseagreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#3cb371\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emediumslateblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#7b68ee\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emediumspringgreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#00fa9a\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emediumturquoise\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#48d1cc\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emediumvioletred\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#c71585\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emidnightblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#191970\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emintcream\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#f5fffa\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emistyrose\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffe4e1\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003emoccasin\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffe4b5\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003enavajowhite\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffdead\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003enavy\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#000080\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eoldlace\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#fdf5e6\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eolive\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#808000\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eolivedrab\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#6b8e23\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eorange\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffa500\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eorangered\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ff4500\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eorchid\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#da70d6\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003epalegoldenrod\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#eee8aa\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003epalegreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#98fb98\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003epaleturquoise\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#afeeee\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003epalevioletred\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#db7093\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003epapayawhip\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffefd5\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003epeachpuff\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffdab9\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eperu\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#cd853f\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003epink\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffc0cb\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eplum\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#dda0dd\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003epowderblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#b0e0e6\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003epurple\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#800080\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003erebeccapurple\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#663399\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ered\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ff0000\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003erosybrown\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#bc8f8f\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eroyalblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#4169e1\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esaddlebrown\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#8b4513\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esalmon\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#fa8072\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esandybrown\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#f4a460\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eseagreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#2e8b57\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eseashell\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#fff5ee\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esienna\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#a0522d\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esilver\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#c0c0c0\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eskyblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#87ceeb\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eslateblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#6a5acd\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eslategray\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#708090\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eslategrey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#708090\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esnow\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#fffafa\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003espringgreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#00ff7f\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003esteelblue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#4682b4\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003etan\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#d2b48c\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eteal\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#008080\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ethistle\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#d8bfd8\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003etomato\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ff6347\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eturquoise\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#40e0d0\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eviolet\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ee82ee\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ewheat\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#f5deb3\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ewhite\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffffff\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ewhitesmoke\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#f5f5f5\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eyellow\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#ffff00\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eyellowgreen\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#9acd32\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 5种模式 全部转换程 \u0026#39;RRGGBBAA\u0026#39;的小写表示\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 1、颜色名，如\u0026#39;red\u0026#39;，\u0026#39;black\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 2、三位十六进制，如\u0026#39;#fba\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 3、六位十六进制, 如\u0026#39;#ffbbaa\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 4、rgb ,如rgb(255,220,123)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 5、rgba，如rgba(255,220,123,30)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econvertStringToHexColor\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBLACK\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;000000ff\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003etypeof\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;string\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBLACK\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e//非法，返回黑色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003etoLowerCase\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e) \u003cspan style=\"color:#75715e\"\u003e//十六进制\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e) \u003cspan style=\"color:#75715e\"\u003e//三位 FFF\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;000\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003echarAt\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003econcat\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003echarAt\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003echarAt\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003echarAt\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003echarAt\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003echarAt\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                                            \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;ff\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e//六位 ffbbaa\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;000000\u0026#39;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e6\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;ff\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;rgba\u0026#39;\u003c/span\u003e)  \u003cspan style=\"color:#75715e\"\u003e// rgba(1,2,3,4)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estart\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eindexOf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;(\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eend\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eindexOf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;)\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003estart\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eend\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003estart\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eend\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBLACK\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ergb\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003estart\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003eend\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003esplit\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;,\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003ergb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBLACK\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#39;\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003econcat\u003c/span\u003e(parseInt(\u003cspan style=\"color:#a6e22e\"\u003ergb\u003c/span\u003e[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e]).\u003cspan style=\"color:#a6e22e\"\u003etoString\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                         parseInt(\u003cspan style=\"color:#a6e22e\"\u003ergb\u003c/span\u003e[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e]).\u003cspan style=\"color:#a6e22e\"\u003etoString\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                         parseInt(\u003cspan style=\"color:#a6e22e\"\u003ergb\u003c/span\u003e[\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e]).\u003cspan style=\"color:#a6e22e\"\u003etoString\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                         parseInt(\u003cspan style=\"color:#a6e22e\"\u003ergb\u003c/span\u003e[\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e]).\u003cspan style=\"color:#a6e22e\"\u003etoString\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e,\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;rgb\u0026#39;\u003c/span\u003e ) \u003cspan style=\"color:#75715e\"\u003e//rgb(1,2,3)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estart\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eindexOf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;(\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eend\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eindexOf\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;)\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003estart\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eend\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003estart\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eend\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBLACK\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ergb\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003estart\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003eend\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003esplit\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;,\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003ergb\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBLACK\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#39;\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003econcat\u003c/span\u003e(parseInt(\u003cspan style=\"color:#a6e22e\"\u003ergb\u003c/span\u003e[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e]).\u003cspan style=\"color:#a6e22e\"\u003etoString\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        parseInt(\u003cspan style=\"color:#a6e22e\"\u003ergb\u003c/span\u003e[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e]).\u003cspan style=\"color:#a6e22e\"\u003etoString\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        parseInt(\u003cspan style=\"color:#a6e22e\"\u003ergb\u003c/span\u003e[\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e]).\u003cspan style=\"color:#a6e22e\"\u003etoString\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e).\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;ff\u0026#39;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003ecolorNameMap\u003c/span\u003e[\u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eundefined\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorNameMap\u003c/span\u003e[\u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e].\u003cspan style=\"color:#a6e22e\"\u003eslice\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecolorStr\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;ff\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBLACK\u003c/span\u003e;  \u003cspan style=\"color:#75715e\"\u003e//非法，返回黑色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003econvertStringToHexColor\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#39;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003econvertStringToHexColor\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#\u0026#39;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003econvertStringToHexColor\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;red\u0026#39;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003econvertStringToHexColor\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#FBA\u0026#39;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003econvertStringToHexColor\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;#FFBBAA\u0026#39;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003econvertStringToHexColor\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;rgb(255,254,253)\u0026#39;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003econvertStringToHexColor\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;rgba(255,254,253,100)\u0026#39;\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"JS 将html的5种颜色表示，解析为RRGGBBAA"},{"content":"环境:\niOS 13.2 + WKWebView 现象一： 当不添加 viewport 时,onfocus被触发一次\n\u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;script\u0026gt; function onfocus123(e){ console.log(456); } \u0026lt;/script\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;span\u0026gt;test_input\u0026lt;/span\u0026gt; \u0026lt;input id=\u0026#34;test_input\u0026#34; type=\u0026#34;text\u0026#34; onfocus=\u0026#34;onfocus123(event)\u0026#34;\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; 第一次点击input输入框第二次点击input输入框输出：456输出: 456\n现象一： 当添加 viewport 时,onfocus被触发两次\n\u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;script\u0026gt; function onfocus123(e){ console.log(456); } \u0026lt;/script\u0026gt; \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width, initial-scale=1.0,maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover,user-scalable=no\u0026#34;\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;span\u0026gt;test_input\u0026lt;/span\u0026gt; \u0026lt;input id=\u0026#34;test_input\u0026#34; type=\u0026#34;text\u0026#34; onfocus=\u0026#34;onfocus123(event)\u0026#34;\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; 第一次点击input输入框第二次点击input输入框输出：456 456输出: 456\n暂时没有比较好的解决办法。\n另，参考https://patrickhlauke.github.io/touch/tests/results/，\nThere is some oddity/bug in iOS 12.2, with , and being fired twice when first tapping on the control. The experimental WebKit feature for pointer events also generates some duplicate pointerup events. 可知，基于WebKit的浏览器如WKWebView,Safari，在一些版本上（如12.2）会有奇怪的bug,事件 mousedown、 mouseup、 click 在第一次进入控件时会被触发两次。\n其他相关讨论可见https://greensock.com/forums/topic/21397-ios-13-safariwkwebview-draggable-double-dispatching-click-events/\n","permalink":"https://blog.z6z8.cn/2020/02/11/html%E7%9A%84input%E6%8E%A7%E4%BB%B6%E7%9A%84onfocus%E4%BA%8B%E4%BB%B6%E8%A2%AB%E8%A7%A6%E5%8F%91%E4%BA%86%E4%B8%A4%E6%AC%A1/","summary":"\u003cp\u003e环境:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eiOS 13.2 + WKWebView\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e现象一：\n当不添加 \u003ccode\u003eviewport\u003c/code\u003e 时,onfocus被触发一次\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u0026lt;!DOCTYPE html\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003ehtml\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003ehead\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eonfocus123\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ee\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e456\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;/\u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ehead\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003espan\u003c/span\u003e\u0026gt;test_input\u0026lt;/\u003cspan style=\"color:#f92672\"\u003espan\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003einput\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test_input\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;text\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eonfocus\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;onfocus123(event)\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ehtml\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e第一次点击input输入框第二次点击input输入框输出：456输出: 456\u003c/p\u003e\n\u003cp\u003e现象一：\n当添加 \u003ccode\u003eviewport\u003c/code\u003e 时,onfocus被触发两次\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u0026lt;!DOCTYPE html\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003ehtml\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003ehead\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eonfocus123\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ee\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elog\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e456\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;/\u003cspan style=\"color:#f92672\"\u003escript\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003emeta\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;viewport\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econtent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;width=device-width, initial-scale=1.0,maximum-scale=1.0, minimum-scale=1.0, viewport-fit=cover,user-scalable=no\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ehead\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003espan\u003c/span\u003e\u0026gt;test_input\u0026lt;/\u003cspan style=\"color:#f92672\"\u003espan\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003einput\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test_input\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;text\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eonfocus\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;onfocus123(event)\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ehtml\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e第一次点击input输入框第二次点击input输入框输出：456 456输出: 456\u003c/p\u003e","title":"WKWebView ： html的input控件的onfocus事件被触发了两次"},{"content":"主要是两个命令 查看所有操作日志\ngit reflog #注意，不是 git log 根据日志，找到对应的操作id,然后恢复\ngit reset id # 例如 git reset 20b6e99 这个恢复操作会在当前分支进行，建新建个临时分支进行恢复。\n恢复的原理有点类似windows的回收站，git也有个垃圾数据区。\n","permalink":"https://blog.z6z8.cn/2020/02/06/%E4%BB%8Egit%E6%93%8D%E4%BD%9C%E6%97%A5%E5%BF%97%E4%B8%AD%E6%81%A2%E5%A4%8D%E8%AF%AF%E6%93%8D%E4%BD%9C/","summary":"\u003cp\u003e主要是两个命令\n查看所有操作日志\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit reflog  \u003cspan style=\"color:#75715e\"\u003e#注意，不是 git log\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e根据日志，找到对应的操作id,然后恢复\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit reset id # 例如 git reset 20b6e99\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e这个恢复操作会在当前分支进行，建新建个临时分支进行恢复。\u003c/p\u003e\n\u003cp\u003e恢复的原理有点类似windows的回收站，git也有个垃圾数据区。\u003c/p\u003e","title":"从git操作日志中恢复误操作"},{"content":"apt update \u0026amp;\u0026amp; apt -y install ca-certificates wget net-tools wget -qO - https://as-repository.openvpn.net/as-repo-public.gpg | apt-key add - echo \u0026#34;deb http://as-repository.openvpn.net/as/debian bionic main\u0026#34;\u0026gt;/etc/apt/sources.list.d/openvpn-as-repo.list apt update \u0026amp;\u0026amp; apt -y install openvpn-as 参考 https://openvpn.net/vpn-software-packages/\n","permalink":"https://blog.z6z8.cn/2020/02/05/ubuntu-18-04-%E5%AE%89%E8%A3%85openvpn-access-server/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt update \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e apt -y install ca-certificates wget net-tools\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ewget -qO - https://as-repository.openvpn.net/as-repo-public.gpg | apt-key add -\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;deb http://as-repository.openvpn.net/as/debian bionic main\u0026#34;\u003c/span\u003e\u0026gt;/etc/apt/sources.list.d/openvpn-as-repo.list\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eapt update \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e apt -y install openvpn-as\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e参考 \u003ca href=\"https://openvpn.net/vpn-software-packages/\"\u003ehttps://openvpn.net/vpn-software-packages/\u003c/a\u003e\u003c/p\u003e","title":"ubuntu 18.04 : 安装openvpn access server"},{"content":"仓库权限只能由仓库的所有者维护（所有者可以是多个用户）。\nMutable：拥有可以通过控制面板更改的权限 Specified：Mutable + 所有者 Effective：Specified +正则表达式，管理员等\nRepo permissions can only be maintained by an owner of the repo. If you are not the owner, it will appear to let you change the permissions, but actually fail silently\n支持上述说法的 代码片段\npublic class RegistrantPermissionsPanel extends BasePanel { private static final long serialVersionUID = 1L; public enum Show { specified, mutable, effective; public boolean show(RegistrantAccessPermission ap) { switch (this) { case specified: return ap.mutable || ap.isOwner(); case mutable: return ap.mutable; case effective: return true; default: return true; } } } private Show activeState = Show.mutable; 参考 1、 https://issue.life/questions/34595235\n","permalink":"https://blog.z6z8.cn/2020/02/04/gitblit-%E4%BB%93%E5%BA%93%E6%9D%83%E9%99%90-mutable-specified-%E5%92%8C-effective-%E7%9A%84%E5%8C%BA%E5%88%AB/","summary":"\u003cp\u003e仓库权限只能由仓库的所有者维护（所有者可以是多个用户）。\u003c/p\u003e\n\u003cp\u003eMutable：拥有可以通过控制面板更改的权限\nSpecified：Mutable + 所有者\nEffective：Specified +正则表达式，管理员等\u003c/p\u003e\n\u003cp\u003eRepo permissions can only be maintained by an owner of the repo. If you are not the owner, it will appear to let you change the permissions, but actually fail silently\u003c/p\u003e\n\u003cp\u003e支持上述说法的 \u003ca href=\"https://www.programcreek.com/java-api-examples/?code=warpfork%2Fgitblit%2Fgitblit-master%2Fsrc%2Fmain%2Fjava%2Fcom%2Fgitblit%2Fwicket%2Fpanels%2FRegistrantPermissionsPanel.java\" title=\"代码片段\"\u003e代码片段\u003c/a\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eRegistrantPermissionsPanel\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e BasePanel {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efinal\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e serialVersionUID \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 1L;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eenum\u003c/span\u003e Show {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        specified, mutable, effective;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eboolean\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eshow\u003c/span\u003e(RegistrantAccessPermission ap) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eswitch\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e specified:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ap.\u003cspan style=\"color:#a6e22e\"\u003emutable\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e ap.\u003cspan style=\"color:#a6e22e\"\u003eisOwner\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e mutable:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ap.\u003cspan style=\"color:#a6e22e\"\u003emutable\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e effective:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e Show activeState \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Show.\u003cspan style=\"color:#a6e22e\"\u003emutable\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e参考\n1、 \u003ca href=\"https://issue.life/questions/34595235\"\u003ehttps://issue.life/questions/34595235\u003c/a\u003e\u003c/p\u003e","title":"gitblit : 仓库权限 mutable, specified 和 effective 的区别"},{"content":"最近调研VSCode的插件开发，选择typescript语言，看了typescript的官方的指导手册关于 namespace 的使用方式，我尝试类官方给出的一个文件和多个文件场景下使用namespace 。 结果一个文件使用namesapce没有问题，但是多个文件共享namespace，VSCode的语法提示总是提示找不到xxxx。 重点说明下，插件工程使用 yo code 创建的，namespace的示例也是官方的，官方的多个文件共享一个命名空间的方法是使用 /// \u0026lt;reference path = \u0026quot;xxxx.ts\u0026quot; /\u0026gt; 指令。\n百思不解，百度依然不解。幸好与多年的c++经验，借鉴c++的namespace中导入符号的方法，我找到类一条可行的路\u0026mdash;-综合利用 nameapce , import as , extends，示意如下:\na.ts内容\n//a.ts export class A { } b.ts内容\n//b.ts export class B { } c.ts内容\n//c.ts export class C { } 然后创建一个聚合的ts文件，将 a,b,c的符号以子类继承方式聚合 my.ts\n//my.ts import * as _a from \u0026#39;a\u0026#39;; import * as _b from \u0026#39;b\u0026#39;; import * as _c from \u0026#39;c\u0026#39;; expport namespace my { export class A extends _a.A {} export class B extends _b.B {} export class C extends _c.C {} } 使用示意：\nimport {my} from \u0026#39;my\u0026#39;; let tmp = new my.A(); ","permalink":"https://blog.z6z8.cn/2020/01/21/typescript-%E8%81%9A%E5%90%88%E5%A4%9A%E4%B8%AA%E6%96%87%E4%BB%B6%E7%9A%84%E5%A4%9A%E4%B8%AA%E7%B1%BB%E5%88%B0%E4%B8%80%E4%B8%AA%E5%91%BD%E5%90%8D%E7%A9%BA%E9%97%B4/","summary":"\u003cp\u003e最近调研VSCode的插件开发，选择typescript语言，看了typescript的官方的指导手册关于 \u003ca href=\"http://www.typescriptlang.org/docs/handbook/namespaces.html\" title=\"namespace\"\u003enamespace\u003c/a\u003e 的使用方式，我尝试类官方给出的一个文件和多个文件场景下使用namespace 。\n结果一个文件使用namesapce没有问题，但是多个文件共享namespace，VSCode的语法提示总是提示找不到xxxx。\n重点说明下，插件工程使用 \u003ccode\u003eyo code\u003c/code\u003e 创建的，namespace的示例也是官方的，官方的多个文件共享一个命名空间的方法是使用 \u003ccode\u003e/// \u0026lt;reference path = \u0026quot;xxxx.ts\u0026quot; /\u0026gt;\u003c/code\u003e 指令。\u003c/p\u003e\n\u003cp\u003e百思不解，百度依然不解。幸好与多年的c++经验，借鉴c++的namespace中导入符号的方法，我找到类一条可行的路\u0026mdash;-综合利用 \u003ccode\u003enameapce\u003c/code\u003e , \u003ccode\u003eimport as\u003c/code\u003e , \u003ccode\u003eextends\u003c/code\u003e，示意如下:\u003c/p\u003e\n\u003cp\u003ea.ts内容\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-typescript\" data-lang=\"typescript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//a.ts\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eA\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eb.ts内容\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-typescript\" data-lang=\"typescript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//b.ts\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eB\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003ec.ts内容\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-typescript\" data-lang=\"typescript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//c.ts\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eC\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e然后创建一个聚合的ts文件，将 a,b,c的符号以子类继承方式聚合\nmy.ts\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-typescript\" data-lang=\"typescript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//my.ts\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e_a\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;a\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e_b\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;b\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e_c\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;c\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eexpport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enamespace\u003c/span\u003e  \u003cspan style=\"color:#a6e22e\"\u003emy\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eA\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e_a\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eA\u003c/span\u003e {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eB\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e_b\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eB\u003c/span\u003e {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eC\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e_c\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eC\u003c/span\u003e {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e使用示意：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-typescript\" data-lang=\"typescript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e {\u003cspan style=\"color:#a6e22e\"\u003emy\u003c/span\u003e} \u003cspan style=\"color:#66d9ef\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;my\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etmp\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emy\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eA\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"typescript 聚合多个文件的多个类到一个命名空间"},{"content":"shadowsocks 干啥用的，我就不细说了。 安装过程如下\n安装pip3 shadowsocks有一个Python语言开发的实现，需要用pip安装\nsudo apt-get update sudo apt-get install python3-pip 安装shadowsocks pip3 install https://github.com/shadowsocks/shadowsocks/archive/master.zip 查看是否安装成功，安装成功应该会有版本显示\nssserver --version //Shadowsocks 3.0.0 创建配置文件 sudo mkdir /etc/shadowsocks cd /etc/shadowsocks vi config.json config.json 的内容如下\n{ \u0026#34;server\u0026#34;:\u0026#34;::\u0026#34;, \u0026#34;local_address\u0026#34;: \u0026#34;127.0.0.1\u0026#34;, \u0026#34;local_port\u0026#34;:1080, \u0026#34;port_password\u0026#34;: { \u0026#34;8388\u0026#34;:\u0026#34;端口A的密码\u0026#34;, \u0026#34;9000\u0026#34;:\u0026#34;端口B的密码\u0026#34;, \u0026#34;9001\u0026#34;:\u0026#34;端口C的密码\u0026#34; }, \u0026#34;timeout\u0026#34;:300, \u0026#34;method\u0026#34;:\u0026#34;aes-256-cfb\u0026#34;, \u0026#34;fast_open\u0026#34;: false } 启动server ssserver -c /etc/shadowsocks/config.json 添加server到系统服务 vi /etc/systemd/system/shadowsocks-server.service 内容如下\n[Unit] Description=Shadowsocks Server After=network.target [Service] ExecStart=/usr/local/bin/ssserver -c /etc/shadowsocks/config.json Restart=on-abort [Install] WantedBy=multi-user.target 然后就可以以系统服务启动了\nsudo systemctl start shadowsocks-server 参考 https://www.drsanwujiang.com/ubuntu-shadowsocks-install-and-optimize/\n","permalink":"https://blog.z6z8.cn/2020/01/14/ubuntu-18-04-%E5%AE%89%E8%A3%85-shadowsocks-server/","summary":"\u003cp\u003eshadowsocks 干啥用的，我就不细说了。\n安装过程如下\u003c/p\u003e\n\u003ch2 id=\"安装pip3\"\u003e安装pip3\u003c/h2\u003e\n\u003cp\u003eshadowsocks有一个Python语言开发的实现，需要用pip安装\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get update\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get install python3-pip\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"安装shadowsocks\"\u003e安装shadowsocks\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003epip3 install https://github.com/shadowsocks/shadowsocks/archive/master.zip\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e查看是否安装成功，安装成功应该会有版本显示\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003essserver --version\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e//Shadowsocks 3.0.0\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"创建配置文件\"\u003e创建配置文件\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo mkdir /etc/shadowsocks\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd /etc/shadowsocks\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003evi config.json\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003ccode\u003econfig.json\u003c/code\u003e 的内容如下\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;server\u0026#34;\u003c/span\u003e:\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;::\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;local_address\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;127.0.0.1\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;local_port\u0026#34;\u003c/span\u003e:\u003cspan style=\"color:#ae81ff\"\u003e1080\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;port_password\u0026#34;\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;8388\u0026#34;\u003c/span\u003e:\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;端口A的密码\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;9000\u0026#34;\u003c/span\u003e:\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;端口B的密码\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026#34;9001\u0026#34;\u003c/span\u003e:\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;端口C的密码\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;timeout\u0026#34;\u003c/span\u003e:\u003cspan style=\"color:#ae81ff\"\u003e300\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;method\u0026#34;\u003c/span\u003e:\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;aes-256-cfb\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;fast_open\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"启动server\"\u003e启动server\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003essserver -c /etc/shadowsocks/config.json\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"添加server到系统服务\"\u003e添加server到系统服务\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003evi  /etc/systemd/system/shadowsocks-server.service\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e内容如下\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[Unit]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eDescription=Shadowsocks Server\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAfter=network.target\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[Service]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eExecStart=/usr/local/bin/ssserver -c /etc/shadowsocks/config.json\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eRestart=on-abort\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[Install]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eWantedBy=multi-user.target\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e然后就可以以系统服务启动了\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl start shadowsocks-server\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e参考\n\u003ca href=\"https://www.drsanwujiang.com/ubuntu-shadowsocks-install-and-optimize/\"\u003ehttps://www.drsanwujiang.com/ubuntu-shadowsocks-install-and-optimize/\u003c/a\u003e\u003c/p\u003e","title":"ubuntu 18.04 安装 shadowsocks server"},{"content":"先上代码 RenderWebViewWithNative 我只在模拟器环境中测了。\n本文成文使用的环境 Xcode Version 11.3 (11C29) 模拟器版本Version 11.3 (SimulatorApp-912.5 SimulatorKit-570.3 CoreSimulator-681.17)，对应iOS 13.2 同层渲染步骤 简单说下同层渲染效果，是将Native控件添加到WKWebView的子层级View中，最明显的是z-index 属性可以控制Native控件。详细请阅读https://developers.weixin.qq.com/community/develop/article/doc/000c4e433707c072c1793e56f5c813\n需要前端改造的地方 为了让WKWebView为Native控件单独生成一个子层级的View，需要改变对应DOM节点的CSS样式,如\n〈div style=\u0026#34;position: fixed; font-size: 50px;overflow: scroll;-webkit-overflow-scrolling: touch\u0026#34; id=\u0026#34;zl_native\u0026#34; 〉 〈zl-native id=\u0026#34;zl_native_node\u0026#34;〉world〈zl-native〉 〈/div〉 本文成文环境中测试的结果是:\nWKWebView只为 position: fixed 的 标签内容生成单独的子层级视图\noverflow: scroll;-webkit-overflow-scrolling: touch,在本文成文环境中不起作用；建议读者自行尝试更多的环境，以得到更准确的结论。\n需要客户端改造的地方 首先，当前端加载DOM时，检测到需要Native渲染的节点，需要通过jsbridge通知客户端，把节点的信息告诉客户端。客户端根据节点信息找到对应的子层级view\n-(UIView *)find_zl_native_view { UIView *wkcontentview = [self get_wkcontentView]; NSMutableArray *arr = [wkcontentview.subviews mutableCopy]; while (arr.count \u0026gt; 0) { UIView *comp = arr.firstObject; [arr removeObjectAtIndex:0]; if ([@\u0026#34;WKCompositingView\u0026#34; isEqualToString:NSStringFromClass([comp class])]) { if ([comp.layer.name isEqualToString:@\u0026#34; id=\u0026#39;zl_native\u0026#39;\u0026#34;]) { return comp; } } if (comp.subviews.count \u0026gt; 0) { [arr addObjectsFromArray:comp.subviews]; } } return nil; } 找到后，在这个子层级view上添加Native控件，渲染对应内容。\n-(void)startNativeRender_zl_native_node { UIView *view = [self find_zl_native_view]; UILabel *lbl = [[UILabel alloc] initWithFrame:view.bounds]; [view addSubview:lbl]; lbl.alpha = 0; [UIView animateWithDuration:3 animations:^{ lbl.alpha = 0.6; lbl.text = @\u0026#34;world\u0026#34;; lbl.textColor = [UIColor yellowColor]; lbl.backgroundColor = [UIColor redColor]; lbl.font = [UIFont systemFontOfSize:49.5]; }]; } ","permalink":"https://blog.z6z8.cn/2020/01/13/%E5%B0%8F%E7%A8%8B%E5%BA%8F%E5%90%8C%E5%B1%82%E6%B8%B2%E6%9F%93-ios-wkwebview%E5%AE%9E%E7%8E%B0/","summary":"\u003cp\u003e先上代码\n\u003ca href=\"/wp-content/uploads/2020/01/RenderWebViewWithNative-1.zip\" title=\"RenderWebViewWithNative\"\u003eRenderWebViewWithNative\u003c/a\u003e\n我只在模拟器环境中测了。\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2020/01/RenderWebViewWithNative.png\"\u003e\u003c/p\u003e\n\u003ch1 id=\"本文成文使用的环境\"\u003e本文成文使用的环境\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003eXcode Version 11.3 (11C29)\u003c/li\u003e\n\u003cli\u003e模拟器版本Version 11.3 (SimulatorApp-912.5 SimulatorKit-570.3 CoreSimulator-681.17)，对应iOS 13.2\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"同层渲染步骤\"\u003e同层渲染步骤\u003c/h1\u003e\n\u003cp\u003e简单说下同层渲染效果，是将Native控件添加到WKWebView的子层级View中，最明显的是z-index 属性可以控制Native控件。详细请阅读https://developers.weixin.qq.com/community/develop/article/doc/000c4e433707c072c1793e56f5c813\u003c/p\u003e\n\u003ch2 id=\"需要前端改造的地方\"\u003e需要前端改造的地方\u003c/h2\u003e\n\u003cp\u003e为了让WKWebView为Native控件单独生成一个子层级的View，需要改变对应DOM节点的CSS样式,如\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e〈div style=\u0026#34;position: fixed; font-size: 50px;overflow: scroll;-webkit-overflow-scrolling: touch\u0026#34; id=\u0026#34;zl_native\u0026#34; 〉\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            〈zl-native id=\u0026#34;zl_native_node\u0026#34;〉world〈zl-native〉\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e〈/div〉\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e本文成文环境中测试的结果是:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003eWKWebView只为 \u003ccode\u003eposition: fixed\u003c/code\u003e 的\n标签内容生成单独的子层级视图\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003eoverflow: scroll;-webkit-overflow-scrolling: touch\u003c/code\u003e,在本文成文环境中不起作用；建议读者自行尝试更多的环境，以得到更准确的结论。\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"需要客户端改造的地方\"\u003e需要客户端改造的地方\u003c/h2\u003e\n\u003cp\u003e首先，当前端加载DOM时，检测到需要Native渲染的节点，需要通过jsbridge通知客户端，把节点的信息告诉客户端。客户端根据节点信息找到对应的子层级view\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-(UIView \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003efind_zl_native_view\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    UIView \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ewkcontentview \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [self get_wkcontentView];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSMutableArray \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003earr \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [wkcontentview.subviews mutableCopy];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e (arr.count \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        UIView \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ecomp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e arr.firstObject;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        [arr removeObjectAtIndex:\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ([\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;WKCompositingView\u0026#34;\u003c/span\u003e isEqualToString:NSStringFromClass([comp \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e])])\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ([comp.layer.name isEqualToString:\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#66d9ef\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u0026#39;\u003c/span\u003ezl_native\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;]) {\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e comp;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (comp.subviews.count \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            [arr addObjectsFromArray:comp.subviews];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e nil;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e找到后，在这个子层级view上添加Native控件，渲染对应内容。\u003c/p\u003e","title":"小程序同层渲染--iOS WKWebView实现"},{"content":"文章内容为谷歌翻译 源址http://www.earthvpn.com/faq-items/what-is-the-difference-between-pptp-l2tp-sstp-and-openvpn/\nPPTP 点对点隧道协议（PPTP）是Microsoft的一项发明，用于在拨号网络上创建VPN，因此多年来一直是内部业务VPN的标准协议。 它仅是一个VPN协议，并依靠各种身份验证方法来提供安全性。 它几乎在所有支持VPN的平台和设备上均作为标准配置提供，因此无需安装其他软件即可轻松设置，对于企业和个人使用而言，它仍然是一种流行的选择。 它还具有实现所需的低计算开销的优点。\nEarthVPN通过MPPE 128位密码（带有或不带有压缩功能以及MS-CHAPv2身份验证）实施PPTP加密。\nL2TP / IPSec 第2层隧道协议（L2TP）是通过Cisco和Microsoft之间的合作关系而产生的，其目的是提供更安全的VPN协议。 与PPTP相比，L2TP被认为是一种更安全的选择，因为结合使用了拥有更多安全加密算法的IPSec协议。 它还需要预共享的证书或密钥。\nEarthVPN通过具有AES加密算法的标准化IPSec协议实现L2TP加密。 256位密钥将用于加密。\nSSTP 安全套接字隧道协议（SSTP）在大多数VPN连接将被阻塞的情况下起作用。 其中包括禁止使用VPN技术的国家和某些阻止VPN连接的公司。 它使用TCP端口443，与安全套接字层（SSL）传输使用的端口相同。 这与特殊方法结合以形成数据包，以允许SSTP传输通过大多数代理和防火墙。 它被认为是VPN隧道协议中最安全的，因为它使用SSL，身份验证证书和2048位加密。\nSSTP的主要缺点是它仅由Microsoft创建，仅在Windows Vista SP 1和Windows 7/8上运行。 由于它是专有软件，因此尚无计划将其正式提供给Mac OS，Linux和较旧版本的Windows用户。\n如果您无法使用PPTP或L2TP协议进行连接，并且可以浏览https网站，则SSTP最有可能为您工作。\nOpenVPN OpenVPN是一种相当新的开源技术，它使用OpenSSL库和SSLv3 / TLSv1协议以及其他技术来提供强大而可靠的VPN解决方案。 它的主要优点之一是高度可配置，尽管它在UDP端口上运行最好，但可以将其设置为在任何端口上运行，包括TCP端口443。这使得它的流量无法区分，除了使用SSL上的标准HTTP，因此很难阻止。\nEarthVPN实施具有AES密码，128位和256位（可选）加密的OpenVPN协议，哈希算法为160位SHA1，控制通道为TLSv1 / SSLv3 DHE-RSA-AES256-SHA和2048位RSA。\nEarthVPN在TCP端口80（http），443（https），992、1194、8888和UDP端口53（dns），80、992、1194和8888上提供OpenVPN / SSL VPN协议。\n如果无法使用PPTP或L2TP协议进行连接，则可以尝试使用具有不同tcp和udp端口的OpenVPN进行连接。\n","permalink":"https://blog.z6z8.cn/2020/01/08/%E7%BF%BB%E8%AF%91-%E4%BB%8B%E7%BB%8Dpptp-%E3%80%81l2tp%E3%80%81sstp%E3%80%81openvpn/","summary":"\u003cp\u003e文章内容为谷歌翻译\n源址http://www.earthvpn.com/faq-items/what-is-the-difference-between-pptp-l2tp-sstp-and-openvpn/\u003c/p\u003e\n\u003ch2 id=\"pptp\"\u003ePPTP\u003c/h2\u003e\n\u003cp\u003e点对点隧道协议（PPTP）是Microsoft的一项发明，用于在拨号网络上创建VPN，因此多年来一直是内部业务VPN的标准协议。 它仅是一个VPN协议，并依靠各种身份验证方法来提供安全性。 它几乎在所有支持VPN的平台和设备上均作为标准配置提供，因此无需安装其他软件即可轻松设置，对于企业和个人使用而言，它仍然是一种流行的选择。 它还具有实现所需的低计算开销的优点。\u003c/p\u003e\n\u003cp\u003eEarthVPN通过MPPE 128位密码（带有或不带有压缩功能以及MS-CHAPv2身份验证）实施PPTP加密。\u003c/p\u003e\n\u003ch2 id=\"l2tp--ipsec\"\u003eL2TP / IPSec\u003c/h2\u003e\n\u003cp\u003e第2层隧道协议（L2TP）是通过Cisco和Microsoft之间的合作关系而产生的，其目的是提供更安全的VPN协议。 与PPTP相比，L2TP被认为是一种更安全的选择，因为结合使用了拥有更多安全加密算法的IPSec协议。 它还需要预共享的证书或密钥。\u003c/p\u003e\n\u003cp\u003eEarthVPN通过具有AES加密算法的标准化IPSec协议实现L2TP加密。 256位密钥将用于加密。\u003c/p\u003e\n\u003ch2 id=\"sstp\"\u003eSSTP\u003c/h2\u003e\n\u003cp\u003e安全套接字隧道协议（SSTP）在大多数VPN连接将被阻塞的情况下起作用。 其中包括禁止使用VPN技术的国家和某些阻止VPN连接的公司。 它使用TCP端口443，与安全套接字层（SSL）传输使用的端口相同。 这与特殊方法结合以形成数据包，以允许SSTP传输通过大多数代理和防火墙。 它被认为是VPN隧道协议中最安全的，因为它使用SSL，身份验证证书和2048位加密。\u003c/p\u003e\n\u003cp\u003eSSTP的主要缺点是它仅由Microsoft创建，仅在Windows Vista SP 1和Windows 7/8上运行。 由于它是专有软件，因此尚无计划将其正式提供给Mac OS，Linux和较旧版本的Windows用户。\u003c/p\u003e\n\u003cp\u003e如果您无法使用PPTP或L2TP协议进行连接，并且可以浏览https网站，则SSTP最有可能为您工作。\u003c/p\u003e\n\u003ch2 id=\"openvpn\"\u003eOpenVPN\u003c/h2\u003e\n\u003cp\u003eOpenVPN是一种相当新的开源技术，它使用OpenSSL库和SSLv3 / TLSv1协议以及其他技术来提供强大而可靠的VPN解决方案。 它的主要优点之一是高度可配置，尽管它在UDP端口上运行最好，但可以将其设置为在任何端口上运行，包括TCP端口443。这使得它的流量无法区分，除了使用SSL上的标准HTTP，因此很难阻止。\u003c/p\u003e\n\u003cp\u003eEarthVPN实施具有AES密码，128位和256位（可选）加密的OpenVPN协议，哈希算法为160位SHA1，控制通道为TLSv1 / SSLv3 DHE-RSA-AES256-SHA和2048位RSA。\u003c/p\u003e\n\u003cp\u003eEarthVPN在TCP端口80（http），443（https），992、1194、8888和UDP端口53（dns），80、992、1194和8888上提供OpenVPN / SSL VPN协议。\u003c/p\u003e\n\u003cp\u003e如果无法使用PPTP或L2TP协议进行连接，则可以尝试使用具有不同tcp和udp端口的OpenVPN进行连接。\u003c/p\u003e","title":"翻译: 介绍pptp 、l2tp、sstp、openvpn"},{"content":"主要是这张图，看懂就懂 权限定义：\nV ，可以使用浏览器查看、订阅RSS、zip打包下载 R ，具有V的所有权限，还具有复制（克隆）远程仓库到本地的权限 RW，具有R的所有权限，还具有推送到远程仓库的权限 RWC，具有RW的所有权限，还具有创建远程分支的权限 RWD，具有RWC的所有权限，还具有删除远程分支的权限 RW+ ，具有RWD的所有权限，还具有回退远程分支的权限 其他:\nadmin ，拥有所有权限（这毋庸置疑） owner，可以创建、编辑、重命名、删除、fork个人仓库 认证用户，可以创建个人仓库、fork个人仓库 参考http://www.gitblit.com/administration.html\n","permalink":"https://blog.z6z8.cn/2020/01/03/gitblit%E6%9D%83%E9%99%90%E7%B1%BB%E5%9E%8B/","summary":"\u003cp\u003e主要是这张图，看懂就懂\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2020/01/gitblit_permissions_matrix.png\"\u003e\u003c/p\u003e\n\u003cp\u003e权限定义：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eV ，可以使用浏览器查看、订阅RSS、zip打包下载\u003c/li\u003e\n\u003cli\u003eR ，具有V的所有权限，还具有复制（克隆）远程仓库到本地的权限\u003c/li\u003e\n\u003cli\u003eRW，具有R的所有权限，还具有推送到远程仓库的权限\u003c/li\u003e\n\u003cli\u003eRWC，具有RW的所有权限，还具有创建远程分支的权限\u003c/li\u003e\n\u003cli\u003eRWD，具有RWC的所有权限，还具有删除远程分支的权限\u003c/li\u003e\n\u003cli\u003eRW+ ，具有RWD的所有权限，还具有回退远程分支的权限\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e其他:\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eadmin ，拥有所有权限（这毋庸置疑）\u003c/li\u003e\n\u003cli\u003eowner，可以创建、编辑、重命名、删除、fork个人仓库\u003c/li\u003e\n\u003cli\u003e认证用户，可以创建个人仓库、fork个人仓库\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e参考http://www.gitblit.com/administration.html\u003c/p\u003e","title":"Gitblit权限类型"},{"content":"首先配置权限 在 package.json 中添加以下 partitions 内容\n{ \u0026#34;webview\u0026#34;: { \u0026#34;partitions\u0026#34;: [ { \u0026#34;name\u0026#34;: \u0026#34;trusted\u0026#34;, \u0026#34;accessible_resources\u0026#34;: [ \u0026#34;\u0026lt;all_urls\u0026gt;\u0026#34; ] } ] } } 然后为webview 的dom节点添加属性 partitions=\u0026quot;true\u0026quot;\n\u0026lt;webview partition=\u0026#34;trusted\u0026#34;\u0026gt;\u0026lt;/webview\u0026gt; 之后就可以使用 src 属性加载本地文件。\n或者使用javascript：\nvar webview = document.createElement(\u0026#34;webview\u0026#34;) webview.partition=\u0026#34;trusted\u0026#34; webview.src = \u0026#34;test/index.html\u0026#34; document.body.appendChild(webview) 参考https://nwjs.org.cn/doc/api/webview-Tag.html\n","permalink":"https://blog.z6z8.cn/2020/01/01/nwjs%EF%BC%9A%E4%BD%BF%E7%94%A8webview%E5%8A%A0%E8%BD%BD%E6%9C%AC%E5%9C%B0%E7%BD%91%E9%A1%B5/","summary":"\u003cp\u003e首先配置权限\n在 \u003ccode\u003epackage.json\u003c/code\u003e 中添加以下 \u003ccode\u003epartitions\u003c/code\u003e 内容\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-json\" data-lang=\"json\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026#34;webview\u0026#34;\u003c/span\u003e: {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026#34;partitions\u0026#34;\u003c/span\u003e: [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         \u003cspan style=\"color:#f92672\"\u003e\u0026#34;name\u0026#34;\u003c/span\u003e: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;trusted\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         \u003cspan style=\"color:#f92672\"\u003e\u0026#34;accessible_resources\u0026#34;\u003c/span\u003e: [ \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026lt;all_urls\u0026gt;\u0026#34;\u003c/span\u003e ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ]\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e然后为webview 的dom节点添加属性 \u003ccode\u003epartitions=\u0026quot;true\u0026quot;\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003ewebview\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epartition\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;trusted\u0026#34;\u003c/span\u003e\u0026gt;\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ewebview\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e之后就可以使用 \u003ccode\u003esrc\u003c/code\u003e 属性加载本地文件。\u003c/p\u003e\n\u003cp\u003e或者使用javascript：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewebview\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e document.\u003cspan style=\"color:#a6e22e\"\u003ecreateElement\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;webview\u0026#34;\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ewebview\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003epartition\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;trusted\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003ewebview\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esrc\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test/index.html\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    document.\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eappendChild\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ewebview\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e参考https://nwjs.org.cn/doc/api/webview-Tag.html\u003c/p\u003e","title":"nwjs：使用webview加载本地网页"},{"content":" 不显示滚动条 document.body.style.overflow = \u0026#34;hidden\u0026#34; //不显示滚动条 全屏 document.body.style.height = win.window.innerHeight + \u0026#34;px\u0026#34; document.body.style.width = win.window.innerWidth + \u0026#34;px\u0026#34; ","permalink":"https://blog.z6z8.cn/2019/12/31/%E4%BD%BF%E7%94%A8javascript%E5%9C%A8html-dom%E4%B8%AD%E8%AE%BE%E7%BD%AE%E5%85%A8%E5%B1%8F%E3%80%81%E9%9A%90%E8%97%8F%E6%BB%9A%E5%8A%A8%E6%9D%A1/","summary":"\u003cul\u003e\n\u003cli\u003e不显示滚动条\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edocument.\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eoverflow\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hidden\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e//不显示滚动条\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e全屏\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e document.\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eheight\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewin\u003c/span\u003e.window.\u003cspan style=\"color:#a6e22e\"\u003einnerHeight\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;px\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    document.\u003cspan style=\"color:#a6e22e\"\u003ebody\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ewidth\u003c/span\u003e  \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewin\u003c/span\u003e.window.\u003cspan style=\"color:#a6e22e\"\u003einnerWidth\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;px\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"使用JavaScript在HTML DOM中设置全屏、隐藏滚动条"},{"content":"我使用的Mac OS系统。\n需要说明的是： Debugger For NWjs 可以一键式配置，但是nwjs官网速度实在是惨不忍睹啊。\n首先，需要下载 nwjs sdk，官网速度能忍就忍吧，不能忍就下载国内的镜像版本，可以从这里下载https://nwjs.org.cn/download.html\nVSCode是必需要安装的。\n说下调试配置。先在VSCode的插件市场中下载安装 Debugger For NWjs， 然后，在系统的用户目录下建立如下目录:\n# ~/.nwjs/nwjs-sdk-版本-系统平台-cpu架构 # 例如 mkdir ~/.nwjs/nwjs-sdk-v0.43.1-osx-x64 然后把下载的 nwjs sdk 解压到这个目录下，注意需要nwjs就在这个一级目录下。\n然后用VSCode打开nwjs项目， VSCode -\u0026gt;调试-\u0026gt;添加配置，应该就可以调试了。\n","permalink":"https://blog.z6z8.cn/2019/12/31/vscodenwjs%E8%B0%83%E8%AF%95%E7%8E%AF%E5%A2%83%E9%85%8D%E7%BD%AE/","summary":"\u003cp\u003e我使用的Mac OS系统。\u003c/p\u003e\n\u003cp\u003e需要说明的是： \u003ccode\u003eDebugger For NWjs\u003c/code\u003e 可以一键式配置，但是nwjs官网速度实在是惨不忍睹啊。\u003c/p\u003e\n\u003cp\u003e首先，需要下载 \u003ccode\u003enwjs sdk\u003c/code\u003e，官网速度能忍就忍吧，不能忍就下载国内的镜像版本，可以从这里下载https://nwjs.org.cn/download.html\u003c/p\u003e\n\u003cp\u003eVSCode是必需要安装的。\u003c/p\u003e\n\u003cp\u003e说下调试配置。先在VSCode的插件市场中下载安装 \u003ccode\u003eDebugger For NWjs\u003c/code\u003e，\n然后，在系统的用户目录下建立如下目录:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# ~/.nwjs/nwjs-sdk-版本-系统平台-cpu架构\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 例如\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emkdir ~/.nwjs/nwjs-sdk-v0.43.1-osx-x64\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e然后把下载的 \u003ccode\u003enwjs sdk\u003c/code\u003e 解压到这个目录下，注意需要nwjs就在这个一级目录下。\u003c/p\u003e\n\u003cp\u003e然后用VSCode打开nwjs项目， \u003ccode\u003eVSCode -\u0026gt;调试-\u0026gt;添加配置\u003c/code\u003e，应该就可以调试了。\u003c/p\u003e","title":"VSCode+NWJS调试环境配置"},{"content":"单台计算机的安装部署过程。\n硬件要求（推荐） 一台计算机\nCPU 2G+，实测1G也可以运行，但仍然建议大点吧 RAM 2G+，实测1G也可以运行，但仍然建议大点吧 硬盘可用空间，实测大于5G就可以安装部署，但仍然建议越大越好 独立网卡和高速网络 固定ip地址 需要的软件 Ubuntu19.10 server版 Docker Apache2 php7 MySql dzzoffice 安装部署过程 Ubuntu19.10 server 官方的太慢了，用国内镜像吧，我用的是网易镜像站 下载地址： http://mirrors.163.com/ubuntu-releases/19.10/ubuntu-19.10-live-server-amd64.iso\n下载完成后，直接安装，安装过程中需要联网，ubuntu安装向导挺人性化的，接近Windows系统安装，很容易很方便。\n需要注意的是，ubuntu 安装过程中有一步骤需要输入镜像站地址，因为众所周知的原因，还是输入国内的吧。我输入的是网易的， http://mirrors.163.com/ubuntu\n（建议）安装OpenSSH Server 这步骤不是必需的，但会方便远程访问，更方便后续安装过程的复制粘贴。\nsudo apt-get install openssh-server #启动ssh服务 sudo service ssh start 然后远程登陆主机 我使用VSCode + Remote SSH。之所以远程登陆，是为了方便后面的复制粘贴。 VSCode + Remote SSH大概配置如下:\nHost dzz_ubuntu19.10 HostName ubuntu主机地址（可以是ip地址） User 用户名 # Port 22 默认是22 上面配置是使用用户名和密码的方式访问，也可以使用私钥文件方式访问，本文不讨论。\n安装Docker 安装过程，参考https://www.runoob.com/docker/ubuntu-docker-install.html\n如果有旧版本，先卸载旧版本\n$ sudo apt-get remove docker docker-engine docker.io containerd runc 更新索引\n$ sudo apt-get update 安装 apt 依赖包，用于通过HTTPS来获取仓库:\nsudo apt-get install \\ apt-transport-https \\ ca-certificates \\ curl \\ gnupg-agent \\ software-properties-common 添加 Docker 的官方 GPG 密钥：\n$ curl -fsSL https://download.docker.com/linux/ubuntu/gpg | sudo apt-key add - 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 通过搜索指纹的后8个字符，验证您现在是否拥有带有指纹的密钥。\n$ sudo apt-key fingerprint 0EBFCD88 pub rsa4096 2017-02-22 [SCEA] 9DC8 5822 9FC7 DD38 854A E2D8 8D81 803C 0EBF CD88 uid [ unknown] Docker Release (CE deb) \u0026lt;docker@docker.com\u0026gt; sub rsa4096 2017-02-22 [S] 使用以下指令设置稳定版仓库\n$ sudo add-apt-repository \\ \u0026#34;deb [arch=amd64] https://download.docker.com/linux/ubuntu \\ $(lsb_release -cs) \\ stable\u0026#34; 安装最新版本的 Docker Engine-Community 和 containerd (到这里才开始安装docker)\n$ sudo apt-get install docker-ce docker-ce-cli containerd.io 用Docker安装Onlyoffce document server 输入命令\nsudo docker pull onlyoffice/documentserver 等待吧，如果网速不快也许就半个小时。\n安装后，启动documentserver,并将宿主9000端口映射到docker的80端口\nsudo docker run -i -t -d -p 9000:80 onlyoffice/documentserver 用浏览器打开 http://主机ip地址:9000,应能看到 安装Apache2 sudo apt-get install apache2 用浏览器打开 http://主机ip地址,应能看到 安装MySql sudo apt-get install mysql-server mysql-client (建议)mysql安全检查 sudo mysql_secure_installation 创建一个mysql用户 sudo mysql -u root -p # 创建用户, 需要记录下用户名和密码 CREATE USER \u0026#39;用户名\u0026#39;@\u0026#39;localhost\u0026#39; IDENTIFIED BY \u0026#39;密码\u0026#39;; #创建数据库 mysql\u0026gt; CREATE DATABASE dzzoffice; Query OK, 1 row affected (0.00 sec) #授权 mysql\u0026gt; GRANT ALL PRIVILEGES ON dzzoffice.* TO \u0026#39;用户名\u0026#39;@\u0026#39;localhost\u0026#39;; Query OK, 0 rows affected (0.00 sec) #提交 mysql\u0026gt; FLUSH PRIVILEGES; Query OK, 0 rows affected (0.01 sec) #如果按照dzzoffice时遇到错误The server requested authentication method unknown to the client #mysql8之后需要执行。变更验证方式 mysql\u0026gt; ALTER USER \u0026#39;用户名\u0026#39;@\u0026#39;localhost\u0026#39; IDENTIFIED WITH mysql_native_password BY \u0026#39;密码\u0026#39;; #退出 mysql\u0026gt; EXIT Bye 安装php7 dzzoffice使用php开发，需要php5.4以上的环境。ubuntu19.10 安装php默认安装php7.3\nsudo apt-get install php 安装其他php组件 例如 php-xml,php-mysql\nsudo apt-get install php-xml 具体需要安装那些，在dzzoffice安装过程中会有提示。 一般需要安装\nphp-xml php-zip php-mysql php-gd php-curl 安装apache php mod apache用来解释php脚本的模块\nsudo apt-get install libapache2-mod-php 安装dzzoffice 官方下载地址: gitee https://gitee.com/zyx0814/dzzoffice/releases github https://github.com/zyx0814/dzzoffice/releases/ 国内用gitee会快些。\n如果是VSCode+RemoteSSH登陆，那么可以先下载然后把包直接拖到ubuntu主机上。 如果是主机上下载，可以使用wget命令。\n下载后的压缩包，解压到 /var/www/html/ 目录下，这个目录是apache网站的默认根目录。\n然后浏览器打开 http://localhost/dzzoffice/install，完成dzzoffice的安装。安装过程也挺简单的，全程中文。 安装过程中，可能会需要php的某些组件，把组件装上，重启apache2就好，例如\nsudo apt-get install php-xml sudo systemctl restart apahce2 如果要求某些目录的权限，按照提示给予 0777 权限，例如\nsudo chmod -R 0777 /var/www/html/dzzoffice/config/ 如果按照dzzoffice时遇到错误 The server requested authentication method unknown to the client，那是因为mysql8验证方式变了，需要手动变更验证方式。\nonlyoffice 和 dzzoffice集成 这是本文的重点。 用 admin 账号进入dzzoffice的管理台，进入应用市场，安装 文档、表格、演示文稿、首页、onlyoffice 插件 在linux系统上，应用安装还需要/var/www/html/dzzoffice/dzz的目录写权限，直接给予0777就好\n然后，进入 onlyoffice 插件的设置界面 需要设置\nOnlyOffice Document Server API地址，就填写docker启动的那个onlyoffice地址，本文为 http://本机ip地址:9000/ dzzoffice服务地址，也就是Xampp的Appache运行的dzzoffice服务地址，需要注意 不能填写localhost,127.0.0.1 地址，要使用dns分配给本机的地址， http://本机ip地址/dzzoffice/ 到这里，你就可以在本机上使用dzzoffice新建编辑在线文档了。 好了，尝试用其他计算机访问试试。\n","permalink":"https://blog.z6z8.cn/2019/12/30/%E5%9C%A8ubuntu19-10-%E4%B8%8A%E9%83%A8%E7%BD%B2dzzofficeonlyoffice%E5%8D%8F%E5%90%8C%E5%8A%9E%E5%85%AC%E7%B3%BB%E7%BB%9F/","summary":"\u003cp\u003e单台计算机的安装部署过程。\u003c/p\u003e\n\u003ch1 id=\"硬件要求推荐\"\u003e硬件要求（推荐）\u003c/h1\u003e\n\u003cp\u003e一台计算机\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eCPU 2G+，实测1G也可以运行，但仍然建议大点吧\u003c/li\u003e\n\u003cli\u003eRAM 2G+，实测1G也可以运行，但仍然建议大点吧\u003c/li\u003e\n\u003cli\u003e硬盘可用空间，实测大于5G就可以安装部署，但仍然建议越大越好\u003c/li\u003e\n\u003cli\u003e独立网卡和高速网络\u003c/li\u003e\n\u003cli\u003e固定ip地址\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"需要的软件\"\u003e需要的软件\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003eUbuntu19.10 server版\u003c/li\u003e\n\u003cli\u003eDocker\u003c/li\u003e\n\u003cli\u003eApache2\u003c/li\u003e\n\u003cli\u003ephp7\u003c/li\u003e\n\u003cli\u003eMySql\u003c/li\u003e\n\u003cli\u003edzzoffice\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"安装部署过程\"\u003e安装部署过程\u003c/h1\u003e\n\u003ch2 id=\"ubuntu1910-server\"\u003eUbuntu19.10 server\u003c/h2\u003e\n\u003cp\u003e官方的太慢了，用国内镜像吧，我用的是网易镜像站\n下载地址： \u003ca href=\"http://mirrors.163.com/ubuntu-releases/19.10/ubuntu-19.10-live-server-amd64.iso\"\u003ehttp://mirrors.163.com/ubuntu-releases/19.10/ubuntu-19.10-live-server-amd64.iso\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e下载完成后，直接安装，安装过程中需要联网，ubuntu安装向导挺人性化的，接近Windows系统安装，很容易很方便。\u003c/p\u003e\n\u003cp\u003e需要注意的是，ubuntu 安装过程中有一步骤需要输入镜像站地址，因为众所周知的原因，还是输入国内的吧。我输入的是网易的， \u003ccode\u003ehttp://mirrors.163.com/ubuntu\u003c/code\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2019/12/ubuntu163mirrors.png\"\u003e\u003c/p\u003e\n\u003ch3 id=\"建议安装openssh-server\"\u003e（建议）安装OpenSSH Server\u003c/h3\u003e\n\u003cp\u003e这步骤不是必需的，但会方便远程访问，更方便后续安装过程的复制粘贴。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get install openssh-server\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#启动ssh服务\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo service ssh start\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e然后远程登陆主机\n我使用VSCode + Remote SSH。之所以远程登陆，是为了方便后面的复制粘贴。\nVSCode + Remote SSH大概配置如下:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eHost dzz_ubuntu19.10\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    HostName ubuntu主机地址（可以是ip地址）\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    User 用户名\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    # Port 22 默认是22\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e上面配置是使用用户名和密码的方式访问，也可以使用私钥文件方式访问，本文不讨论。\u003c/p\u003e\n\u003ch2 id=\"安装docker\"\u003e安装Docker\u003c/h2\u003e\n\u003cp\u003e安装过程，参考https://www.runoob.com/docker/ubuntu-docker-install.html\u003c/p\u003e\n\u003cp\u003e如果有旧版本，先卸载旧版本\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ sudo apt-get remove docker docker-engine docker.io containerd runc\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e更新索引\u003c/p\u003e","title":"在Ubuntu19.10 上部署dzzoffice+onlyoffice协同办公系统"},{"content":"如果能连接公网的话，关闭本页面吧。一大票的好用的解决方案、office365、google doc、wps、腾讯文档、石墨文档。。。。。。\n废话不说，直接进入正题，单台计算机的安装部署过程。\n硬件要求 一台计算机\nCPU 2G+ RAM 4G+ 独立网卡和高速网络 固定ip地址 需要的软件 Windows操作系统，Windows7之类，不需要Windows Server也可以 Virtual Box，虚拟机 DockerToolBox，docker集成工具 Xampp，LAMP集成环境 Onlyoffce document server dzzoffice 安装部署过程 安装VirtualBox 官方下载地址： https://www.virtualbox.org/wiki/Downloads 国内下载地址：自己百度吧。国内下载的速度会快一些\n下载完成后，直接安装。在Windows上安装软件基本可以“一路确定”\n安装Docker Windows上使用DockerToolBox集成工具，国内可以使用阿里云的镜像来下载，下载地址： http://mirrors.aliyun.com/docker-toolbox/windows/docker-toolbox/\n同样是“一路确定”。详细安装过程，参考https://www.runoob.com/docker/windows-docker-install.html\n安装后，启动 Docker Quickstart Terminal 初始化Docker，等待即可（中途可能会询问权限，放开就好）。 用Docker安装Onlyoffce document server 打开 Docker Quickstart Terminal，正常的情况下会看到这么一行\ndocker is configured to use the default machine with IP 192.168.99.100 记下这个ip地址，后面会用到。\n输入命令\ndocker pull onlyoffice/documentserver 等待吧，如果网速不快也许就半个小时。\n安装后，启动documentserver,并将宿主9000端口映射到docker的80端口\ndocker run -i -t -d -p 9000:80 onlyoffice/documentserver 用浏览器打开 http://ip:9000（本文对应 http://192.168.99.100:9000）,应能看到 安装Xampp 官方下载地址: https://www.apachefriends.org/index.html 同样是“一路确定”。 安装后，打开 XAMPP Control Panel，开启Apache和MySQL服务 安装dzzoffice 官方下载地址: gitee https://gitee.com/zyx0814/dzzoffice/releases github https://github.com/zyx0814/dzzoffice/releases/\n国内用gitee会快些。 下载后的压缩包，解压到Xampp的 htdocs 目录 然后浏览器打开 http://localhost/dzzoffice/install，完成dzzoffice的安装。安装过程也挺简单的，全程中文。\nonlyoffice 和 dzzoffice集成 这是本文的重点。 用 admin 账号进入dzzoffice的管理台，进入应用市场，安装 文档、表格、演示文稿、首页、onlyoffice 插件 然后，进入 onlyoffice 插件的设置界面 需要设置\nOnlyOffice Document Server API地址，就填写docker启动的那个onlyoffice地址，本文为 http://192.168.99.100:9000/（后面会提到联网问题） dzzoffice服务地址，也就是Xampp的Appache运行的dzzoffice服务地址，需要注意 不能填写localhost,127.0.0.1 地址，要使用dns分配给本机的地址，如 http://192.168.43.40/dzzoffice/ 到这里，你就可以在本机上使用dzzoffice新建编辑在线文档了。\n给局域网的其他机器提供服务 局域网的其他计算机是可以访问dzzoffice服务的，可以新建文档，但是不能编辑在线文档，原因就是我们使用了docker安装onlyoffice documentserver，默认情况docker的内部网络无法和本机之外的其他计算机通信。 有一个简单的解决办法就是 端口转发. 打开 VirtualBox，可以看到一个叫 default 的虚拟机，设置这个虚拟的网络参数 新建规则，将本机9000端口（onlyoffice documentserver服务端口）全部转发到docker内的9000端口。 主机ip是本机ip，子系统ip是docker的ip。 最后，修改dzzoffice的onlyoffce的设置参数，将OnlyOffice Document Server API的地址修改为 http://本机ip:9000\n好了，尝试用其他计算机访问试试。\n","permalink":"https://blog.z6z8.cn/2019/12/28/%E5%B1%80%E5%9F%9F%E7%BD%91%E9%83%A8%E7%BD%B2%E6%96%87%E6%A1%A3%E5%8D%8F%E5%90%8C%E5%8A%9E%E5%85%AC%E7%B3%BB%E7%BB%9F%EF%BC%9Awindows-onlyoffice-dzzoffice/","summary":"\u003cp\u003e如果能连接公网的话，关闭本页面吧。一大票的好用的解决方案、office365、google doc、wps、腾讯文档、石墨文档。。。。。。\u003c/p\u003e\n\u003cp\u003e废话不说，直接进入正题，单台计算机的安装部署过程。\u003c/p\u003e\n\u003ch1 id=\"硬件要求\"\u003e硬件要求\u003c/h1\u003e\n\u003cp\u003e一台计算机\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eCPU 2G+\u003c/li\u003e\n\u003cli\u003eRAM 4G+\u003c/li\u003e\n\u003cli\u003e独立网卡和高速网络\u003c/li\u003e\n\u003cli\u003e固定ip地址\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"需要的软件\"\u003e需要的软件\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003eWindows操作系统，Windows7之类，不需要Windows Server也可以\u003c/li\u003e\n\u003cli\u003eVirtual Box，虚拟机\u003c/li\u003e\n\u003cli\u003eDockerToolBox，docker集成工具\u003c/li\u003e\n\u003cli\u003eXampp，LAMP集成环境\u003c/li\u003e\n\u003cli\u003eOnlyoffce document server\u003c/li\u003e\n\u003cli\u003edzzoffice\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"安装部署过程\"\u003e安装部署过程\u003c/h1\u003e\n\u003ch2 id=\"安装virtualbox\"\u003e安装VirtualBox\u003c/h2\u003e\n\u003cp\u003e官方下载地址： \u003ca href=\"https://www.virtualbox.org/wiki/Downloads\"\u003ehttps://www.virtualbox.org/wiki/Downloads\u003c/a\u003e\n国内下载地址：自己百度吧。国内下载的速度会快一些\u003c/p\u003e\n\u003cp\u003e下载完成后，直接安装。在Windows上安装软件基本可以“一路确定”\u003c/p\u003e\n\u003ch2 id=\"安装docker\"\u003e安装Docker\u003c/h2\u003e\n\u003cp\u003eWindows上使用DockerToolBox集成工具，国内可以使用阿里云的镜像来下载，下载地址： \u003ca href=\"http://mirrors.aliyun.com/docker-toolbox/windows/docker-toolbox/\"\u003ehttp://mirrors.aliyun.com/docker-toolbox/windows/docker-toolbox/\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e同样是“一路确定”。详细安装过程，参考https://www.runoob.com/docker/windows-docker-install.html\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"https://www.runoob.com/wp-content/uploads/2017/12/icon-set.png\"\u003e\n安装后，启动 \u003ccode\u003eDocker Quickstart Terminal\u003c/code\u003e 初始化Docker，等待即可（中途可能会询问权限，放开就好）。\n\u003cimg loading=\"lazy\" src=\"https://www.runoob.com/wp-content/uploads/2017/12/1513667960-3359-b2d-shell.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"用docker安装onlyoffce-document-server\"\u003e用Docker安装Onlyoffce document server\u003c/h2\u003e\n\u003cp\u003e打开 \u003ccode\u003eDocker Quickstart Terminal\u003c/code\u003e，正常的情况下会看到这么一行\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edocker is configured to use the default machine with IP 192.168.99.100\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e记下这个ip地址，后面会用到。\u003c/p\u003e\n\u003cp\u003e输入命令\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edocker pull onlyoffice/documentserver\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e等待吧，如果网速不快也许就半个小时。\u003c/p\u003e\n\u003cp\u003e安装后，启动documentserver,并将宿主9000端口映射到docker的80端口\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edocker run -i -t -d -p 9000:80 onlyoffice/documentserver\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e用浏览器打开 \u003ccode\u003ehttp://ip:9000\u003c/code\u003e（本文对应 \u003ccode\u003ehttp://192.168.99.100:9000\u003c/code\u003e）,应能看到\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2019/12/documentserver.jpg\"\u003e\u003c/p\u003e","title":"局域网部署文档协同办公系统：Windows + onlyoffice + dzzoffice"},{"content":" function check_webp_feature(feature, callback) { var kTestImages = { lossy: \u0026#34;UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA\u0026#34;, lossless: \u0026#34;UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==\u0026#34;, alpha: \u0026#34;UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==\u0026#34;, animation: \u0026#34;UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA\u0026#34; }; var img = new Image(); img.onload = function () { var result = (img.width \u0026gt; 0) \u0026amp;\u0026amp; (img.height \u0026gt; 0); callback(feature, result); }; img.onerror = function () { callback(feature, false); }; img.src = \u0026#34;data:image/webp;base64,\u0026#34; + kTestImages[feature]; } ","permalink":"https://blog.z6z8.cn/2019/12/26/javascript%E6%A3%80%E6%B5%8B%E6%98%AF%E5%90%A6%E6%94%AF%E6%8C%81webp%E5%9B%BE%E7%89%87%EF%BC%88%E5%87%BA%E8%87%AAgoogle%E5%AE%98%E6%96%B9%E6%96%87%E6%A1%A3%EF%BC%89/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003echeck_webp_feature\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003efeature\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003ecallback\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ekTestImages\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003elossy\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;UklGRiIAAABXRUJQVlA4IBYAAAAwAQCdASoBAAEADsD+JaQAA3AAAAAA\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003elossless\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;UklGRhoAAABXRUJQVlA4TA0AAAAvAAAAEAcQERGIiP4HAA==\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ealpha\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;UklGRkoAAABXRUJQVlA4WAoAAAAQAAAAAAAAAAAAQUxQSAwAAAARBxAR/Q9ERP8DAABWUDggGAAAABQBAJ0BKgEAAQAAAP4AAA3AAP7mtQAAAA==\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eanimation\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;UklGRlIAAABXRUJQVlA4WAoAAAASAAAAAAAAAAAAQU5JTQYAAAD/////AABBTk1GJgAAAAAAAAAAAAAAAAAAAGQAAABWUDhMDQAAAC8AAAAQBxAREYiI/gcA\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eimg\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eImage\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eimg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eonload\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e () {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eimg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ewidth\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eimg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eheight\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ecallback\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003efeature\u003c/span\u003e, \u003cspan style=\"color:#a6e22e\"\u003eresult\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eimg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eonerror\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e () {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003ecallback\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003efeature\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eimg\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003esrc\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;data:image/webp;base64,\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ekTestImages\u003c/span\u003e[\u003cspan style=\"color:#a6e22e\"\u003efeature\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"JavaScript检测是否支持WebP图片（出自Google官方文档）"},{"content":"自己都忘了什么时候写的了，@_@\n#pragma once #include \u0026lt;list\u0026gt; #include \u0026lt;vector\u0026gt; #include \u0026lt;stack\u0026gt; using namespace std; struct Bound { size_t low; size_t high; Bound(size_t lowind,size_t highind) { this-\u0026gt;low=lowind; this-\u0026gt;high=highind; } }; template \u0026lt;typename T\u0026gt; void QSort(vector\u0026lt;T\u0026gt; \u0026amp; vay) //从小到大排序 { size_t len=vay.size(); if( len \u0026gt; 2) { stack\u0026lt;Bound\u0026gt; boundS; Bound bd(0,len-1); boundS.push(bd); size_t low,high; while( ! boundS.empty() ) //当栈不为空时 { bd=boundS.top();//取栈顶元素 low=bd.low; high=bd.high; boundS.pop();//弹出栈顶元素 low++;//用数组的排序部分的首个元素作为关键值，进行比较 while( true ) //进行二分数组排序 { while( low \u0026lt; high \u0026amp;\u0026amp; vay[low] \u0026lt;= vay[bd.low] ) //用数组的排序部分的首个元素作为关键值，进行比较 { low++; } while( low \u0026lt; high \u0026amp;\u0026amp; vay[high] \u0026gt; vay[bd.low] ) //vay[high] \u0026gt; vay[bd.low] 不能用 \u0026gt;=，因为要二分数组的排序部分，保证两部分的排他性 { high--; } if( low \u0026lt; high ) {//交换低索引和高索引元素 T tmp=vay[low]; vay[low]=vay[high]; vay[high]=tmp; } else {//此时，low == high 为真 break; } } //此时，low == high 为真 if( vay[low] \u0026gt; vay[bd.low] ) { low--; } //将关键值插入大元素和小元素的分界 T tmp=vay[low]; vay[low]=vay[bd.low]; vay[bd.low]=tmp; if( low - bd.low \u0026gt; 1 ) //若小元素部分元素个数大于1个，继续排序 { Bound newbd(bd.low,low-1); boundS.push(newbd); } if( bd.high - low \u0026gt; 1)//若大元素部分元素个数大于1个，继续排序 { Bound newbd(low+1,bd.high); boundS.push(newbd); } } } else if( len == 2) //若数组长度为2，直接比较 { if( vay[0] \u0026gt; vay[1] ) { T tmp=vay[0]; vay[0]=vay[1]; vay[1]=tmp; } } //若数组长度小于2，不用排序 } template \u0026lt;typename T\u0026gt; struct BoundIter { BoundIter(typename list\u0026lt;T\u0026gt;::iterator lowiter,typename list\u0026lt;T\u0026gt;::iterator highiter) { this-\u0026gt;low=lowiter; this-\u0026gt;high=highiter; } typename list\u0026lt;T\u0026gt;::iterator low; typename list\u0026lt;T\u0026gt;::iterator high; }; template \u0026lt;typename T\u0026gt; void QSort(list\u0026lt;T\u0026gt; \u0026amp; lst) //从小到大排序 { if( lst.size() \u0026gt; 2) { stack\u0026lt;BoundIter\u0026lt;T\u0026gt;\u0026gt; boundIterS; BoundIter\u0026lt;T\u0026gt; bd(lst.begin(),(--lst.end())); boundIterS.push(bd); list\u0026lt;T\u0026gt;::iterator low,high; while( ! boundIterS.empty() ) //当栈不为空时 { bd=boundIterS.top();//取栈顶元素 low=bd.low; high=bd.high; boundIterS.pop();//弹出栈顶元素 low++;//用数组的排序部分的首个元素作为关键值，进行比较 while( true ) //进行二分数组排序 { while( low != high \u0026amp;\u0026amp; *low \u0026lt;= *(bd.low) ) //用数组的排序部分的首个元素作为关键值，进行比较 { low++; } while( low != high \u0026amp;\u0026amp; *high \u0026gt; *(bd.low) ) //*high \u0026gt; *(bd.low) 不能用 \u0026gt;=，因为要二分数组的排序部分，保证两部分的排他性 { high--; } if( low != high ) {//交换低索引和高索引元素 T tmp=*low; *low=*high; *high=tmp; } else {//此时，low == high 为真 break; } } //此时，low == high 为真 if( *low \u0026gt; *bd.low ) { low--; } //将关键值插入大元素和小元素的分界 T tmp=*low; *low=*bd.low; *bd.low=tmp; if( low != bd.low ) {//若小元素部分元素个数大于1个，继续排序 low--; if( low != bd.low ) { BoundIter\u0026lt;T\u0026gt; newbd(bd.low,low); boundIterS.push(newbd); } low++; } if( low != bd.high) {//若大元素部分元素个数大于1个，继续排序 low++; if( low != bd.high ) { BoundIter\u0026lt;T\u0026gt; newbd(low,bd.high); boundIterS.push(newbd); } } } } else if( lst.size() == 2) //若数组长度为2，直接比较 { list\u0026lt;T\u0026gt;::iterator iter0=lst.begin(); list\u0026lt;T\u0026gt;::iterator iter1=(++lst.begin()); if( *iter0 \u0026gt; *iter1 ) { T tmp=*iter0; *iter0=*iter1; *iter1=tmp; } } //若数组长度小于2，不用排序 } ","permalink":"https://blog.z6z8.cn/2019/12/25/%E5%BF%AB%E9%80%9F%E6%8E%92%E5%BA%8Fc%E5%AE%9E%E7%8E%B0/","summary":"\u003cp\u003e自己都忘了什么时候写的了，@_@\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-cpp\" data-lang=\"cpp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#pragma once\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;list\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;vector\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;stack\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eusing\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enamespace\u003c/span\u003e std;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBound\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    size_t low;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    size_t high;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Bound(size_t lowind,size_t highind)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003elow\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003elowind;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003ehigh\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ehighind;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003etypename\u003c/span\u003e T\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e QSort(vector\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eT\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e vay) \u003cspan style=\"color:#75715e\"\u003e//从小到大排序\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    size_t len\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003evay.size();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( len \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        stack\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eBound\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e boundS;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Bound \u003cspan style=\"color:#a6e22e\"\u003ebd\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e,len\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        boundS.push(bd);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        size_t low,high;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e( \u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e boundS.empty() ) \u003cspan style=\"color:#75715e\"\u003e//当栈不为空时\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            bd\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eboundS.top();\u003cspan style=\"color:#75715e\"\u003e//取栈顶元素\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            low\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ebd.low;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            high\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ebd.high;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            boundS.pop();\u003cspan style=\"color:#75715e\"\u003e//弹出栈顶元素\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            low\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\u003cspan style=\"color:#75715e\"\u003e//用数组的排序部分的首个元素作为关键值，进行比较\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e( true ) \u003cspan style=\"color:#75715e\"\u003e//进行二分数组排序\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e( low \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e high \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e vay[low] \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e vay[bd.low] ) \u003cspan style=\"color:#75715e\"\u003e//用数组的排序部分的首个元素作为关键值，进行比较\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    low\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e( low \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e high \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e vay[high] \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e vay[bd.low] ) \u003cspan style=\"color:#75715e\"\u003e//vay[high] \u0026gt; vay[bd.low] 不能用 \u0026gt;=，因为要二分数组的排序部分，保证两部分的排他性\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    high\u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( low \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e high )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#75715e\"\u003e//交换低索引和高索引元素\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    T tmp\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003evay[low];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    vay[low]\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003evay[high];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    vay[high]\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003etmp;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#75715e\"\u003e//此时，low == high 为真\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e//此时，low == high 为真\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( vay[low] \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e vay[bd.low] )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                low\u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e//将关键值插入大元素和小元素的分界\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            T tmp\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003evay[low];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            vay[low]\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003evay[bd.low];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            vay[bd.low]\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003etmp;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( low \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e bd.low \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e ) \u003cspan style=\"color:#75715e\"\u003e//若小元素部分元素个数大于1个，继续排序\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                Bound \u003cspan style=\"color:#a6e22e\"\u003enewbd\u003c/span\u003e(bd.low,low\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                boundS.push(newbd);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( bd.high \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e low \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\u003cspan style=\"color:#75715e\"\u003e//若大元素部分元素个数大于1个，继续排序\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                Bound \u003cspan style=\"color:#a6e22e\"\u003enewbd\u003c/span\u003e(low\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,bd.high);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                boundS.push(newbd);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eif\u003c/span\u003e( len \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#75715e\"\u003e//若数组长度为2，直接比较\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( vay[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e vay[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e] )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            T tmp\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003evay[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            vay[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003evay[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            vay[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e]\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003etmp;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//若数组长度小于2，不用排序\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003etypename\u003c/span\u003e T\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBoundIter\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    BoundIter(\u003cspan style=\"color:#66d9ef\"\u003etypename\u003c/span\u003e list\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eT\u003cspan style=\"color:#f92672\"\u003e\u0026gt;::\u003c/span\u003eiterator lowiter,\u003cspan style=\"color:#66d9ef\"\u003etypename\u003c/span\u003e list\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eT\u003cspan style=\"color:#f92672\"\u003e\u0026gt;::\u003c/span\u003eiterator highiter)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003elow\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003elowiter;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003ehigh\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ehighiter;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etypename\u003c/span\u003e list\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eT\u003cspan style=\"color:#f92672\"\u003e\u0026gt;::\u003c/span\u003eiterator low;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etypename\u003c/span\u003e list\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eT\u003cspan style=\"color:#f92672\"\u003e\u0026gt;::\u003c/span\u003eiterator high;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003etypename\u003c/span\u003e T\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e QSort(list\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eT\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e lst) \u003cspan style=\"color:#75715e\"\u003e//从小到大排序\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( lst.size() \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        stack\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eBoundIter\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eT\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e boundIterS;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        BoundIter\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eT\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e bd(lst.begin(),(\u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003elst.end()));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        boundIterS.push(bd);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        list\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eT\u003cspan style=\"color:#f92672\"\u003e\u0026gt;::\u003c/span\u003eiterator low,high;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e( \u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e boundIterS.empty() ) \u003cspan style=\"color:#75715e\"\u003e//当栈不为空时\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            bd\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eboundIterS.top();\u003cspan style=\"color:#75715e\"\u003e//取栈顶元素\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            low\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ebd.low;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            high\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003ebd.high;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            boundIterS.pop();\u003cspan style=\"color:#75715e\"\u003e//弹出栈顶元素\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            low\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\u003cspan style=\"color:#75715e\"\u003e//用数组的排序部分的首个元素作为关键值，进行比较\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e( true ) \u003cspan style=\"color:#75715e\"\u003e//进行二分数组排序\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e( low \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e high \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003elow \u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e(bd.low) ) \u003cspan style=\"color:#75715e\"\u003e//用数组的排序部分的首个元素作为关键值，进行比较\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    low\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e( low \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e high \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ehigh \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e(bd.low) ) \u003cspan style=\"color:#75715e\"\u003e//*high \u0026gt; *(bd.low) 不能用 \u0026gt;=，因为要二分数组的排序部分，保证两部分的排他性\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    high\u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( low \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e high )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#75715e\"\u003e//交换低索引和高索引元素\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    T tmp\u003cspan style=\"color:#f92672\"\u003e=*\u003c/span\u003elow;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003elow\u003cspan style=\"color:#f92672\"\u003e=*\u003c/span\u003ehigh;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ehigh\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003etmp;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\u003cspan style=\"color:#75715e\"\u003e//此时，low == high 为真\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e//此时，low == high 为真\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003elow \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ebd.low )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                low\u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e//将关键值插入大元素和小元素的分界\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            T tmp\u003cspan style=\"color:#f92672\"\u003e=*\u003c/span\u003elow;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003elow\u003cspan style=\"color:#f92672\"\u003e=*\u003c/span\u003ebd.low;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ebd.low\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003etmp;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( low \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e bd.low )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\u003cspan style=\"color:#75715e\"\u003e//若小元素部分元素个数大于1个，继续排序\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                low\u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( low \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e bd.low )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    BoundIter\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eT\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e newbd(bd.low,low);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    boundIterS.push(newbd);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                low\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( low \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e bd.high)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\u003cspan style=\"color:#75715e\"\u003e//若大元素部分元素个数大于1个，继续排序\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                low\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( low \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e bd.high )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    BoundIter\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eT\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e newbd(low,bd.high);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    boundIterS.push(newbd);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eif\u003c/span\u003e( lst.size() \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#75715e\"\u003e//若数组长度为2，直接比较\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        list\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eT\u003cspan style=\"color:#f92672\"\u003e\u0026gt;::\u003c/span\u003eiterator iter0\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003elst.begin();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        list\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eT\u003cspan style=\"color:#f92672\"\u003e\u0026gt;::\u003c/span\u003eiterator iter1\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003elst.begin());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eiter0 \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eiter1 )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            T tmp\u003cspan style=\"color:#f92672\"\u003e=*\u003c/span\u003eiter0;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eiter0\u003cspan style=\"color:#f92672\"\u003e=*\u003c/span\u003eiter1;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eiter1\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003etmp;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//若数组长度小于2，不用排序\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"快速排序C++实现"},{"content":"我用Android手机装了个电商软件，抢购用。自己手机的状态栏不能显示秒级别的时间，只能精确到分钟。为了能准确的把握抢购时间，自己边学习边开发了一个时间显示悬浮窗。\nWindowManager 参考文章 WindowManager可以在其他应用最上层，甚至手机桌面最上层显示窗口。\n使用Context.getSystemService(Context.WINDOW_SERVICE)来获取WindowManager。 API 17推出了Presentation，它将自动获取display的Context和WindowManager，可以方便地在另一个display上显示窗口 使用WindowManager继承自基类的addView方法和removeView方法来显示和隐藏窗口 WindowManager实现悬浮窗需要声明权限，在manifest中添加如下权限： 在MIUI上需要在设置中打开本应用的”显示悬浮窗”开关，并且重启应用，否则悬浮窗只能显示在本应用界面内，不能显示在手机桌面上。 具体过程 创建工程 用Android Studio创建一个Android Basic Activity工程 添加权限 修改 AndroidManifest.xml，添加下面结构的数据\n\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34;?\u0026gt; \u0026lt;manifest \u0026gt; \u0026lt;!-- 显示顶层浮窗权限 --\u0026gt; \u0026lt;uses-permission android:name=\u0026#34;android.permission.SYSTEM_ALERT_WINDOW\u0026#34;\u0026gt; \u0026lt;/uses-permission\u0026gt; \u0026lt;/manifest\u0026gt; 修改代码 给MainActivity添加两个属性\npublic class MainActivity extends AppCompatActivity { TextView textView; //用于显示时间 Timer timer;//用于定时刷新时间 ... } Android Basic Activity工程创建后，自带一个按钮，给按钮添加点击事件的处理\nfinal View.OnClickListener listener = new View.OnClickListener() { @Override public void onClick(View view) { final WindowManager.LayoutParams params = new WindowManager.LayoutParams(); // 类型 TYPE_SYSTEM_OVERLAY ，当悬浮窗口在其他App窗口上面时，不会隔断触摸事件，其他App能正常使用。 //若要隔断触摸事件，可以使用TYPE_SYSTEM_ALERT params.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; // 设置flag int flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; // | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; // 如果设置了WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE，弹出的View收不到Back键的事件 // FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口 // 设置 FLAG_NOT_FOCUSABLE 悬浮窗口较小时，后面的应用图标由不可长按变为可长按 params.flags = flags; // 不设置这个弹出框的透明遮罩显示为黑色 params.format = PixelFormat.TRANSLUCENT; params.width = 300; params.height = 50; params.gravity = Gravity.TOP; TextView top=new TextView(view.getContext()); //控件字体位置位于左边 top.setGravity(Gravity.LEFT); top.setText(\u0026#34;悬浮窗口\u0026#34;); WindowManager windowManager = (WindowManager)view.getContext().getApplicationContext().getSystemService(Context.WINDOW_SERVICE); windowManager.addView(top,params); textView = top; startTimer();//启动定时器（实现在后面） } }; FloatingActionButton fab = findViewById(R.id.fab); //添加点击事件处理 fab.setOnClickListener(listener); 定时器刷新时间\npublic void startTimer(){ timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { Date currentTime = new Date(); SimpleDateFormat formatter = new SimpleDateFormat(\u0026#34;yyyy-MM-dd HH:mm:ss\u0026#34;); final String dateString = formatter.format(currentTime); MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { textView.setText(dateString); } }); } },1000,300); } 完整代码如下\npackage com.zxs.windonwtimer; import android.content.Context; import android.graphics.PixelFormat; import android.os.Bundle; import com.google.android.material.floatingactionbutton.FloatingActionButton; import com.google.android.material.snackbar.Snackbar; import androidx.appcompat.app.AppCompatActivity; import androidx.appcompat.widget.Toolbar; import android.view.Gravity; import android.view.View; import android.view.Menu; import android.view.MenuItem; import android.view.ViewGroup; import android.view.WindowManager; import android.widget.TextView; import java.text.SimpleDateFormat; import java.util.Date; import java.util.Timer; import java.util.TimerTask; public class MainActivity extends AppCompatActivity { TextView textView; Timer timer; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_main); Toolbar toolbar = findViewById(R.id.toolbar); setSupportActionBar(toolbar); final View.OnClickListener listener = new View.OnClickListener() { @Override public void onClick(View view) { final WindowManager.LayoutParams params = new WindowManager.LayoutParams(); // 类型 params.type = WindowManager.LayoutParams.TYPE_SYSTEM_OVERLAY; // WindowManager.LayoutParams.TYPE_SYSTEM_ALERT // 设置flag int flags = WindowManager.LayoutParams.FLAG_ALT_FOCUSABLE_IM; // | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE; // 如果设置了WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE，弹出的View收不到Back键的事件 // FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口 // 设置 FLAG_NOT_FOCUSABLE 悬浮窗口较小时，后面的应用图标由不可长按变为可长按 // 不设置这个flag的话，home页的划屏会有问题 params.flags = flags; // 不设置这个弹出框的透明遮罩显示为黑色 params.format = PixelFormat.TRANSLUCENT; params.width = 300;//WindowManager.LayoutParams.MATCH_PARENT; params.height = 50;//WindowManager.LayoutParams.MATCH_PARENT; params.gravity = Gravity.TOP; TextView top=new TextView(view.getContext()); //控件字体位置位于左边 top.setGravity(Gravity.LEFT); top.setText(\u0026#34;悬浮窗口\u0026#34;); WindowManager windowManager = (WindowManager)view.getContext().getApplicationContext().getSystemService(Context.WINDOW_SERVICE); windowManager.addView(top,params); textView = top; startTimer(); } }; FloatingActionButton fab = findViewById(R.id.fab); fab.setOnClickListener(listener); } public void startTimer(){ timer = new Timer(); timer.schedule(new TimerTask() { @Override public void run() { Date currentTime = new Date(); SimpleDateFormat formatter = new SimpleDateFormat(\u0026#34;yyyy-MM-dd HH:mm:ss\u0026#34;); final String dateString = formatter.format(currentTime); MainActivity.this.runOnUiThread(new Runnable() { @Override public void run() { textView.setText(dateString); } }); } },1000,300); } @Override public boolean onCreateOptionsMenu(Menu menu) { // Inflate the menu; this adds items to the action bar if it is present. getMenuInflater().inflate(R.menu.menu_main, menu); return true; } @Override public boolean onOptionsItemSelected(MenuItem item) { // Handle action bar item clicks here. The action bar will // automatically handle clicks on the Home/Up button, so long // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); //noinspection SimplifiableIfStatement if (id == R.id.action_settings) { return true; } return super.onOptionsItemSelected(item); } } ","permalink":"https://blog.z6z8.cn/2019/12/18/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9Awindowmanager%E6%98%BE%E7%A4%BAandroid%E5%85%A8%E5%B1%80%E6%82%AC%E6%B5%AE%E7%AA%97%E5%8F%A3/","summary":"\u003cp\u003e我用Android手机装了个电商软件，抢购用。自己手机的状态栏不能显示秒级别的时间，只能精确到分钟。为了能准确的把握抢购时间，自己边学习边开发了一个时间显示悬浮窗。\u003c/p\u003e\n\u003ch1 id=\"windowmanager\"\u003eWindowManager\u003c/h1\u003e\n\u003cp\u003e\u003ca href=\"https://blog.csdn.net/robertcpp/article/details/51628643\" title=\"参考文章\"\u003e参考文章\u003c/a\u003e\nWindowManager可以在其他应用最上层，甚至手机桌面最上层显示窗口。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e使用Context.getSystemService(Context.WINDOW_SERVICE)来获取WindowManager。\u003c/li\u003e\n\u003cli\u003eAPI 17推出了Presentation，它将自动获取display的Context和WindowManager，可以方便地在另一个display上显示窗口\u003c/li\u003e\n\u003cli\u003e使用WindowManager继承自基类的addView方法和removeView方法来显示和隐藏窗口\u003c/li\u003e\n\u003cli\u003eWindowManager实现悬浮窗需要声明权限，在manifest中添加如下权限：\u003c/li\u003e\n\u003cli\u003e在MIUI上需要在设置中打开本应用的”显示悬浮窗”开关，并且重启应用，否则悬浮窗只能显示在本应用界面内，不能显示在手机桌面上。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"具体过程\"\u003e具体过程\u003c/h1\u003e\n\u003ch2 id=\"创建工程\"\u003e创建工程\u003c/h2\u003e\n\u003cp\u003e用Android Studio创建一个Android Basic Activity工程\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2019/12/BasicActivity.png\"\u003e\u003c/p\u003e\n\u003ch2 id=\"添加权限\"\u003e添加权限\u003c/h2\u003e\n\u003cp\u003e修改 \u003ccode\u003eAndroidManifest.xml\u003c/code\u003e，添加下面结构的数据\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u0026lt;?xml version=\u0026#34;1.0\u0026#34; encoding=\u0026#34;utf-8\u0026#34;?\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;manifest\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u0026lt;!--    显示顶层浮窗权限  --\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;uses-permission\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eandroid:name=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;android.permission.SYSTEM_ALERT_WINDOW\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/uses-permission\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/manifest\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"修改代码\"\u003e修改代码\u003c/h2\u003e\n\u003cp\u003e给MainActivity添加两个属性\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMainActivity\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e AppCompatActivity {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    TextView textView; \u003cspan style=\"color:#75715e\"\u003e//用于显示时间\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Timer timer;\u003cspan style=\"color:#75715e\"\u003e//用于定时刷新时间\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ...\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eAndroid Basic Activity工程创建后，自带一个按钮，给按钮添加点击事件的处理\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efinal\u003c/span\u003e View.\u003cspan style=\"color:#a6e22e\"\u003eOnClickListener\u003c/span\u003e listener \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e View.\u003cspan style=\"color:#a6e22e\"\u003eOnClickListener\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#a6e22e\"\u003e@Override\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eonClick\u003c/span\u003e(View view) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efinal\u003c/span\u003e WindowManager.\u003cspan style=\"color:#a6e22e\"\u003eLayoutParams\u003c/span\u003e params \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e WindowManager.\u003cspan style=\"color:#a6e22e\"\u003eLayoutParams\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// 类型 TYPE_SYSTEM_OVERLAY ，当悬浮窗口在其他App窗口上面时，不会隔断触摸事件，其他App能正常使用。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e//若要隔断触摸事件，可以使用TYPE_SYSTEM_ALERT\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                params.\u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e WindowManager.\u003cspan style=\"color:#a6e22e\"\u003eLayoutParams\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eTYPE_SYSTEM_OVERLAY\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// 设置flag\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e flags \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e WindowManager.\u003cspan style=\"color:#a6e22e\"\u003eLayoutParams\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eFLAG_ALT_FOCUSABLE_IM\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// | WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// 如果设置了WindowManager.LayoutParams.FLAG_NOT_FOCUSABLE，弹出的View收不到Back键的事件\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e               \u003cspan style=\"color:#75715e\"\u003e// FLAG_NOT_TOUCH_MODAL不阻塞事件传递到后面的窗口\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// 设置 FLAG_NOT_FOCUSABLE 悬浮窗口较小时，后面的应用图标由不可长按变为可长按\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                params.\u003cspan style=\"color:#a6e22e\"\u003eflags\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e flags;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e// 不设置这个弹出框的透明遮罩显示为黑色\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                params.\u003cspan style=\"color:#a6e22e\"\u003eformat\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e PixelFormat.\u003cspan style=\"color:#a6e22e\"\u003eTRANSLUCENT\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                params.\u003cspan style=\"color:#a6e22e\"\u003ewidth\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 300;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                params.\u003cspan style=\"color:#a6e22e\"\u003eheight\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 50;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                params.\u003cspan style=\"color:#a6e22e\"\u003egravity\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Gravity.\u003cspan style=\"color:#a6e22e\"\u003eTOP\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                TextView top\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e TextView(view.\u003cspan style=\"color:#a6e22e\"\u003egetContext\u003c/span\u003e());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e//控件字体位置位于左边\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                top.\u003cspan style=\"color:#a6e22e\"\u003esetGravity\u003c/span\u003e(Gravity.\u003cspan style=\"color:#a6e22e\"\u003eLEFT\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                top.\u003cspan style=\"color:#a6e22e\"\u003esetText\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;悬浮窗口\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                WindowManager windowManager \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (WindowManager)view.\u003cspan style=\"color:#a6e22e\"\u003egetContext\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003egetApplicationContext\u003c/span\u003e().\u003cspan style=\"color:#a6e22e\"\u003egetSystemService\u003c/span\u003e(Context.\u003cspan style=\"color:#a6e22e\"\u003eWINDOW_SERVICE\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                windowManager.\u003cspan style=\"color:#a6e22e\"\u003eaddView\u003c/span\u003e(top,params);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                textView \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e top;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                startTimer();\u003cspan style=\"color:#75715e\"\u003e//启动定时器（实现在后面）\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eFloatingActionButton fab \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e findViewById(R.\u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003efab\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//添加点击事件处理\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003efab.\u003cspan style=\"color:#a6e22e\"\u003esetOnClickListener\u003c/span\u003e(listener);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e定时器刷新时间\u003c/p\u003e","title":"学习笔记：WindowManager显示Android全局悬浮窗口"},{"content":"RSA加密算法是一种非对称加密算法. 对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之，对一极大整数做因数分解愈困难，RSA算法愈可靠。假如有人找到一种快速因数分解的算法的话，那么用RSA加密的信息的可靠性就肯定会极度下降。\n密钥 RSA为非对称加密算法，密钥分为私钥和公钥。 其中，公钥可以由私钥导出（意思就是，拥有私钥，也就拥有了公钥），而公钥不能导出私钥。\n密钥存储格式 比较常用的格式有ASN1.DER 和 PEM\nASN1.DER 是公钥或者私钥的采用ASN1.DER方式序列化，其结果是一串二进制数据 PEM 为Base64格式的文本，主要内容为ASN1.DER数据的Base64表达。另外，PEM允许使用指定的对称加密算法将加密，如DES等。 PEM格式的样例，中间的Base64文本其实就是ASN1.DER的Base64表示 -----BEGIN PUBLIC KEY----- MIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA04KNnZEBO3Ajk+nI4x/VKdoL F+yNv/KI0wCNF1J9do8Ra+MXUdDr+Nbehf6JYLuwHfur2mhw0gTT9lTLM2mD0qHo rbMs/XtSbXc9eP3xwJ/hU0V76LqtKw+y7GSgJ9XiyWS848DO2fV7uHdpwgRWCfHu R8fcUO0SrOHLj5g1HwIDAQAB -----END PUBLIC KEY----- 密钥长度 密钥长度越长，安全性越好，加密解密所需时间越长。 RSA长度有512、1024 、 2048 、 4096，一般使用时的最低长度为1024。\n参考 文章，密钥长度增长一倍，公钥操作所需时间增加约 4 倍，私钥操作所需时间增加约 8 倍，公私钥生成时间约增长 16 倍。\n加密与解密 RSA的加密密钥可以是公钥、也可以是私钥；解密亦然。\n公钥加密，私钥解密 私钥加密，公钥解密 块加密与补全模式 RSA也是一种分块加密算法，单次加密长度的上限时密钥长度，而当RSA使用PKCS1 补全模式时， padding 占用了 11 个字节，因此单次计算块长度约束 待加密的字节数不能超过密钥的比特长度值除以 8 再减去 11\n例如，密钥长度是1024比特，那么单次块最大长度 (1024 / 8 -11) = 117 字节 签名与验签 对于非对称加密算法来说，除了常规的加解密外，还可以用来签名与验签。\n签名用私钥 验签用公钥 另外，就RSA来讲，签名的摘要算法可以使用 MD5、 SHA1、 SHA2系列（如SHA256）\n","permalink":"https://blog.z6z8.cn/2019/12/17/%E7%BC%96%E7%A8%8B%E4%B9%8B%E8%B7%AF%E6%80%BB%E7%BB%93%EF%BC%9A%E5%8A%A0%E5%AF%86%E4%B8%8E%E8%A7%A3%E5%AF%86-rsa%E8%A6%81%E7%82%B9/","summary":"\u003cp\u003eRSA加密算法是一种非对称加密算法. 对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之，对一极大整数做因数分解愈困难，RSA算法愈可靠。假如有人找到一种快速因数分解的算法的话，那么用RSA加密的信息的可靠性就肯定会极度下降。\u003c/p\u003e\n\u003ch1 id=\"密钥\"\u003e密钥\u003c/h1\u003e\n\u003cp\u003eRSA为非对称加密算法，密钥分为私钥和公钥。\n其中，公钥可以由私钥导出（意思就是，拥有私钥，也就拥有了公钥），而公钥不能导出私钥。\u003c/p\u003e\n\u003ch2 id=\"密钥存储格式\"\u003e密钥存储格式\u003c/h2\u003e\n\u003cp\u003e比较常用的格式有ASN1.DER 和 PEM\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eASN1.DER 是公钥或者私钥的采用ASN1.DER方式序列化，其结果是一串二进制数据\u003c/li\u003e\n\u003cli\u003ePEM 为Base64格式的文本，主要内容为ASN1.DER数据的Base64表达。另外，PEM允许使用指定的对称加密算法将加密，如DES等。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ePEM格式的样例，中间的Base64文本其实就是ASN1.DER的Base64表示\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-----BEGIN PUBLIC KEY-----\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eMIGfMA0GCSqGSIb3DQEBAQUAA4GNADCBiQKBgQDA04KNnZEBO3Ajk+nI4x/VKdoL\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eF+yNv/KI0wCNF1J9do8Ra+MXUdDr+Nbehf6JYLuwHfur2mhw0gTT9lTLM2mD0qHo\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erbMs/XtSbXc9eP3xwJ/hU0V76LqtKw+y7GSgJ9XiyWS848DO2fV7uHdpwgRWCfHu\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eR8fcUO0SrOHLj5g1HwIDAQAB\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-----END PUBLIC KEY-----\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"密钥长度\"\u003e密钥长度\u003c/h2\u003e\n\u003cp\u003e密钥长度越长，安全性越好，加密解密所需时间越长。\nRSA长度有512、1024 、 2048 、 4096，一般使用时的最低长度为1024。\u003c/p\u003e\n\u003cp\u003e参考 \u003ca href=\"https://blog.csdn.net/liwei16611/article/details/83751851\" title=\"文章\"\u003e文章\u003c/a\u003e，密钥长度增长一倍，公钥操作所需时间增加约 4 倍，私钥操作所需时间增加约 8 倍，公私钥生成时间约增长 16 倍。\u003c/p\u003e\n\u003ch1 id=\"加密与解密\"\u003e加密与解密\u003c/h1\u003e\n\u003cp\u003eRSA的加密密钥可以是公钥、也可以是私钥；解密亦然。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e公钥加密，私钥解密\u003c/li\u003e\n\u003cli\u003e私钥加密，公钥解密\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"块加密与补全模式\"\u003e块加密与补全模式\u003c/h2\u003e\n\u003cp\u003eRSA也是一种分块加密算法，单次加密长度的上限时密钥长度，而当RSA使用PKCS1 补全模式时， padding 占用了 11 个字节，因此单次计算块长度约束\n\u003ccode\u003e待加密的字节数不能超过密钥的比特长度值除以 8 再减去 11\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e例如，密钥长度是1024比特，那么单次块最大长度\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e(1024 / 8 -11) = 117 字节\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"签名与验签\"\u003e签名与验签\u003c/h1\u003e\n\u003cp\u003e对于非对称加密算法来说，除了常规的加解密外，还可以用来签名与验签。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e签名用私钥\u003c/li\u003e\n\u003cli\u003e验签用公钥\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e另外，就RSA来讲，签名的摘要算法可以使用 \u003ccode\u003eMD5\u003c/code\u003e、 \u003ccode\u003eSHA1\u003c/code\u003e、 \u003ccode\u003eSHA2系列（如SHA256）\u003c/code\u003e\u003c/p\u003e","title":"编程之路总结：加密与解密--RSA要点"},{"content":"#pragma once //从ATL的base64库整理而来 //整理的目的是提供一个仅基于标准c++的base64库，提高代码的可移植性 #include \u0026lt;string\u0026gt; namespace Crypt { class Base64 { public: enum Base64_Flag { ATL_BASE64_FLAG_NONE = 0, // 0000 0000 标准的编码方式（RFC2045） ATL_BASE64_FLAG_NOPAD = 1 , // 0000 0001 没有补全（ = ） ATL_BASE64_FLAG_NOCRLF = 2 // 0000 0010 没有换行 ( crlf ) } ; //计算编码后的长度 static int EncodeGetRequiredLength(int nSrcLen, Base64_Flag dwFlags = ATL_BASE64_FLAG_NONE) { int nRet = static_cast\u0026lt;int\u0026gt;( (nSrcLen\u0026lt;\u0026lt;2) /3); if ((dwFlags \u0026amp; ATL_BASE64_FLAG_NOPAD) == 0)// 需要补全 = nRet += nSrcLen % 3; int nOnLastLine = nRet % 76; if (nOnLastLine) { if ( (nOnLastLine \u0026amp; 0x03) ) //nOnLastLine % 4 nRet += 4-(nOnLastLine \u0026amp; 0x03 ); } if ((dwFlags \u0026amp; ATL_BASE64_FLAG_NOCRLF) == 0) //需要换行符 { nRet += ((nRet / 76 + 1) \u0026lt;\u0026lt; 1) ;//(nRet / 76 + 1) * 2, 回车换行个数（+1是为了取最多值），根据rfc2045，编码后一行最多76个字符（不含换行） } return nRet; } inline static int DecodeGetRequiredLength(int nSrcLen) { return ((nSrcLen*3)\u0026gt;\u0026gt;2)+2; //(nSrcLen*3)/4+2 } //pbSrcData 要编码的原始数据 //nSrcLen 原始数据长度 //szDest 编码后的输出 //pnEncodeRealLen 编码后的实际长度 static bool Encode(const unsigned char *pbSrcData,int nSrcLen,char* szDest,int *pnEncodeRealLen,Base64_Flag dwFlags = ATL_BASE64_FLAG_NONE) { static const char *s_chBase64EncodingTable=\u0026#34;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\u0026#34;; if (!pbSrcData || !szDest || !pnEncodeRealLen) { return false; } int nWritten = 0 ; //编码后的长度，EncodeGetRequiredLength获得的长度通常大于实际长度 int nLen1 = (nSrcLen/3) \u0026lt;\u0026lt; 2; // (nSrcLen/3)*4 int nLen2 = nLen1/76 ; //RFC2045 base64编码后，每行最多76个字符 int nLen3 = 19 ; for (int i=0; i\u0026lt;=nLen2; i++) { if (i==nLen2) nLen3 = (nLen1%76)/4; for (int j=0; j\u0026lt;nLen3; j++) { unsigned long dwCurr = 0; for (int n=0; n\u0026lt;3; n++) { dwCurr |= *pbSrcData++; dwCurr \u0026lt;\u0026lt;= 8; } for (int k=0; k\u0026lt;4; k++) { unsigned char b = (unsigned char)(dwCurr\u0026gt;\u0026gt;26); *szDest++ = s_chBase64EncodingTable[b]; dwCurr \u0026lt;\u0026lt;= 6; } } nWritten+= nLen3*4; if ((dwFlags \u0026amp; ATL_BASE64_FLAG_NOCRLF)==0) { *szDest++ = \u0026#39;\\r\u0026#39;; *szDest++ = \u0026#39;\\n\u0026#39;; nWritten+= 2; } } if (nWritten \u0026amp;\u0026amp; (dwFlags \u0026amp; ATL_BASE64_FLAG_NOCRLF)==0) { szDest-= 2; nWritten -= 2; } nLen2 = (nSrcLen%3) ? (nSrcLen%3 + 1) : 0; if (nLen2) { unsigned long dwCurr = 0; for (int n=0; n\u0026lt;3; n++) { if (n\u0026lt;(nSrcLen%3)) dwCurr |= *pbSrcData++; dwCurr \u0026lt;\u0026lt;= 8; } for (int k=0; k\u0026lt;nLen2; k++) { unsigned char b = (unsigned char)(dwCurr\u0026gt;\u0026gt;26); *szDest++ = s_chBase64EncodingTable[b]; dwCurr \u0026lt;\u0026lt;= 6; } nWritten+= nLen2; if ((dwFlags \u0026amp; ATL_BASE64_FLAG_NOPAD)==0) { nLen3 = nLen2 ? 4-nLen2 : 0; for (int j=0; j\u0026lt;nLen3; j++) { *szDest++ = \u0026#39;=\u0026#39;; } nWritten+= nLen3; } } *pnEncodeRealLen = nWritten; return true; } //szSrc 要解码的数据 //nSrcLen 要解码数据的长度 //pbDest 解码后的输出 //pnDecodeRealLen 解码后的字节长度 static bool Decode(const char* szSrc, int nSrcLen, unsigned char *pbDest, int *pnDecodeRealLen) { // walk the source buffer // each four character sequence is converted to 3 bytes // CRLFs and =, and any characters not in the encoding table // are skiped // returns -1 if the character is invalid // or should be skipped // otherwise, returns the 6-bit code for the character // from the encoding table static const int base64_decode_table[] = { -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, 62, -1, -1, -1, 63, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, -1, -1, -1, -1, -1, -1, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, -1, -1, -1, -1, -1, -1, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1, -1 }; if (szSrc == 0 || pnDecodeRealLen == 0) { return false; } const char* szSrcEnd = szSrc + nSrcLen; int nWritten = 0; while (szSrc \u0026lt; szSrcEnd \u0026amp;\u0026amp;(*szSrc) != 0) { unsigned long dwCurr = 0; int i; int nBits = 0; for (i=0; i\u0026lt;4; i++) { if (szSrc \u0026gt;= szSrcEnd) break; int nCh = base64_decode_table[(unsigned char)(*szSrc)]; //强转为unsigned char，防止运行时抛出异常 szSrc++; if (nCh == -1) { // skip this char i--; continue; } dwCurr \u0026lt;\u0026lt;= 6; dwCurr |= nCh; nBits += 6; } // dwCurr has the 3 bytes to write to the output buffer // left to right dwCurr \u0026lt;\u0026lt;= 24-nBits; for (i=0; i\u0026lt;nBits/8; i++) { *pbDest = (unsigned char) ((dwCurr \u0026amp; 0x00ff0000) \u0026gt;\u0026gt; 16); pbDest++; dwCurr \u0026lt;\u0026lt;= 8; nWritten++; } } *pnDecodeRealLen = nWritten; return true; } static bool Encode(const std::string \u0026amp; in , std::string \u0026amp; out,Base64_Flag dwFlags = ATL_BASE64_FLAG_NONE) { int len = EncodeGetRequiredLength(static_cast\u0026lt;int\u0026gt;(in.size()),dwFlags); out.assign(len,0); bool ret=Encode((const unsigned char*)in.c_str(),static_cast\u0026lt;int\u0026gt;(in.size()),(char*)out.c_str(),\u0026amp;len,dwFlags); out.resize(static_cast\u0026lt;size_t\u0026gt;(len)); return ret; } static bool Encode( const unsigned char * in ,int in_len,std::string \u0026amp; out ,Base64_Flag dwFlags = ATL_BASE64_FLAG_NONE) { int len = EncodeGetRequiredLength(in_len,dwFlags); out.assign(len,0); bool ret=Encode(in ,in_len,(char*)out.c_str(),\u0026amp;len,dwFlags); out.resize(static_cast\u0026lt;size_t\u0026gt;(len)); return ret; } static bool Decode(const std::string \u0026amp; in, std::string \u0026amp; out ) { out.assign(in.size(),0); int len=static_cast\u0026lt;int\u0026gt;(out.size()); bool ret = Decode(in.c_str(),static_cast\u0026lt;int\u0026gt;(in.size()), (unsigned char*) out.c_str() , \u0026amp;len); out.resize(static_cast\u0026lt;size_t\u0026gt;(len)); return ret; } static bool Decode(const char * in ,int in_len , std::string \u0026amp; out ) { out.assign( static_cast\u0026lt;size_t\u0026gt;(in_len),0); int outlen=static_cast\u0026lt;int\u0026gt;(out.size()); bool ret = Decode(in ,in_len, (unsigned char*) out.c_str() , \u0026amp;outlen); out.resize(static_cast\u0026lt;size_t\u0026gt;(outlen)); return ret; } }; } ","permalink":"https://blog.z6z8.cn/2019/12/13/base64%E4%B8%80%E4%B8%AA%E4%BB%85%E5%9F%BA%E4%BA%8Ec%E7%9A%84%E5%AE%9E%E7%8E%B0/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-cpp\" data-lang=\"cpp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#pragma once\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//从ATL的base64库整理而来\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//整理的目的是提供一个仅基于标准c++的base64库，提高代码的可移植性\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;string\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003enamespace\u003c/span\u003e Crypt\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBase64\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eenum\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eBase64_Flag\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ATL_BASE64_FLAG_NONE \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, \u003cspan style=\"color:#75715e\"\u003e// 0000 0000  标准的编码方式（RFC2045）\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        ATL_BASE64_FLAG_NOPAD \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e , \u003cspan style=\"color:#75715e\"\u003e// 0000 0001  没有补全（ = ）\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        ATL_BASE64_FLAG_NOCRLF \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e// 0000 0010   没有换行 ( crlf )\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    } ;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//计算编码后的长度\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eEncodeGetRequiredLength\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e nSrcLen, Base64_Flag dwFlags \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ATL_BASE64_FLAG_NONE)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e nRet \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic_cast\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e( (nSrcLen\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ((dwFlags \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e ATL_BASE64_FLAG_NOPAD) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\u003cspan style=\"color:#75715e\"\u003e// 需要补全 =\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            nRet \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e nSrcLen \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e nOnLastLine \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e nRet \u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e76\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (nOnLastLine)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (  (nOnLastLine \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0x03\u003c/span\u003e)  ) \u003cspan style=\"color:#75715e\"\u003e//nOnLastLine % 4\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                nRet \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e(nOnLastLine \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0x03\u003c/span\u003e );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ((dwFlags \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e ATL_BASE64_FLAG_NOCRLF) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) \u003cspan style=\"color:#75715e\"\u003e//需要换行符\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            nRet \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e ((nRet \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e76\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) ;\u003cspan style=\"color:#75715e\"\u003e//(nRet / 76 + 1) * 2, 回车换行个数（+1是为了取最多值），根据rfc2045，编码后一行最多76个字符（不含换行）\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e nRet;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eDecodeGetRequiredLength\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e nSrcLen)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ((nSrcLen\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e//(nSrcLen*3)/4+2\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//pbSrcData  要编码的原始数据\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e//nSrcLen  原始数据长度\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e//szDest    编码后的输出\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e//pnEncodeRealLen       编码后的实际长度\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eEncode\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003epbSrcData,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e nSrcLen,\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e szDest,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003epnEncodeRealLen,Base64_Flag dwFlags \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ATL_BASE64_FLAG_NONE)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003es_chBase64EncodingTable\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003epbSrcData \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003eszDest \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003epnEncodeRealLen)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e false;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e nWritten \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; \u003cspan style=\"color:#75715e\"\u003e//编码后的长度，EncodeGetRequiredLength获得的长度通常大于实际长度\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e nLen1 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (nSrcLen\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e// (nSrcLen/3)*4\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e nLen2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e nLen1\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e76\u003c/span\u003e ;  \u003cspan style=\"color:#75715e\"\u003e//RFC2045 base64编码后，每行最多76个字符\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e nLen3 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e19\u003c/span\u003e ;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e i\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; i\u003cspan style=\"color:#f92672\"\u003e\u0026lt;=\u003c/span\u003enLen2; i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (i\u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003enLen2)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                nLen3 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (nLen1\u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e76\u003c/span\u003e)\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e j\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; j\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003enLen3; j\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e dwCurr \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e n\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; n\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e; n\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    dwCurr \u003cspan style=\"color:#f92672\"\u003e|=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003epbSrcData\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    dwCurr \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e k\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; k\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e; k\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e b \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e)(dwCurr\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e26\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eszDest\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e s_chBase64EncodingTable[b];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    dwCurr \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e6\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            nWritten\u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e nLen3\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ((dwFlags \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e ATL_BASE64_FLAG_NOCRLF)\u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eszDest\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\\r\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eszDest\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\\n\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                nWritten\u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (nWritten \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e (dwFlags \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e ATL_BASE64_FLAG_NOCRLF)\u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            szDest\u003cspan style=\"color:#f92672\"\u003e-=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            nWritten \u003cspan style=\"color:#f92672\"\u003e-=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        nLen2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (nSrcLen\u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e (nSrcLen\u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (nLen2)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e dwCurr \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e n\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; n\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e; n\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (n\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e(nSrcLen\u003cspan style=\"color:#f92672\"\u003e%\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    dwCurr \u003cspan style=\"color:#f92672\"\u003e|=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003epbSrcData\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                dwCurr \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e k\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; k\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003enLen2; k\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e b \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e)(dwCurr\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e26\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eszDest\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e s_chBase64EncodingTable[b];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                dwCurr \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e6\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            nWritten\u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e nLen2;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ((dwFlags \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e ATL_BASE64_FLAG_NOPAD)\u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                nLen3 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e nLen2 \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003enLen2 : \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e j\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; j\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003enLen3; j\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eszDest\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;=\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                nWritten\u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e nLen3;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003epnEncodeRealLen \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e nWritten;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e true;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//szSrc  要解码的数据\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e//nSrcLen  要解码数据的长度\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e//pbDest   解码后的输出\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e//pnDecodeRealLen  解码后的字节长度\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eDecode\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e szSrc, \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e nSrcLen, \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003epbDest, \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003epnDecodeRealLen)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// walk the source buffer\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#75715e\"\u003e// each four character sequence is converted to 3 bytes\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#75715e\"\u003e// CRLFs and =, and any characters not in the encoding table\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#75715e\"\u003e// are skiped\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// returns -1 if the character is invalid\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#75715e\"\u003e// or should be skipped\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#75715e\"\u003e// otherwise, returns the 6-bit code for the character\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#75715e\"\u003e// from the encoding table\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e base64_decode_table[] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e62\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e63\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e52\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e53\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e54\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e55\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e56\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e57\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e58\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e59\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e60\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e61\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,  \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e,  \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,  \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e,  \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e,  \u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e,  \u003cspan style=\"color:#ae81ff\"\u003e5\u003c/span\u003e,  \u003cspan style=\"color:#ae81ff\"\u003e6\u003c/span\u003e,  \u003cspan style=\"color:#ae81ff\"\u003e7\u003c/span\u003e,  \u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e,  \u003cspan style=\"color:#ae81ff\"\u003e9\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e11\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e12\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e13\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e14\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#ae81ff\"\u003e15\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e17\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e18\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e19\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e21\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e22\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e23\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e24\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e25\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e26\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e27\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e28\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#ae81ff\"\u003e29\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e30\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e31\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e32\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e33\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e34\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e35\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e36\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e37\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e38\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e39\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e40\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e41\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e42\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e43\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e44\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e45\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e46\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e47\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e48\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#ae81ff\"\u003e49\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e50\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e51\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (szSrc \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e pnDecodeRealLen \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e false;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e szSrcEnd \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e szSrc \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e nSrcLen;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e nWritten \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e (szSrc \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e szSrcEnd \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eszSrc) \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e dwCurr \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e i;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e nBits \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (i\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; i\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e; i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (szSrc \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e szSrcEnd)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e nCh \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e base64_decode_table[(\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e)(\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eszSrc)]; \u003cspan style=\"color:#75715e\"\u003e//强转为unsigned char，防止运行时抛出异常\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                szSrc\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (nCh \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#75715e\"\u003e// skip this char\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    i\u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003econtinue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                dwCurr \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e6\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                dwCurr \u003cspan style=\"color:#f92672\"\u003e|=\u003c/span\u003e nCh;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                nBits \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e6\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// dwCurr has the 3 bytes to write to the output buffer\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            \u003cspan style=\"color:#75715e\"\u003e// left to right\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            dwCurr \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e24\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003enBits;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (i\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; i\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003enBits\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e; i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003epbDest \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e) ((dwCurr \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0x00ff0000\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                pbDest\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                dwCurr \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                nWritten\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003epnDecodeRealLen \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e nWritten;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e true;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eEncode\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e in , std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e out,Base64_Flag dwFlags \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ATL_BASE64_FLAG_NONE)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e len \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e EncodeGetRequiredLength(\u003cspan style=\"color:#66d9ef\"\u003estatic_cast\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e(in.size()),dwFlags);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        out.assign(len,\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e ret\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eEncode((\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)in.c_str(),\u003cspan style=\"color:#66d9ef\"\u003estatic_cast\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e(in.size()),(\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)out.c_str(),\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003elen,dwFlags);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        out.resize(\u003cspan style=\"color:#66d9ef\"\u003estatic_cast\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003esize_t\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e(len));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ret;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eEncode\u003c/span\u003e( \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e in ,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e in_len,std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e out ,Base64_Flag dwFlags \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ATL_BASE64_FLAG_NONE)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e len \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e EncodeGetRequiredLength(in_len,dwFlags);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        out.assign(len,\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e ret\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003eEncode(in ,in_len,(\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)out.c_str(),\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003elen,dwFlags);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        out.resize(\u003cspan style=\"color:#66d9ef\"\u003estatic_cast\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003esize_t\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e(len));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ret;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eDecode\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e in, std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e out )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        out.assign(in.size(),\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e len\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003estatic_cast\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e(out.size());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e ret \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Decode(in.c_str(),\u003cspan style=\"color:#66d9ef\"\u003estatic_cast\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e(in.size()), (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e) out.c_str() , \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003elen);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        out.resize(\u003cspan style=\"color:#66d9ef\"\u003estatic_cast\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003esize_t\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e(len));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ret;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eDecode\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e in ,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e in_len , std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e out )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        out.assign( \u003cspan style=\"color:#66d9ef\"\u003estatic_cast\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003esize_t\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e(in_len),\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e outlen\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003estatic_cast\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e(out.size());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e ret \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Decode(in ,in_len, (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e) out.c_str() , \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eoutlen);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        out.resize(\u003cspan style=\"color:#66d9ef\"\u003estatic_cast\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003esize_t\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e(outlen));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ret;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Base64:一个仅基于C++的实现"},{"content":" //在升序数组中，查找插入索引 ,插入索引是第一个恰当的位置（多个相同元素的第一个元素位置） //existSame ,输出YES时，返回的索引是相等的元素索引，输出NO，返回的索引是需要插入的位置索引 NSUInteger FindInsertIndex(NSArray * ascSortedItmes , id obj, BOOL \u0026amp;existSame, int(^CompareTwoItem)(id item, id obj)) { existSame = NO; NSUInteger count = [ascSortedItmes count]; if (count \u0026gt; 0) { NSUInteger midIndex ,startIndex = 0 , endIndex = count -1 , safeN = count; while (safeN--) //safeN 保证while一定会结束 ,可以去掉这个判断 { midIndex = ((startIndex + endIndex) \u0026gt;\u0026gt; 1); // (startIndex + endIndex) / 2 id item = ascSortedItmes[midIndex]; int cmp = CompareTwoItem(item ,obj); if (cmp \u0026gt;0 ) // item \u0026gt; obj { if (endIndex == startIndex // 此时 endIndex == midIndex == startIndex || midIndex == 0 ) { return midIndex; } endIndex = midIndex -1; } else if (cmp == 0) //处理相等情况，确保插入的索引是第一个恰当的索引(多个相同元素的第一个元素位置) { if (midIndex == startIndex) //此时，startIndex到endIndex最多两个元素 { existSame = YES; return midIndex; } endIndex = midIndex; } else // item \u0026lt; obj { startIndex = midIndex + 1; if (startIndex \u0026gt; endIndex) // 此时 midIndex == endIndex { return (startIndex \u0026lt; count) ? startIndex : count; } } } ASSERT(0);//上面查找算法有问题 return count;//表示附加到末尾 } else { return 0; } } ","permalink":"https://blog.z6z8.cn/2019/12/13/objective-c%E5%9C%A8%E5%8D%87%E5%BA%8F%E6%95%B0%E7%BB%84%E4%B8%AD%E4%BD%BF%E7%94%A8%E4%BA%8C%E5%88%86%E6%B3%95%E6%9F%A5%E6%89%BE%E5%85%83%E7%B4%A0/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//在升序数组中，查找插入索引 ,插入索引是第一个恰当的位置（多个相同元素的第一个元素位置）\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//existSame ,输出YES时，返回的索引是相等的元素索引，输出NO，返回的索引是需要插入的位置索引\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003eNSUInteger \u003cspan style=\"color:#a6e22e\"\u003eFindInsertIndex\u003c/span\u003e(NSArray \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e ascSortedItmes , \u003cspan style=\"color:#66d9ef\"\u003eid\u003c/span\u003e obj, \u003cspan style=\"color:#66d9ef\"\u003eBOOL\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eexistSame,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                           \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003eCompareTwoItem)(\u003cspan style=\"color:#66d9ef\"\u003eid\u003c/span\u003e item, \u003cspan style=\"color:#66d9ef\"\u003eid\u003c/span\u003e obj))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    existSame \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e NO;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSUInteger count \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [ascSortedItmes count];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (count \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        NSUInteger midIndex ,startIndex \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e , endIndex \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e count \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e ,  safeN \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e count;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e (safeN\u003cspan style=\"color:#f92672\"\u003e--\u003c/span\u003e) \u003cspan style=\"color:#75715e\"\u003e//safeN 保证while一定会结束 ,可以去掉这个判断\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            midIndex \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ((startIndex \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e endIndex) \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e); \u003cspan style=\"color:#75715e\"\u003e// (startIndex + endIndex) / 2\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            \u003cspan style=\"color:#66d9ef\"\u003eid\u003c/span\u003e item \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ascSortedItmes[midIndex];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e cmp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e CompareTwoItem(item ,obj);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (cmp \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ) \u003cspan style=\"color:#75715e\"\u003e//  item \u0026gt; obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (endIndex \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e startIndex \u003cspan style=\"color:#75715e\"\u003e// 此时  endIndex == midIndex == startIndex\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e midIndex \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e midIndex;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                endIndex \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e midIndex \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (cmp \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) \u003cspan style=\"color:#75715e\"\u003e//处理相等情况，确保插入的索引是第一个恰当的索引(多个相同元素的第一个元素位置)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (midIndex \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e startIndex) \u003cspan style=\"color:#75715e\"\u003e//此时，startIndex到endIndex最多两个元素\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    existSame \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YES;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e midIndex;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                endIndex \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e midIndex;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e// item \u0026lt; obj\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                startIndex \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e midIndex \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (startIndex \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e endIndex) \u003cspan style=\"color:#75715e\"\u003e// 此时 midIndex == endIndex\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e (startIndex \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e count) \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e startIndex : count;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        ASSERT(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\u003cspan style=\"color:#75715e\"\u003e//上面查找算法有问题\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e count;\u003cspan style=\"color:#75715e\"\u003e//表示附加到末尾\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Objective-C在升序数组中使用二分法查找元素"},{"content":"先摘录一段百度百科的文字: 密码学（在西欧语文中，源于希腊语kryptós“隐藏的”，和gráphein“书写”）是研究如何隐密地传递信息的学科.\n密码学的历史很长，人类使用密码的历史几乎与使用文字的时间一样长。古典密码学、近代密码学、现代密码学\u0026hellip;\u0026hellip;详细请阅读 这里\n在现代，密码技术大部分都和计算机紧密相关，因为计算了实在是太大了。做过基础应用开发的话，一般会对密码工具或加密工具有所了解，接触一些 CryptoXXX 或 XXXCrypto 工具库。Crypto是不是和希腊语kryptós很像？😄😄😄\n好了，说些我懂的吧。我从软件编程的角度谈下自己的体会。\n算法分类 在学习和使用Crypto类的加解密工具库时，尤其是在查看和使用其提供API时，要明白这后面对应的是什么算法、在什么场景下使用。 当前，我们常用的算法可以分为三类：\n摘要算法，也称散列、哈希算法，也有叫做单向加密算法的。严格来说，这不是加密算法\u0026mdash;-摘要算法是一种操作不可逆的算法，不能反向解密出原始数据。它应用的场景往往是完整性、真实性校验，例如数字签名。 对称加密算法。指加密和解密的密钥都是同一个，通常是加密方和解密方预先共同约定一个密钥。在非对称加密算法 非对称加密算法，公钥加密算法。这和对称加密算法相对应，指加密密钥和解密密钥不是同一个。著名的应用场景就是TLS/SSL（HTTPS的 S 指的是TLS/SSL） 摘要（Digest） 也叫杂凑、哈希；就是把任意长度的输入，通过散列算法，变换成固定长度的输出，该输出就是散列值。这种转换是一种压缩映射，也就是，散列值的空间通常远小于输入的空间，不同的输入可能会散列成相同的输出，而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。例如MD5是将数据散列到128比特（16字节）上。\nMD5 英文 MD5 Message-Digest Algorithm. 是第5代摘要算法，前面还有MD2、MD4。\nMD5由美国密码学家罗纳德·李维斯特（Ronald Linn Rivest）设计，于1992年公开，用以取代MD4算法。这套算法的程序在 RFC 1321 标准中被加以规范。1996年后该算法被证实存在弱点，可以被加以破解，对于需要高度安全性的数据，专家一般建议改用其他算法，如SHA-2。2004年，证实MD5算法无法防止碰撞（collision），因此不适用于安全性认证，如SSL公开密钥认证或是数字签名等用途。\u0026ndash;摘自百度百科。\n算法输入单次计算块输出MD2任意数据，包括空数据512比特（64字节）128比特（16字节）MD4任意数据，包括空数据512比特（64字节）128比特（16字节）MD5任意数据，包括空数据512比特（64字节）128比特（16字节）\nMD5的计算结果不存在32位、16位之分，其结果就是16字节、128比特。32位、16位之说是极其不专业的。\nMD5已经被证明不安全，但这并不影响我们继续使用，只需要我们将应用范围缩小到不涉及安全方面就可以了。 例如，\n我们仍然可以使用MD5来校验非核心文件的完整性。 用MD5将URL映射到本地文件名，以帮助实现缓存功能。（通常在客户端使用MD5时，是不考虑MD5的碰撞概率的）。 SHA系列 英语 Secure Hash Algorithm，缩写为SHA\n算法输入单次计算块输出SHA10 ~ (2^64 - 1)字节，包括空数据512比特（64字节）160比特（20字节）SHA2240 ~ (2^64 - 1)字节，包括空数据512比特（64字节）224比特（28字节）SHA2560 ~ (2^64 - 1)字节，包括空数据512比特（64字节）256比特（32字节）SHA3840 ~ (2^128 - 1)字节，包括空数据1024比特（128字节）284比特（48字节）SHA5120 ~ (2^128 - 1)字节，包括空数据1024比特（128字节）512比特（64字节）\nSHA224、SHA256、SHA384、SHA512统称为SHA2。当前，SHA1已经被证明不安全了（Google曾公布过两幅不同的有意义的图片，但其SHA1值是一样的，这在法律上是极其可怕的事）。 SHA2在安全领域仍然继续服役着。\nSHA系列的最新标准已经有了SHA3系列，详情可以参考维基百科 SHA3\nSM3 我国SM3密码算法正式成为ISO/IEC国际标准\nSM3是中华人民共和国政府采用的一种密码散列函数标准,相关标准为“GM/T 0004-2012 《SM3密码杂凑算法》”。 在商用密码体系中，SM3主要用于数字签名及验证、消息认证码生成及验证、随机数生成等，其算法公开。据国家密码管理局表示，其安全性及效率与SHA256相当。 SM3 算法的哈希值大小为 256 比特。\n算法输入单次计算块输出SM30 ~ (2^64 - 1)字节，包括空数据512比特（64字节）256比特（16字节）\n对称加密 对称加密(Symmetry Crypto)，采用单钥密码系统的加密方法，加密和解密所使用的密钥是同一个。例如DES、3DES、AES、SM4等。\nChacha20,流式加密的算法，也属于对称加密；Google发布并用于取代RC4算法。本文不涉及，详细可自行搜索。\n其安全性不仅取决于加密算法本身，密钥管理的安全性更是重要。 通常对称加密的速度较快，在加密大量数据的场景，对称加密是首选。\nAES 高级加密标准（英语：Advanced Encryption Standard，缩写：AES），是美国联邦政府采用的一种区块加密标准。这个标准用来替代原先的DES，已经被多方分析且广为全世界所使用。 AES的区块长度固定为128 比特，密钥长度则可以是128，192或256比特;需要注意，AES中初始化向量(IV)的长度固定为128比特\n算法输入单次计算块KEY长度IV长度输出AES128任意，包括空数据128比特（16字节）128比特（16字节）128比特（16字节）最大长度 = 输入长度+128比特）AES192任意，包括空数据128比特（16字节）192比特（24字节）128比特（16字节）最大长度 = 输入长度+128比特AES256任意，包括空数据128比特（16字节）256比特（32字节）128比特（16字节）最大长度 = 输入长度+128比特\nAES加密几个要点 摘自https://139.155.43.7/2019/11/21/ssl-evp%e6%a1%86%e6%9e%b6%ef%bc%9aaes%e5%8a%a0%e5%af%86/\n对称加密(Symmetry Crypto) 加密和解密的钥匙是同一把\u0026mdash;-加密方和解密方拥有相同的密钥（音yue，四声）。\n密钥(key) 任意数据（不一定非得字符串），长度常见为128比特、192比特、256比特，也有支持512比特的算法库\n初始化向量(IV) 这不是AES算法标准强制要求的，是一种增加AES破解难度的手段。IV和密钥共同参与加密和解密运算。IV长度固定为128比特。\n加密块(block) 每次加密的块长度都是128比特；输入和输出长度相同，考虑补全模式的情况下，输出的最大长度 = 输入长度+128比特\n加密模式 是指当需要加密的源数据长度大于128比特时，加密块和加密块之间的运算模式。 常见的有 CBC密码分组链接模式、ECB电码本模式（不推荐）、CTR计算器模式、CFB密码反馈模式、OFB输出反馈模式。\n补全模式模式（padding） 因为AES一个加密块为16字节，当源数据的最后一个块不足16字节时，需要手动补全为16字节。\n一般使用PKCS7模式，手动补全N个N，N为不足的字节数。\nSM4 SM4（原名SMS4）是中华人民共和国政府采用的一种分组密码标准,其设计安全性等同于AES-128，但是近年来的一些密码分析表明的其全性略弱于AES-128. 在商用密码体系中，SM4主要用于数据加密，其算法公开，分组长度与密钥长度均为128bit，\n非对称加密 非对称加密，是指加密和解密的密钥不是同一个，是一对密钥\u0026ndash;密钥对，分为公钥和私钥。非对称加密算法也称\u0026quot;公钥加密算法\u0026quot;\n公钥（publickey），是公开的；私钥（privatekey），只被通信的一方持有，保密的。如果用公钥对数据进行加密，只有用对应的私钥才能解密。\n和对称加密比起来，非对称加密通常速度较慢，但安全强度很高。所以，非对称加密一般用来传输或保密对称密钥。\n当前比较流行的两种算法是\n基于极大整数做因数分解，以RSA为代表 ECC类，基于椭圆曲线数学，如SM2。 通常，基于椭圆曲线的加密算法强度大于基于极大整数做因数分解的加密算法。\nRSA RSA加密算法是一种非对称加密算法. 对极大整数做因数分解的难度决定了RSA算法的可靠性。换言之，对一极大整数做因数分解愈困难，RSA算法愈可靠。假如有人找到一种快速因数分解的算法的话，那么用RSA加密的信息的可靠性就肯定会极度下降。\n另外，RSA也是一种分块加密算法。\n算法输入单次计算块输出RSA任意数据待加密的字节数不能超过密钥的比特长度值除以 8 再减去 11）最大长度 = （输入长度 x 密钥长度）/( 密钥长度 - 11)\nSM2 我国SM2密码算法正式成为ISO/IEC国际标准\nSM2是国家密码管理局于2010年12月17日发布的椭圆曲线公钥密码算法，属于ECC算法的一种，其可靠性基于椭圆曲线数学（RSA基于极大整数做因数分解难题）。\nSM2也是一种分块加密算法。\nSM9 我国SM9密码算法正式成为ISO/IEC国际标准\n有空再单开一篇文章介绍吧。\n","permalink":"https://blog.z6z8.cn/2019/12/13/%E7%BC%96%E7%A8%8B%E4%B9%8B%E8%B7%AF%E6%80%BB%E7%BB%93%EF%BC%9A%E5%8A%A0%E5%AF%86%E4%B8%8E%E8%A7%A3%E5%AF%86%EF%BC%88%E4%B8%80%EF%BC%89/","summary":"\u003cp\u003e先摘录一段百度百科的文字:\n\u003ccode\u003e密码学（在西欧语文中，源于希腊语kryptós“隐藏的”，和gráphein“书写”）是研究如何隐密地传递信息的学科.\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e密码学的历史很长，人类使用密码的历史几乎与使用文字的时间一样长。古典密码学、近代密码学、现代密码学\u0026hellip;\u0026hellip;详细请阅读 \u003ca href=\"https://blog.csdn.net/jiang_xinxing/article/details/89360638\" title=\"这里\"\u003e这里\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e在现代，密码技术大部分都和计算机紧密相关，因为计算了实在是太大了。做过基础应用开发的话，一般会对密码工具或加密工具有所了解，接触一些 \u003ccode\u003eCryptoXXX\u003c/code\u003e 或 \u003ccode\u003eXXXCrypto\u003c/code\u003e 工具库。Crypto是不是和希腊语kryptós很像？😄😄😄\u003c/p\u003e\n\u003cp\u003e好了，说些我懂的吧。我从软件编程的角度谈下自己的体会。\u003c/p\u003e\n\u003ch1 id=\"算法分类\"\u003e算法分类\u003c/h1\u003e\n\u003cp\u003e在学习和使用Crypto类的加解密工具库时，尤其是在查看和使用其提供API时，要明白这后面对应的是什么算法、在什么场景下使用。\n当前，我们常用的算法可以分为三类：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e摘要算法，也称散列、哈希算法，也有叫做单向加密算法的。严格来说，这不是加密算法\u0026mdash;-摘要算法是一种操作不可逆的算法，不能反向解密出原始数据。它应用的场景往往是完整性、真实性校验，例如数字签名。\u003c/li\u003e\n\u003cli\u003e对称加密算法。指加密和解密的密钥都是同一个，通常是加密方和解密方预先共同约定一个密钥。在非对称加密算法\u003c/li\u003e\n\u003cli\u003e非对称加密算法，公钥加密算法。这和对称加密算法相对应，指加密密钥和解密密钥不是同一个。著名的应用场景就是TLS/SSL（HTTPS的 \u003ccode\u003eS\u003c/code\u003e 指的是TLS/SSL）\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"摘要digest\"\u003e摘要（Digest）\u003c/h1\u003e\n\u003cp\u003e也叫杂凑、哈希；就是把任意长度的输入，通过散列算法，变换成固定长度的输出，该输出就是散列值。这种转换是一种压缩映射，也就是，散列值的空间通常远小于输入的空间，不同的输入可能会散列成相同的输出，而不可能从散列值来唯一的确定输入值。简单的说就是一种将任意长度的消息压缩到某一固定长度的消息摘要的函数。例如MD5是将数据散列到128比特（16字节）上。\u003c/p\u003e\n\u003ch2 id=\"md5\"\u003eMD5\u003c/h2\u003e\n\u003cp\u003e英文 MD5 Message-Digest Algorithm. 是第5代摘要算法，前面还有MD2、MD4。\u003c/p\u003e\n\u003cp\u003eMD5由美国密码学家罗纳德·李维斯特（Ronald Linn Rivest）设计，于1992年公开，用以取代MD4算法。这套算法的程序在 RFC 1321 标准中被加以规范。1996年后该算法被证实存在弱点，可以被加以破解，对于需要高度安全性的数据，专家一般建议改用其他算法，如SHA-2。2004年，证实MD5算法无法防止碰撞（collision），因此不适用于安全性认证，如SSL公开密钥认证或是数字签名等用途。\u0026ndash;摘自百度百科。\u003c/p\u003e\n\u003cp\u003e算法输入单次计算块输出MD2任意数据，包括空数据512比特（64字节）128比特（16字节）MD4任意数据，包括空数据512比特（64字节）128比特（16字节）MD5任意数据，包括空数据512比特（64字节）128比特（16字节）\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eMD5的计算结果不存在32位、16位之分，其结果就是16字节、128比特。32位、16位之说是极其不专业的。\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003eMD5已经被证明不安全，但这并不影响我们继续使用，只需要我们将应用范围缩小到不涉及安全方面就可以了。\n例如，\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e我们仍然可以使用MD5来校验非核心文件的完整性。\u003c/li\u003e\n\u003cli\u003e用MD5将URL映射到本地文件名，以帮助实现缓存功能。（通常在客户端使用MD5时，是不考虑MD5的碰撞概率的）。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch2 id=\"sha系列\"\u003eSHA系列\u003c/h2\u003e\n\u003cp\u003e英语 Secure Hash Algorithm，缩写为SHA\u003c/p\u003e\n\u003cp\u003e算法输入单次计算块输出SHA10 ~ (2^64 - 1)字节，包括空数据512比特（64字节）160比特（20字节）SHA2240 ~ (2^64 - 1)字节，包括空数据512比特（64字节）224比特（28字节）SHA2560 ~ (2^64 - 1)字节，包括空数据512比特（64字节）256比特（32字节）SHA3840 ~ (2^128 - 1)字节，包括空数据1024比特（128字节）284比特（48字节）SHA5120 ~ (2^128 - 1)字节，包括空数据1024比特（128字节）512比特（64字节）\u003c/p\u003e\n\u003cp\u003eSHA224、SHA256、SHA384、SHA512统称为SHA2。当前，SHA1已经被证明不安全了（Google曾公布过两幅不同的有意义的图片，但其SHA1值是一样的，这在法律上是极其可怕的事）。\nSHA2在安全领域仍然继续服役着。\u003c/p\u003e\n\u003cp\u003eSHA系列的最新标准已经有了SHA3系列，详情可以参考维基百科 \u003ca href=\"https://zh.wikipedia.org/wiki/SHA-3\" title=\"SHA3\"\u003eSHA3\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"sm3\"\u003eSM3\u003c/h2\u003e\n\u003cblockquote\u003e\n\u003cp\u003e我国SM3密码算法正式成为ISO/IEC国际标准\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003cp\u003eSM3是中华人民共和国政府采用的一种密码散列函数标准,相关标准为“GM/T 0004-2012 《SM3密码杂凑算法》”。\n在商用密码体系中，SM3主要用于数字签名及验证、消息认证码生成及验证、随机数生成等，其算法公开。据国家密码管理局表示，其安全性及效率与SHA256相当。\nSM3 算法的哈希值大小为 256 比特。\u003c/p\u003e","title":"编程之路总结：加密与解密"},{"content":"安装 sudo npm install uglify-js -g -g 全局安装 简单使用 uglifyjs 文件1 文件2 文件3 -c -m -o 输出文件 # 例如 uglifyjs a.js b.js c.js -c -m -o result.js -c 压缩输入文件（删除空白字符，注释等，而非常见的zip压缩） -m 混淆符号，这个是轻量的混淆，把长符号替换成端符号 -o 输出文件 ","permalink":"https://blog.z6z8.cn/2019/12/09/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9Auglifyjs-%E6%B7%B7%E6%B7%86javascript/","summary":"\u003ch1 id=\"安装\"\u003e安装\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo npm install uglify-js -g\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e-g 全局安装\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"简单使用\"\u003e简单使用\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003euglifyjs 文件1 文件2 文件3  -c -m -o 输出文件\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# 例如\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003euglifyjs  a.js  b.js  c.js  -c -m -o result.js\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003e-c 压缩输入文件（删除空白字符，注释等，而非常见的zip压缩）\u003c/li\u003e\n\u003cli\u003e-m 混淆符号，这个是轻量的混淆，把长符号替换成端符号\u003c/li\u003e\n\u003cli\u003e-o 输出文件\u003c/li\u003e\n\u003c/ul\u003e","title":"学习笔记：uglifyjs 混淆JavaScript"},{"content":"本文谷歌翻译.\n正文 为程序生命周期中的特定事件建立了配置基准，并有助于程序的“获取程序基准”（APB）的绩效部分。 总体技术基准汇总到APB中，并包含以下配置基准：\nA Configuration Baseline is established for specific events in a programs life-cycle and contributes to the performance portion of a program’s Acquisition Program Baseline (APB). The overall Technical Baseline rolls up into the APB and consists of the following configuration baselines:\n功能基准(Functional Baseline) 定义所需的系统功能，以描述整个系统的功能和接口特性，并进行验证以证明实现了这些指定功能特性。 该基准来自功能开发文档（CDD），通常包括整个系统的详细功能性能规范以及验证和验证总体系统性能所需的测试。\n通常在系统功能审查（SFR）中建立功能基线并将其置于配置控制之下。 通常使用系统验证审查（SVR）和/或功能配置审核（FCA）对其进行验证。\nDefinition of the required system functionality describing functional and interface characteristics of the overall system, and the verification required to demonstrate the achievement of those specified functional characteristics. This baseline is derived from the Capability Development Document (CDD) and normally includes a detailed functional performance specification for the overall system and the tests necessary to verify and validate overall system performance.\nThe functional baseline is normally established and put under configuration control at the System Functional Review (SFR). It is usually verified with a System Verification Review (SVR) and/or a Functional Configuration Audit (FCA).\n分配基准(Allocated Baseline) 定义组成系统的配置项，然后如何在较低级别的配置项之间分配系统功能和性能要求（因此分配基线一词）。它包括从顶级系统或更高级别的配置项分配的所有功能和接口特性，派生的要求，与其他配置项的接口要求，设计约束以及为证明指定功能，性能的可追溯性和实现而进行的验证以及界面特征。分配的基准中每个配置项目的性能都在其初步设计规范中进行了描述，验证和验证配置项目性能所需的测试也是如此。\n通常在每个配置项（硬件和软件）的初步设计审查（PDR）中建立分配的基准并将其置于配置控制下，最终达到在系统级PDR建立的系统分配的基准。\nDefinition of the configuration items making up a system, and then how system function and performance requirements are allocated across lower level configuration items (hence the term allocated baseline). It includes all functional and interface characteristics that are allocated from the top level system or higher-level configuration items, derived requirements, interface requirements with other configuration items, design constraints, and the verification required to demonstrate the traceability and achievement of specified functional, performance, and interface characteristics. The performance of each configuration item in the allocated baseline is described in its preliminary design specification as are the tests necessary to verify and validate configuration item performance.\nThe allocated baseline is usually established and put under configuration control at each configuration item’s (hardware and software) Preliminary Design Review (PDR), culminating in a system allocated baseline established at the system-level PDR.\n产品基准(Product Baseline) 描述配置项所有必要的功能和物理特性的文档；指定用于生产验收测试的所选功能和物理特性；以及部署/安装，操作，支持，培训和处置配置项所需的测试。最初的产品基准包括硬件（产品，过程，材料规格，工程图和其他相关数据）和软件的“内置”规格（软件模块设计-“代码至”规格）。通常会在每个配置项的关键设计评审（CDR）中建立初始产品基准并将其置于配置控制下，最终达到在系统级CDR上建立的初始系统产品基准。根据DoD策略，PM应在系统级CDR之后承担对该初始产品基准的控制，并控制所有1类更改。在完成系统验证审查（SVR）和/或FCA之前，第1类更改应为那些影响政府绩效规范的更改。根据SVR / FCA，政府将在合同上进一步定义什么构成1级变更。系统产品基线已在物理配置审核（PCA）中完成并验证。\nDocumentation describing all of the necessary functional and physical characteristics of a configuration item; the selected functional and physical characteristics designated for production acceptance testing; and tests necessary for deployment/installation, operation, support, training, and disposal of the configuration item. The initial product baseline includes “build-to” specifications for hardware (product, process, material specifications, engineering drawings, and other related data) and software (software module design— “code-to” specifications). The Initial product baseline is usually established and put under configuration control at each configuration item’s Critical Design Review (CDR), culminating in an initial system product baseline established at the system-level CDR. By DoD policy, the PM shall assume control over this initial product baseline after the system-level CDR and control all Class 1 changes. Until completion of the System Verification Review (SVR) and/or FCA, Class 1 changes shall be those changes that affect the government performance specification. Following the SVR/FCA, the government will further define contractually what constitutes a Class 1 change. The system product baseline is finalized and validated at the Physical Configuration Audit (PCA).\n源文 http://acqnotes.com/acqnote/careerfields/configuration-baselines\n","permalink":"https://blog.z6z8.cn/2019/12/06/%E7%BF%BB%E8%AF%91%EF%BC%9A%E7%B3%BB%E7%BB%9F%E5%B7%A5%E7%A8%8B%E4%B9%8B%E9%85%8D%E7%BD%AE%E5%9F%BA%E5%87%86/","summary":"\u003cp\u003e本文谷歌翻译.\u003c/p\u003e\n\u003ch1 id=\"正文\"\u003e正文\u003c/h1\u003e\n\u003cp\u003e为程序生命周期中的特定事件建立了配置基准，并有助于程序的“获取程序基准”（APB）的绩效部分。 总体技术基准汇总到APB中，并包含以下配置基准：\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eA Configuration Baseline is established for specific events in a programs life-cycle and contributes to the performance portion of a program’s Acquisition Program Baseline (APB). The overall Technical Baseline rolls up into the APB and consists of the following configuration baselines:\u003c/em\u003e\u003c/p\u003e\n\u003ch2 id=\"功能基准functional-baseline\"\u003e功能基准(Functional Baseline)\u003c/h2\u003e\n\u003cp\u003e定义所需的系统功能，以描述整个系统的功能和接口特性，并进行验证以证明实现了这些指定功能特性。 该基准来自功能开发文档（CDD），通常包括整个系统的详细功能性能规范以及验证和验证总体系统性能所需的测试。\u003c/p\u003e\n\u003cp\u003e通常在系统功能审查（SFR）中建立功能基线并将其置于配置控制之下。 通常使用系统验证审查（SVR）和/或功能配置审核（FCA）对其进行验证。\u003c/p\u003e\n\u003cp\u003e\u003cem\u003eDefinition of the required system functionality describing functional and interface characteristics of the overall system, and the verification required to demonstrate the achievement of those specified functional characteristics. This baseline is derived from the Capability Development Document (CDD) and normally includes a detailed functional performance specification for the overall system and the tests necessary to verify and validate overall system performance.\u003c/em\u003e\u003c/p\u003e","title":"翻译：系统工程之配置基准"},{"content":"JavaScript 原生中默认是没有 Console 对象,这是宿主对象提供的内置对象。 在webview中已经内置实现了，但是在JSCore这样的JS引擎中没有实现相关功能，因此为了前端同学调试方便和代码可移植性，有必要手动实现一个。 大体的实现思路如下：\n注入全局的日志打印函数 我们可以注入一个全局的日志打印函数，假设名字叫做 NativePrint，然后创建Console对象，将Console对象的日志输出全部转发到这个 NativePrint 上。\nNativePrint 接收两个参数，一个是日志类型，一个日志内容.\niOS JSContext示例\nJSContext * context = [JSContext new]; context[@\u0026#34;NativePrint\u0026#34;] = ^(NSString *logType , id logContext) { //打印输出 } Android V8示例\nimport com.eclipsesource.v8.V8; JavaVoidCallback callback = new JavaVoidCallback() { @Override public void invoke(final V8Object receiver, final V8Array parameters) { //解析parameters ，打印输出 } } V8 runtime = V8.createV8Runtime(); runtime.registerJavaMethod(callback, \u0026#34;NativePrint\u0026#34;); 注入Console对象 可变参数 对于JavaScript的方法来说，都有一个 arguments 参数列表（列表名字就是arguments），所以我们可以定义可变参数函数\njavascript代码 注入NativePrint方法后，我们再注入一个全局的Console对象， 例如\nconsole = { default:this, __Stringformat : function (values) { function __toString(s) { if (s === null || s === undefined) { return \u0026#34;\u0026#34;; } return s.toString(); } if (values.length == 0) { return \u0026#34;\u0026#34;; } else if (values.length == 1) { return __toString(values[0]); } index = 0; return values[0].replace(/%([a-zA-Z_])/g, function (match) { index = index +1; if (values.length \u0026gt; index) { return __toString(values[index]); } else { return \u0026#34;\u0026#34;; } }); }, info : function () { ffpd_log(\u0026#34;info\u0026#34;,this.__Stringformat(arguments)); }, warn : function () { ffpd_log(\u0026#34;warn\u0026#34;,this.__Stringformat(arguments)); }, //其他Console方法 }; 使用示例\nconsole.info(\u0026#34;%s %s %i\u0026#34;,\u0026#34;hello\u0026#34;,\u0026#34;world\u0026#34;, 100); ","permalink":"https://blog.z6z8.cn/2019/12/05/jscore-v8%E7%8E%AF%E5%A2%83%E4%B8%AD%E5%AE%9E%E7%8E%B0javascript%E7%9A%84console%E5%8A%9F%E8%83%BD/","summary":"\u003cp\u003eJavaScript 原生中默认是没有 Console 对象,这是宿主对象提供的内置对象。\n在webview中已经内置实现了，但是在JSCore这样的JS引擎中没有实现相关功能，因此为了前端同学调试方便和代码可移植性，有必要手动实现一个。\n大体的实现思路如下：\u003c/p\u003e\n\u003ch1 id=\"注入全局的日志打印函数\"\u003e注入全局的日志打印函数\u003c/h1\u003e\n\u003cp\u003e我们可以注入一个全局的日志打印函数，假设名字叫做 \u003ccode\u003eNativePrint\u003c/code\u003e，然后创建Console对象，将Console对象的日志输出全部转发到这个 \u003ccode\u003eNativePrint\u003c/code\u003e 上。\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003eNativePrint\u003c/code\u003e 接收两个参数，一个是日志类型，一个日志内容.\u003c/p\u003e\n\u003cp\u003eiOS JSContext示例\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eJSContext \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e context \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [JSContext new];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003econtext[\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;NativePrint\u0026#34;\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e(NSString \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003elogType , \u003cspan style=\"color:#66d9ef\"\u003eid\u003c/span\u003e logContext) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e//打印输出\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eAndroid V8示例\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e com.eclipsesource.v8.V8;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eJavaVoidCallback callback \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e JavaVoidCallback() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003e@Override\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einvoke\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003efinal\u003c/span\u003e V8Object receiver, \u003cspan style=\"color:#66d9ef\"\u003efinal\u003c/span\u003e V8Array parameters) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e//解析parameters ，打印输出\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eV8 runtime \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e V8.\u003cspan style=\"color:#a6e22e\"\u003ecreateV8Runtime\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eruntime.\u003cspan style=\"color:#a6e22e\"\u003eregisterJavaMethod\u003c/span\u003e(callback, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;NativePrint\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"注入console对象\"\u003e注入Console对象\u003c/h1\u003e\n\u003ch2 id=\"可变参数\"\u003e可变参数\u003c/h2\u003e\n\u003cp\u003e对于JavaScript的方法来说，都有一个 \u003ccode\u003earguments\u003c/code\u003e 参数列表（列表名字就是arguments），所以我们可以定义可变参数函数\u003c/p\u003e\n\u003ch2 id=\"javascript代码\"\u003ejavascript代码\u003c/h2\u003e\n\u003cp\u003e注入NativePrint方法后，我们再注入一个全局的Console对象，\n例如\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003econsole\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003e__Stringformat\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003evalues\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__toString\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eundefined\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e          \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003es\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003etoString\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003evalues\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    } \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003evalues\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__toString\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003evalues\u003c/span\u003e[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003evalues\u003c/span\u003e[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e].\u003cspan style=\"color:#a6e22e\"\u003ereplace\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e/%([a-zA-Z_])/g\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003ematch\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003evalues\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__toString\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003evalues\u003c/span\u003e[\u003cspan style=\"color:#a6e22e\"\u003eindex\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      } \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003einfo\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e () {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003effpd_log\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;info\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003e__Stringformat\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003earguments\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003ewarn\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e () {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003effpd_log\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;warn\u0026#34;\u003c/span\u003e,\u003cspan style=\"color:#66d9ef\"\u003ethis\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003e__Stringformat\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003earguments\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  },\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e//其他Console方法\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e};\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e使用示例\u003c/p\u003e","title":"JSCore/V8环境中实现JavaScript的Console功能"},{"content":"我曾经以为理所当然应该知道的事，而如今的一些程序员却一脸茫然。\n先声明，我本人对Java没有偏见。\n起因是这样的，同事拿着一段Java代码给我看，咨询下啥啥功能的事。我便细细观摩，看到关于读写文件的代码\u0026ndash;将文件以字符串形式读到内存中。\n看了会儿，我说：“这块有点瑕疵，没有指定文本的编码格式” 他说：“什么编码？以前也这么写的，运行起来没有问题。” \u0026hellip;\u0026hellip;（后续交流省略）\u0026hellip;..\n从我近年来和多位从事移动开发的程序员接触来看，我的感触就是移动互联网发展太快了，以至于他们完美的错过了这个行业很基础的知识灌溉\u0026mdash;-或者忙着写业务了，或者手中正翻看xx天速成、包教包会的书，或者忙着追各种吹牛x的黑科技了，\n好了，抱怨了一通，我转回正题。为什么要指定文本的编码格式？这事儿要从上世纪的蛮荒时代说起。\n百花齐放 我们都知道，计算机的中储存以字节（8比特）为单位，人们阅读的文本在计算机存储都是一堆字节，而不是什么“世界你好，hello world”之类的可阅读文本。\n为了解码这些字节，必须按照一定的规范将文本映射为计算机可以储存的字节。最早的可知晓的规范就是非常著名的ASCII编码，比如 0x30 代表字符 0, 0x41 代表字符 A 等等\nASCII编码，全称为美国信息交换标准代码， 在1967年作为规范标准发布，主要用来表示现代英文的编码约定（可以理解，那时计算机的主导是美国，到现在美国也是引领者），只定义了128个字符。\n随着计算机的发展，越来越多的国家和地区使用计算机，自然因为语言不同，也有了制定适合自己国家和地区的文本编码了，诸如ISO系列，ibm系列，Windows系列，像中文的big-5,gb系列等， 详细请参考\n这里，闲聊一句，上世纪80、90年代BP寻呼机，支持汉显和不支持汉显的价格有时能差一倍。\n当编码多了，最大的问题是不同编码之间无法相互兼容，只有程序员能明白这其中的苦楚；若还是不明白，问问微软在上世纪是如何在各个国家和地区适配多语言的。\nUnicode一统 文本编码不能相互兼容，这为软件行业的发展、互联网的推广带来了很大的麻烦，统一字符编码势在必行。最终统一的结果也就是今天大家看到的Unicode\u0026mdash; 是由一个名为 Unicode 学术学会(Unicode Consortium)的机构制订的字符编码系统，支持现今世界各种不同语言的书面文本的交换、处理及显示。该编码于1990年开始研发，1994年正式公布，最新版本是2019年5月7日的Unicode 12.1.0(这段摘自百度百科)。\n字符集和编码 这里单独说下字符集和编码的关系。 平时我们交流时，很少说字符集，通常都是Unicode编码、GB2312编码，UTF8之类的。\n严谨的来说，包括Unicode、ASCII、GB2312在内的编码规范，其实分为两部分：字符集、编码方式。\n字符集，指的是该规范收录了哪些字符，可以称之为字符的集合。例如，ASCII收录了数字、大小写英文字母、一些常用的符号和一些控制打印的字符；GBK2312收录包括ASCII在内的符号，以及常用的汉字和符号，还收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。\n编码方式，指将收录的字符如何映射到计算机中的字节存储。简单来说，ASCII是单字节编码，为每一个收录的字符分配一个字节的数值表示，比如 0x30 代表字符 0, 0x41 代表字符 A。\nGBK2312是双字节编码，为每一个收录的字符分配两个字节的数值表示。\nUTF8，是Unicode字符集的一种编码方式，变长字节； UTF16，是Unicode字符集的一种编码方式，两个字节（不考虑Java中的字符代理对情况）；另外，考虑到网络传输，UTF16还要区分大小端（大小尾）。两个数字 0xFFFE，0xFEFF，估计还是有人能看懂的。 UTF32，是Unicode字符集的一种编码方式，四个字节； UTF7，有谁听说过吗？是Unicode字符集的一种编码方式，变长字节。\n另外，强烈建议在大部分场景使用UTF8编码方式，这是真正的万国编码。\n为什么要指定文本编码 答：因为鬼知道我不指定编码，软件会怎么解码文本？\n联通为什么干不过移动 答：微软记事本告诉你https://www.iteye.com/blog/mfkvfn-1703414\n在windows操作系统中，新建一个文本文件，用词本打开，输入\u0026#34;联通\u0026#34;两个字之后，保存，关闭，然后再次打开，你会发现这两个字已经消失了，代之的是个乱码！而输入移去就不会有问题。 据说这就是联通之所以拼不过移动的原因。 Windows NT（Windows 2000及以上）版本的记事本 ，亦默认安装于Windows 2000和Windows XP中，可以侦查到缺乏字节序标记的Unicode文件。这个功能由一个Windows API提供，名为IsTextUnicode() 。但是，这个功能是不完美的，副作用是一些小写字体的ASCII文字，会错误判断为UTF-16。 在2006年5月18日，有报道称，对于一个含有类似\u0026#34;this app can break\u0026#34;这样短语的文档（甚至是类似\u0026#34;aaaa aaa aaa aaaaa\u0026#34;的简单短语），记事本会将其打开并显示为Unicode二进制文本。如果安装了相关中文字体则会显示二进制码所对应的汉字。造成这个错误的字符串可能形如“4个字母+空格+3个字母+空格+3个字母+空格+5个字母 ”，或者“4个字母+空格+5个字母+空格+5个字母+空格+5个字母 ”，并且文档末尾没有换行符。有人认为这是一个复活节彩蛋 ，但事实并非如此。还有人认为这是由于记事本的Unicode的检测算法所引起。 这个问题已在Windows Vista版本的Notepad中被修复。 但是，记事本还有一个问题，就是用ANSI保存的文档有时会被误认为Unicode。如在记事本中输入“联通 ”并保存，再次打开的时候会显示乱码，目前尚未被修复。 ","permalink":"https://blog.z6z8.cn/2019/12/04/%E7%BC%96%E7%A8%8B%E4%B9%8B%E8%B7%AF%E6%80%BB%E7%BB%93%EF%BC%9A%E7%BC%96%E7%A0%81%E4%B8%8E%E5%AD%97%E7%AC%A6%E9%9B%86/","summary":"\u003cp\u003e我曾经以为理所当然应该知道的事，而如今的一些程序员却一脸茫然。\u003c/p\u003e\n\u003cp\u003e先声明，我本人对Java没有偏见。\u003c/p\u003e\n\u003cp\u003e起因是这样的，同事拿着一段Java代码给我看，咨询下啥啥功能的事。我便细细观摩，看到关于读写文件的代码\u0026ndash;将文件以字符串形式读到内存中。\u003c/p\u003e\n\u003cp\u003e看了会儿，我说：“这块有点瑕疵，没有指定文本的编码格式”\n他说：“什么编码？以前也这么写的，运行起来没有问题。”\n\u0026hellip;\u0026hellip;（后续交流省略）\u0026hellip;..\u003c/p\u003e\n\u003cp\u003e从我近年来和多位从事移动开发的程序员接触来看，我的感触就是移动互联网发展太快了，以至于他们完美的错过了这个行业很基础的知识灌溉\u0026mdash;-或者忙着写业务了，或者手中正翻看xx天速成、包教包会的书，或者忙着追各种吹牛x的黑科技了，\u003c/p\u003e\n\u003cp\u003e好了，抱怨了一通，我转回正题。为什么要指定文本的编码格式？这事儿要从上世纪的蛮荒时代说起。\u003c/p\u003e\n\u003ch1 id=\"百花齐放\"\u003e百花齐放\u003c/h1\u003e\n\u003cp\u003e我们都知道，计算机的中储存以字节（8比特）为单位，人们阅读的文本在计算机存储都是一堆字节，而不是什么“世界你好，hello world”之类的可阅读文本。\u003c/p\u003e\n\u003cp\u003e为了解码这些字节，必须按照一定的规范将文本映射为计算机可以储存的字节。最早的可知晓的规范就是非常著名的ASCII编码，比如 0x30 代表字符 \u003ccode\u003e0\u003c/code\u003e, 0x41 代表字符 \u003ccode\u003eA\u003c/code\u003e 等等\u003c/p\u003e\n\u003cp\u003eASCII编码，全称为美国信息交换标准代码， 在1967年作为规范标准发布，主要用来表示现代英文的编码约定（可以理解，那时计算机的主导是美国，到现在美国也是引领者），只定义了128个字符。\u003c/p\u003e\n\u003cp\u003e随着计算机的发展，越来越多的国家和地区使用计算机，自然因为语言不同，也有了制定适合自己国家和地区的文本编码了，诸如ISO系列，ibm系列，Windows系列，像中文的big-5,gb系列等， \u003ca href=\"https://blog.csdn.net/miqi770/article/details/43935273\" title=\"详细请参考\"\u003e详细请参考\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e这里，闲聊一句，上世纪80、90年代BP寻呼机，支持汉显和不支持汉显的价格有时能差一倍。\u003c/p\u003e\n\u003cp\u003e当编码多了，最大的问题是不同编码之间无法相互兼容，只有程序员能明白这其中的苦楚；若还是不明白，问问微软在上世纪是如何在各个国家和地区适配多语言的。\u003c/p\u003e\n\u003ch1 id=\"unicode一统\"\u003eUnicode一统\u003c/h1\u003e\n\u003cp\u003e文本编码不能相互兼容，这为软件行业的发展、互联网的推广带来了很大的麻烦，统一字符编码势在必行。最终统一的结果也就是今天大家看到的Unicode\u0026mdash; \u003ccode\u003e是由一个名为 Unicode 学术学会(Unicode Consortium)的机构制订的字符编码系统，支持现今世界各种不同语言的书面文本的交换、处理及显示。该编码于1990年开始研发，1994年正式公布，最新版本是2019年5月7日的Unicode 12.1.0\u003c/code\u003e(这段摘自百度百科)。\u003c/p\u003e\n\u003ch2 id=\"字符集和编码\"\u003e字符集和编码\u003c/h2\u003e\n\u003cp\u003e这里单独说下字符集和编码的关系。\n平时我们交流时，很少说字符集，通常都是Unicode编码、GB2312编码，UTF8之类的。\u003c/p\u003e\n\u003cp\u003e严谨的来说，包括Unicode、ASCII、GB2312在内的编码规范，其实分为两部分：字符集、编码方式。\u003c/p\u003e\n\u003cp\u003e字符集，指的是该规范收录了哪些字符，可以称之为字符的集合。例如，ASCII收录了数字、大小写英文字母、一些常用的符号和一些控制打印的字符；GBK2312收录包括ASCII在内的符号，以及常用的汉字和符号，还收录了包括拉丁字母、希腊字母、日文平假名及片假名字母、俄语西里尔字母在内的682个全角字符。\u003c/p\u003e\n\u003cp\u003e编码方式，指将收录的字符如何映射到计算机中的字节存储。简单来说，ASCII是单字节编码，为每一个收录的字符分配一个字节的数值表示，比如 0x30 代表字符 \u003ccode\u003e0\u003c/code\u003e, 0x41 代表字符 \u003ccode\u003eA\u003c/code\u003e。\u003c/p\u003e\n\u003cp\u003eGBK2312是双字节编码，为每一个收录的字符分配两个字节的数值表示。\u003c/p\u003e\n\u003cp\u003eUTF8，是Unicode字符集的一种编码方式，变长字节；\nUTF16，是Unicode字符集的一种编码方式，两个字节（不考虑Java中的字符代理对情况）；另外，考虑到网络传输，UTF16还要区分大小端（大小尾）。两个数字 0xFFFE，0xFEFF，估计还是有人能看懂的。\nUTF32，是Unicode字符集的一种编码方式，四个字节；\nUTF7，有谁听说过吗？是Unicode字符集的一种编码方式，变长字节。\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e另外，强烈建议在大部分场景使用UTF8编码方式，这是真正的万国编码。\u003c/p\u003e\n\u003c/blockquote\u003e\n\u003ch1 id=\"为什么要指定文本编码\"\u003e为什么要指定文本编码\u003c/h1\u003e\n\u003cp\u003e答：因为鬼知道我不指定编码，软件会怎么解码文本？\u003c/p\u003e\n\u003ch1 id=\"联通为什么干不过移动\"\u003e联通为什么干不过移动\u003c/h1\u003e\n\u003cp\u003e答：微软记事本告诉你https://www.iteye.com/blog/mfkvfn-1703414\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e在windows操作系统中，新建一个文本文件，用词本打开，输入\u0026#34;联通\u0026#34;两个字之后，保存，关闭，然后再次打开，你会发现这两个字已经消失了，代之的是个乱码！而输入移去就不会有问题。\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e　　据说这就是联通之所以拼不过移动的原因。\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e　　Windows NT（Windows 2000及以上）版本的记事本 ，亦默认安装于Windows 2000和Windows XP中，可以侦查到缺乏字节序标记的Unicode文件。这个功能由一个Windows API提供，名为IsTextUnicode() 。但是，这个功能是不完美的，副作用是一些小写字体的ASCII文字，会错误判断为UTF-16。\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e　　在2006年5月18日，有报道称，对于一个含有类似\u0026#34;this app can break\u0026#34;这样短语的文档（甚至是类似\u0026#34;aaaa aaa aaa aaaaa\u0026#34;的简单短语），记事本会将其打开并显示为Unicode二进制文本。如果安装了相关中文字体则会显示二进制码所对应的汉字。造成这个错误的字符串可能形如“4个字母+空格+3个字母+空格+3个字母+空格+5个字母 ”，或者“4个字母+空格+5个字母+空格+5个字母+空格+5个字母 ”，并且文档末尾没有换行符。有人认为这是一个复活节彩蛋 ，但事实并非如此。还有人认为这是由于记事本的Unicode的检测算法所引起。\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e　　这个问题已在Windows Vista版本的Notepad中被修复。\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e　　但是，记事本还有一个问题，就是用ANSI保存的文档有时会被误认为Unicode。如在记事本中输入“联通 ”并保存，再次打开的时候会显示乱码，目前尚未被修复。\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"编程之路总结：编码与字符集"},{"content":"通过读取png图像文件的头信息\n#include \u0026#34;stdio.h\u0026#34; namespace { class CFileStream { public: CFileStream (FILE *fs):m_fs(fs) {} ~CFileStream() { fclose(m_fs); } inline operator FILE*() { return m_fs; } inline operator bool() { return m_fs != 0; } private: FILE *m_fs; }; inline unsigned long Convert4char( unsigned char c[4]) //网络端字节序 { unsigned long n = ((unsigned long)c[0]) \u0026lt;\u0026lt; 24; n += ((unsigned long)c[1]) \u0026lt;\u0026lt; 16; n += ((unsigned long)c[2]) \u0026lt;\u0026lt; 8; n += ((unsigned long)c[3]); return n; } } #define png_signature_len 8 //png文件签名 #define png_chunk_len_len 4 //idhr长度信息 #define png_chunk_type_len 4 //ihdr类型码 #define png_ihdr_data_len 13 //ihdr数据 + (BOOL)imageSizeFromPNGFile:(NSString *)pngFile size:(CGSize *)size; { if (!pngFile || !size) { return NO; } CFileStream fs = fopen([pngFile UTF8String], \u0026#34;rb\u0026#34;); if (!fs) { return NO; } unsigned char buf[png_signature_len+png_chunk_len_len+png_chunk_type_len+png_ihdr_data_len]; if (sizeof(buf) != fread(buf, 1, sizeof(buf), fs)) { return NO; } //校验文件签名 if ( memcmp(buf, \u0026#34;\\x89\\x50\\x4e\\x47\\x0d\\x0a\\x1a\\x0a\u0026#34;, png_signature_len) != 0 ) { return NO; } //校验ihdr长度 if (memcmp(buf + png_signature_len, \u0026#34;\\x00\\x00\\x00\\x0d\u0026#34;, png_chunk_len_len) != 0) { return NO; } //校验ihdr类型码 if (memcmp(buf + png_signature_len +png_chunk_len_len, \u0026#34;IHDR\u0026#34;, png_chunk_len_len) != 0) { return NO; } size-\u0026gt;width = Convert4char(buf + png_signature_len+png_chunk_len_len+png_chunk_type_len ); size-\u0026gt;height = Convert4char(buf + png_signature_len+png_chunk_len_len+png_chunk_type_len+4); return YES; } #undef png_signature_len #undef png_chunk_len_len #undef png_chunk_type_len #undef png_ihdr_data_len ","permalink":"https://blog.z6z8.cn/2019/12/03/png-ihdr%EF%BC%9A%E8%8E%B7%E5%8F%96png%E5%9B%BE%E5%83%8F%E5%AE%BD%E5%92%8C%E9%AB%98/","summary":"\u003cp\u003e通过读取png图像文件的头信息\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-cpp\" data-lang=\"cpp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026#34;stdio.h\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003enamespace\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCFileStream\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        CFileStream (FILE \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003efs)\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003em_fs(fs)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e~\u003c/span\u003eCFileStream()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            fclose(m_fs);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eoperator\u003c/span\u003e FILE\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e  m_fs;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eoperator\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ebool\u003c/span\u003e()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e  m_fs \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        FILE \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003em_fs;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eConvert4char\u003c/span\u003e( \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e c[\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e]) \u003cspan style=\"color:#75715e\"\u003e//网络端字节序\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e n \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e)c[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e]) \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e24\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        n \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e)c[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e]) \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e16\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        n \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e)c[\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e]) \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        n \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e)c[\u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e n;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define png_signature_len 8 \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e//png文件签名\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e#define png_chunk_len_len  4 \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e//idhr长度信息\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e#define png_chunk_type_len 4 \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e//ihdr类型码\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e#define png_ihdr_data_len 13 \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e//ihdr数据\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e (BOOL)imageSizeFromPNGFile:(NSString \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)pngFile size:(CGSize \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)size;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003epngFile \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003esize) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e NO;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    CFileStream fs \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e fopen([pngFile UTF8String], \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;rb\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003efs) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e NO;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e buf[png_signature_len\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003epng_chunk_len_len\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003epng_chunk_type_len\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003epng_ihdr_data_len];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(buf) \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e fread(buf, \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(buf), fs)) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e NO;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//校验文件签名\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( memcmp(buf, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\x89\\x50\\x4e\\x47\\x0d\\x0a\\x1a\\x0a\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e, png_signature_len) \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e NO;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//校验ihdr长度\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (memcmp(buf \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e png_signature_len, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e\\x00\\x00\\x00\\x0d\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e, png_chunk_len_len) \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e NO;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//校验ihdr类型码\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (memcmp(buf \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e png_signature_len \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003epng_chunk_len_len, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;IHDR\u0026#34;\u003c/span\u003e, png_chunk_len_len) \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e NO;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    size\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003ewidth \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Convert4char(buf \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e png_signature_len\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003epng_chunk_len_len\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003epng_chunk_type_len );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    size\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003eheight \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Convert4char(buf \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e png_signature_len\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003epng_chunk_len_len\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003epng_chunk_type_len\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e4\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e YES;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#undef png_signature_len\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#undef png_chunk_len_len\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#undef png_chunk_type_len\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#undef png_ihdr_data_len\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"PNG IHDR：获取PNG图像宽和高"},{"content":"动态创建一个类，NewClass ，继承自NSObject\nClass newClass = objc_allocateClassPair([NSObject class], \u0026#34;NewClass\u0026#34;, 0); //向运行时注册这个类 objc_registerClassPair(newClass); //从运行时销毁这个类 objc_disposeClassPair(newClass); ","permalink":"https://blog.z6z8.cn/2019/11/29/objective-c%E5%8A%A8%E6%80%81%E5%88%9B%E5%BB%BA%E6%96%B0%E7%B1%BB%EF%BC%88class%EF%BC%89/","summary":"\u003cp\u003e动态创建一个类，NewClass ，继承自NSObject\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eClass\u003c/span\u003e newClass \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e objc_allocateClassPair([NSObject \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e], \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;NewClass\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//向运行时注册这个类\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003eobjc_registerClassPair(newClass);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//从运行时销毁这个类\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003eobjc_disposeClassPair(newClass);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Objective-C:动态创建新类（Class）"},{"content":"集成 在Android Studio的Android工程中，需要在build.gradle文件内容里添加依赖指令，然后gradle构建就会自动化集成J2V8引擎\ndependencies { implementation \u0026#39;com.eclipsesource.j2v8:j2v8:5.0.103@aar\u0026#39; } J2V8的最新版本，可以在marven仓库中查看 https://mvnrepository.com/artifact/com.eclipsesource.j2v8/j2v8\n使用示例 示例摘自https://eclipsesource.com/blogs/tutorials/getting-started-with-j2v8/\nimport com.eclipsesource.v8.V8; public static void main(String[] args) { V8 runtime = V8.createV8Runtime(); int result = runtime.executeIntegerScript(\u0026#34;\u0026#34; + \u0026#34;var hello = \u0026#39;hello, \u0026#39;;\\n\u0026#34; + \u0026#34;var world = \u0026#39;world!\u0026#39;;\\n\u0026#34; + \u0026#34;hello.concat(world).length;\\n\u0026#34;); System.out.println(result); runtime.release(); } 访问JavaScript对象（Object） 假设有这样一段JS脚本\nvar jsobj = {}; jsobj.hello = \u0026#34;world\u0026#34;; 在J2V8中可以直接访问jsobj对象\nimport com.eclipsesource.v8.V8; public static void main(String[] args) { V8 runtime = V8.createV8Runtime(); runtime.executeVoidScript(\u0026#34;\u0026#34; + \u0026#34;var jsobj = {};\\n\u0026#34; + \u0026#34;jsobj.hello = \u0026#39;world\u0026#39;;\\n\u0026#34;); // 访问jsobj的属性 V8Object jsobj = runtime.getObject(\u0026#34;jsobj\u0026#34;); System.out.println(jsobj.getString(\u0026#34;hello\u0026#34;)); jsobj.release(); runtime.release(); } 需要注意， V8Object 需要自己手动释放\n执行JavaScript函数 JS脚本\nfunction test(a,b){ return a+b; } var jsobj = {}; jsobj.func = test; Java代码\nV8 runtime = V8.createV8Runtime(); runtime.executeVoidScript(\u0026#34;上面js脚本\u0026#34;) //包装参数 V8Array parameters = new V8Array(1).push(2); //调用js test方法 runtime.executeIntegerFunction(\u0026#34;test\u0026#34;,parameters); //调用jsobj.func V8Object jsobj = runtime.getObject(\u0026#34;jsobj\u0026#34;); jsob.executeIntegerFunction(\u0026#34;func\u0026#34;,parameters); //释放 parameters.release(); jsobj.release(); runtime.release(); JS调用Java方法 需要注册实现了 JavaCallback 接口的对象\nJavaVoidCallback callback = new JavaVoidCallback() { @Override public void invoke(final V8Object receiver, final V8Array parameters) { System.out.println(\u0026#34;xxxx\u0026#34;); } } V8 runtime = V8.createV8Runtime(); // 注册到 js 全局函数，函数名为 \u0026lt;code\u0026gt;JavaFunc\u0026lt;/code\u0026gt; runtime.registerJavaMethod(callback, \u0026#34;JavaFunc\u0026#34;); 在js中使用\nJavaFunc(1,2,3); JS调用Java对象实例方法 使用 V8Object.registerJavaMethod(object, javaMedthod, jsMethod, paramlist);\nobject java对象 javaMedthod object上的方法名 jsMethod js环境中的方法名 paramlist 这里指参数类型列表 V8 runtime = V8.createV8Runtime(); Object test = new test(); V8Object v8test = new V8Object(runtime); runtime.add(\u0026#34;test\u0026#34;, v8test); v8test.registerJavaMethod(test, \u0026#34;nativeFunc\u0026#34;, \u0026#34;jsFunc\u0026#34;, new Class\u0026lt;?\u0026gt;[] { String.class }); 在js中使用\ntest.jsFunc(\u0026#39;hello, world\u0026#39;); ","permalink":"https://blog.z6z8.cn/2019/11/28/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A%E4%BD%BF%E7%94%A8android-v8-%EF%BC%88j2v8%EF%BC%89javascript%E5%BC%95%E6%93%8E/","summary":"\u003ch1 id=\"集成\"\u003e集成\u003c/h1\u003e\n\u003cp\u003e在Android Studio的Android工程中，需要在build.gradle文件内容里添加依赖指令，然后gradle构建就会自动化集成J2V8引擎\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gradle\" data-lang=\"gradle\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edependencies \u003cspan style=\"color:#f92672\"\u003e{\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    implementation \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;com.eclipsesource.j2v8:j2v8:5.0.103@aar\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e}\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003eJ2V8的最新版本，可以在marven仓库中查看\n\u003ca href=\"https://mvnrepository.com/artifact/com.eclipsesource.j2v8/j2v8\"\u003ehttps://mvnrepository.com/artifact/com.eclipsesource.j2v8/j2v8\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"使用示例\"\u003e使用示例\u003c/h1\u003e\n\u003cp\u003e示例摘自https://eclipsesource.com/blogs/tutorials/getting-started-with-j2v8/\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e com.eclipsesource.v8.V8;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emain\u003c/span\u003e(String\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e args) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e V8 runtime \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e V8.\u003cspan style=\"color:#a6e22e\"\u003ecreateV8Runtime\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e result \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e runtime.\u003cspan style=\"color:#a6e22e\"\u003eexecuteIntegerScript\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;var hello = \u0026#39;hello, \u0026#39;;\\n\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;var world = \u0026#39;world!\u0026#39;;\\n\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hello.concat(world).length;\\n\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(result);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e runtime.\u003cspan style=\"color:#a6e22e\"\u003erelease\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"访问javascript对象object\"\u003e访问JavaScript对象（Object）\u003c/h1\u003e\n\u003cp\u003e假设有这样一段JS脚本\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ejsobj\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003ejsobj\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003ehello\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;world\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e在J2V8中可以直接访问jsobj对象\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003eimport\u003c/span\u003e com.eclipsesource.v8.V8;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emain\u003c/span\u003e(String\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e args) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  V8 runtime \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e V8.\u003cspan style=\"color:#a6e22e\"\u003ecreateV8Runtime\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  runtime.\u003cspan style=\"color:#a6e22e\"\u003eexecuteVoidScript\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;var jsobj = {};\\n\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;jsobj.hello = \u0026#39;world\u0026#39;;\\n\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e// 访问jsobj的属性\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  V8Object jsobj \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e runtime.\u003cspan style=\"color:#a6e22e\"\u003egetObject\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;jsobj\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  System.\u003cspan style=\"color:#a6e22e\"\u003eout\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eprintln\u003c/span\u003e(jsobj.\u003cspan style=\"color:#a6e22e\"\u003egetString\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hello\u0026#34;\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  jsobj.\u003cspan style=\"color:#a6e22e\"\u003erelease\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  runtime.\u003cspan style=\"color:#a6e22e\"\u003erelease\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e需要注意， \u003ccode\u003eV8Object\u003c/code\u003e 需要自己手动释放\u003c/p\u003e","title":"学习笔记：使用Android  V8 （J2V8）JavaScript引擎"},{"content":"NSOpenPanel控件\n- (void)p_selectFileDialog:(void(^)(NSString* filePath))block { NSOpenPanel* panel = [NSOpenPanel openPanel]; [panel setCanChooseDirectories:NO]; [panel setAllowsMultipleSelection:NO]; [panel setMessage:@\u0026#34;提示语\u0026#34;]; // Display the panel attached to the document\u0026#39;s window. [panel beginSheetModalForWindow:self.window completionHandler:^(NSInteger result){ if (result == NSModalResponseOK) { //点击确定后的代码 block(panel.URL.path); } else { block(nil); } }]; } ","permalink":"https://blog.z6z8.cn/2019/11/28/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9Amacos-%E9%80%89%E6%8B%A9%E6%96%87%E4%BB%B6%E5%AF%B9%E8%AF%9D%E6%A1%86%E7%A4%BA%E4%BE%8B/","summary":"\u003cp\u003eNSOpenPanel控件\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003ep_selectFileDialog:\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e)(NSString\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e filePath))block\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSOpenPanel\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e panel \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [NSOpenPanel openPanel];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [panel setCanChooseDirectories:NO];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [panel setAllowsMultipleSelection:NO];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [panel setMessage:\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;提示语\u0026#34;\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// Display the panel attached to the document\u0026#39;s window.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    [panel beginSheetModalForWindow:self.window completionHandler:\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e(NSInteger result){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (result \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e NSModalResponseOK)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e//点击确定后的代码\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            block(panel.URL.path);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            block(nil);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"学习笔记：macOS 选择文件对话框示例"},{"content":"AES加密几个要点 对称加密(Symmetry Crypto) 加密和解密的钥匙是同一把\u0026mdash;-加密方和解密方拥有相同的密钥（音yue，四声）。\n密钥(key) 任意数据（不一定非得字符串），长度常见为128比特、192比特、256比特，也有支持512比特的算法库\n初始化向量(IV) 这不是AES算法标准强制要求的，是一种增加AES破解难度的手段。IV和密钥共同参与加密和解密运算。IV长度固定为128比特。\n加密块(block) 每次加密的块长度都是128比特；输入和输出长度相同，考虑补全模式的情况下，输出的最大长度 = 输入长度+128比特\n加密模式 是指当需要加密的源数据长度大于128比特时，加密块和加密块之间的运算模式。 常见的有 CBC密码分组链接模式、ECB电码本模式（不推荐）、CTR计算器模式、CFB密码反馈模式、OFB输出反馈模式。\n补全模式模式（padding） 因为AES一个加密块为16字节，当源数据的最后一个块不足16字节时，需要手动补全为16字节。\n一般使用PKCS7模式，手动补全N个N，N为不足的字节数。\n例如，最后一个块为 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 需要补6个字节，那么就是6个6 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 0x06 0x06 0x06 0x06 0x06 0x06 EVP AES 加密 #include \u0026#34;openssl/crypto.h\u0026#34; #include \u0026#34;openssl/aes.h\u0026#34; #include \u0026#34;openssl/evp.h\u0026#34; //引入c++的string，作为buffer使用 #include \u0026lt;string\u0026gt; //std::string 作为返回值其实可以右值优化的。 std::string encrypt(std::string \u0026amp;data , std::string \u0026amp;key ,std::string \u0026amp;iv) { //这里应该做必要的参数校验，如检查key和iv长度 //指定算法模式 EVP_CIPHER *ciper = NULL; switch (data.size()) { case 128 / 8: ciper = EVP_aes_128_cbc();break; case 192 / 8: ciper = EVP_aes_192_cbc();break; case 256 / 8: ciper = EVP_aes_256_cbc();break; default:return \u0026#34;需要做一些错误处理\u0026#34;; } //初始化ctx EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(ctx); //指定加密算法及key和iv int ret = EVP_EncryptInit_ex(ctx, ciper, NULL, (unsigned char *)key.c_str(), (unsigned char *)iv.c_str()); if(ret != 1) {//EVP_EncryptInit_ex failed EVP_CIPHER_CTX_free(ctx); return \u0026#34;需要做一些错误处理\u0026#34;; } // 设置padding EVP框架默认使用的就是PKCS7 EVP_CIPHER_CTX_set_padding(ctx, 1); std::string buffer; buffer.append(0,AES_BLOCK_SIZE + data.size()); int mlen = 0; //进行加密操作 ret = EVP_EncryptUpdate(ctx, (unsigned char *)buffer.c_str(), \u0026amp;mlen, (unsigned char *)data.c_str(),(int)buffer.size()); if(ret != 1) { EVP_CIPHER_CTX_free(ctx); return \u0026#34;需要做一些错误处理\u0026#34;; } int flen = 0; //结束加密操作 ret = EVP_EncryptFinal_ex(ctx, (unsigned char *)buffer.c_str()+mlen, \u0026amp;flen); if(ret != 1) { EVP_CIPHER_CTX_free(ctx); return \u0026#34;需要做一些错误处理\u0026#34;; } EVP_CIPHER_CTX_free(ctx); buffer.resize(mlen + flen); return buffer; } EVP AES 解密 std::string decrypt(std::string \u0026amp;data , std::string \u0026amp;key ,std::string \u0026amp;iv) { //这里应该做必要的参数校验，如检查key和iv长度 //指定算法模式 EVP_CIPHER *ciper = NULL; switch (data.size()) { case 128 / 8: ciper = EVP_aes_128_cbc();break; case 192 / 8: ciper = EVP_aes_192_cbc();break; case 256 / 8: ciper = EVP_aes_256_cbc();break; default:return \u0026#34;需要做一些错误处理\u0026#34;; } //初始化ctx EVP_CIPHER_CTX *ctx = EVP_CIPHER_CTX_new(); EVP_CIPHER_CTX_init(ctx); //指定加密算法及key和iv int ret = EVP_DecryptInit_ex(ctx, ciper, NULL, (unsigned char *)key.c_str(), (unsigned char *)iv.c_str()); if(ret != 1) {//EVP_EncryptInit_ex failed EVP_CIPHER_CTX_free(ctx); return \u0026#34;需要做一些错误处理\u0026#34;; } // 设置padding功能 EVP框架默认使用的就是PKCS7 EVP_CIPHER_CTX_set_padding(ctx, 1); std::string buffer; buffer.append(0,data.size()); int mlen = 0; //进行解密操作 ret = EVP_DecryptUpdate(ctx, (unsigned char *)buffer.c_str(), \u0026amp;mlen, (unsigned char *)data.c_str(),(int) data.size()); if(ret != 1) { EVP_CIPHER_CTX_free(ctx); return \u0026#34;需要做一些错误处理\u0026#34;; } int flen = 0; //结束解密操作 ret = EVP_DecryptFinal_ex(ctx, (unsigned char *)buffer.c_str()+mlen, \u0026amp;flen); if(ret != 1) { EVP_CIPHER_CTX_free(ctx); return \u0026#34;需要做一些错误处理\u0026#34;; } EVP_CIPHER_CTX_free(ctx); buffer.resize(mlen + flen); return buffer; } ","permalink":"https://blog.z6z8.cn/2019/11/21/ssl-evp%E6%A1%86%E6%9E%B6%EF%BC%9Aaes%E5%8A%A0%E5%AF%86/","summary":"\u003ch1 id=\"aes加密几个要点\"\u003eAES加密几个要点\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e对称加密(Symmetry Crypto)\n加密和解密的钥匙是同一把\u0026mdash;-加密方和解密方拥有相同的密钥（音yue，四声）。\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e密钥(key)\n任意数据（不一定非得字符串），长度常见为128比特、192比特、256比特，也有支持512比特的算法库\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e初始化向量(IV)\n这不是AES算法标准强制要求的，是一种增加AES破解难度的手段。IV和密钥共同参与加密和解密运算。IV长度固定为128比特。\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e加密块(block)\n每次加密的块长度都是128比特；输入和输出长度相同，考虑补全模式的情况下，输出的最大长度 = 输入长度+128比特\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e加密模式\n是指当需要加密的源数据长度大于128比特时，加密块和加密块之间的运算模式。\n常见的有 CBC密码分组链接模式、ECB电码本模式（不推荐）、CTR计算器模式、CFB密码反馈模式、OFB输出反馈模式。\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e补全模式模式（padding）\n因为AES一个加密块为16字节，当源数据的最后一个块不足16字节时，需要手动补全为16字节。\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e一般使用PKCS7模式，手动补全N个N，N为不足的字节数。\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e例如，最后一个块为 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e需要补6个字节，那么就是6个6\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x10 0x06 0x06 0x06 0x06 0x06 0x06\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"evp-aes-加密\"\u003eEVP AES 加密\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-cpp\" data-lang=\"cpp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026#34;openssl/crypto.h\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026#34;openssl/aes.h\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026#34;openssl/evp.h\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//引入c++的string，作为buffer使用\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;string\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//std::string 作为返回值其实可以右值优化的。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003estd\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring encrypt(std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003edata , std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ekey ,std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eiv)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#75715e\"\u003e//这里应该做必要的参数校验，如检查key和iv长度\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e//指定算法模式\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    EVP_CIPHER \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eciper \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e NULL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eswitch\u003c/span\u003e (data.size())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e128\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e ciper \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e  EVP_aes_128_cbc();\u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e192\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e ciper \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e  EVP_aes_192_cbc();\u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e256\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e ciper \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e  EVP_aes_256_cbc();\u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;需要做一些错误处理\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//初始化ctx\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    EVP_CIPHER_CTX \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ectx \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e EVP_CIPHER_CTX_new();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    EVP_CIPHER_CTX_init(ctx);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//指定加密算法及key和iv\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e ret \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e EVP_EncryptInit_ex(ctx, ciper, NULL, (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)key.c_str(),  (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)iv.c_str());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(ret \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\u003cspan style=\"color:#75715e\"\u003e//EVP_EncryptInit_ex failed\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        EVP_CIPHER_CTX_free(ctx);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;需要做一些错误处理\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 设置padding EVP框架默认使用的就是PKCS7\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    EVP_CIPHER_CTX_set_padding(ctx, \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring buffer;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   buffer.append(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e,AES_BLOCK_SIZE \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e data.size());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e mlen \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//进行加密操作\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    ret \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e EVP_EncryptUpdate(ctx, (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)buffer.c_str(), \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003emlen, (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)data.c_str(),(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)buffer.size());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(ret \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        EVP_CIPHER_CTX_free(ctx);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;需要做一些错误处理\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e flen \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//结束加密操作\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    ret \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e EVP_EncryptFinal_ex(ctx, (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)buffer.c_str()\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003emlen, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eflen);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(ret \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        EVP_CIPHER_CTX_free(ctx);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;需要做一些错误处理\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    EVP_CIPHER_CTX_free(ctx);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    buffer.resize(mlen \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e flen);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e buffer;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"evp-aes-解密\"\u003eEVP AES 解密\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-cpp\" data-lang=\"cpp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003estd\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring decrypt(std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003edata , std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003ekey ,std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eiv)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#75715e\"\u003e//这里应该做必要的参数校验，如检查key和iv长度\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e//指定算法模式\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    EVP_CIPHER \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eciper \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e NULL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eswitch\u003c/span\u003e (data.size())\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e128\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e ciper \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e  EVP_aes_128_cbc();\u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e192\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e ciper \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e  EVP_aes_192_cbc();\u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ecase\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e256\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e8\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e ciper \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e  EVP_aes_256_cbc();\u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;需要做一些错误处理\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//初始化ctx\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    EVP_CIPHER_CTX \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ectx \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e EVP_CIPHER_CTX_new();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    EVP_CIPHER_CTX_init(ctx);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//指定加密算法及key和iv\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e ret \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e EVP_DecryptInit_ex(ctx, ciper, NULL,  (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)key.c_str(),  (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)iv.c_str());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(ret \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\u003cspan style=\"color:#75715e\"\u003e//EVP_EncryptInit_ex failed\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        EVP_CIPHER_CTX_free(ctx);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e  \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;需要做一些错误处理\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e// 设置padding功能 EVP框架默认使用的就是PKCS7\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    EVP_CIPHER_CTX_set_padding(ctx, \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    std\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003estring buffer;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    buffer.append(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e,data.size());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e mlen \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//进行解密操作\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    ret \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e EVP_DecryptUpdate(ctx,  (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)buffer.c_str(), \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003emlen,  (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)data.c_str(),(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e) data.size());\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(ret \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        EVP_CIPHER_CTX_free(ctx);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e  \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;需要做一些错误处理\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e flen \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//结束解密操作\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    ret \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e EVP_DecryptFinal_ex(ctx, (\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)buffer.c_str()\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003emlen, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003eflen);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(ret \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        EVP_CIPHER_CTX_free(ctx);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e  \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;需要做一些错误处理\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    EVP_CIPHER_CTX_free(ctx);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    buffer.resize(mlen \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e flen);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e buffer;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"SSL EVP框架：AES加密"},{"content":"[[NSProcessInfo processInfo] systemUptime]; 或者\n#include \u0026lt;mach/mach.h\u0026gt; #include \u0026lt;mach/mach_time.h\u0026gt; long long tm = mach_absolute_time(); static mach_timebase_info_data_t sTimebaseInfo; if ( sTimebaseInfo.denom == 0 ) //静态整型变量初始化时默认为0 { mach_timebase_info(\u0026amp;sTimebaseInfo); } return tm * sTimebaseInfo.numer / sTimebaseInfo.denom / (1000*1000); ","permalink":"https://blog.z6z8.cn/2019/11/20/ios-%E8%8E%B7%E5%8F%96%E5%BC%80%E6%9C%BA%E5%90%AF%E5%8A%A8%E5%90%8E%E7%9A%84%E7%B4%AF%E7%A7%AF%E6%97%B6%E9%97%B4/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[[NSProcessInfo processInfo] systemUptime];\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e或者\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;mach/mach.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;mach/mach_time.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e tm \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emach_absolute_time\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emach_timebase_info_data_t\u003c/span\u003e    sTimebaseInfo;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( sTimebaseInfo.denom \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ) \u003cspan style=\"color:#75715e\"\u003e//静态整型变量初始化时默认为0\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003emach_timebase_info\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003esTimebaseInfo);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e tm \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e sTimebaseInfo.numer \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e sTimebaseInfo.denom  \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e (\u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1000\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"iOS 获取开机启动后的累积时间"},{"content":"头文件\n// // ZLNetworkTime.h // // Created by zxs.zl on 2018/3/12. // #import \u0026lt;Foundation/Foundation.h\u0026gt; @interface ZLNetworkTime : NSObject +(void)startSyncTimeFromNetwork; +(BOOL)syncTimeFromNetworkDone; +(NSTimeInterval)timeIntervalSince1970; @end 实现文件\n// // ZLNetworkTime.m // // Created by zxs.zl on 2018/3/12. // #if ! __has_feature(objc_arc) #error This file must be compiled with ARC. Either turn on ARC for the project or use -fobjc-arc flag #endif #import \u0026#34;ZLNetworkTime.h\u0026#34; struct _ZLTimeBase_ { _ZLTimeBase_() { init_state = not_init; init_count = 0; } NSTimeInterval systemUptimeBase; NSTimeInterval networkTimBbase; enum { not_init, initing, inited, } init_state; int init_count; }s_timeBase; @implementation ZLNetworkTime +(NSTimeInterval)timeIntervalSince1970 { if (s_timeBase.init_state == s_timeBase.inited) return s_timeBase.networkTimBbase + [[NSProcessInfo processInfo] systemUptime] - s_timeBase.systemUptimeBase; else return [[NSDate date] timeIntervalSince1970]; } +(BOOL)syncTimeFromNetworkDone { return s_timeBase.init_state == s_timeBase.inited; } +(void)startSyncTimeFromNetwork { if (s_timeBase.init_state != s_timeBase.not_init) return; if (s_timeBase.init_count \u0026gt;= 3) return; @synchronized(self){ if (s_timeBase.init_state != s_timeBase.not_init) return; s_timeBase.init_state = s_timeBase.initing; } s_timeBase.init_count++; NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration]; config.timeoutIntervalForRequest = 3; config.requestCachePolicy = NSURLRequestReloadIgnoringCacheData; NSURLSession * session = [NSURLSession sessionWithConfiguration:config]; NSURL * url = [NSURL URLWithString:@\u0026#34;http://time.tianqi.com/\u0026#34;]; NSTimeInterval systemUptime = [[NSProcessInfo processInfo] systemUptime]; NSURLSessionDataTask * dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) { NSHTTPURLResponse * httpResponse = (NSHTTPURLResponse*)response; if ([httpResponse isKindOfClass:[NSHTTPURLResponse class]] \u0026amp;\u0026amp; httpResponse.statusCode == 200 ) { NSString * dateStr = httpResponse.allHeaderFields[@\u0026#34;Date\u0026#34;]; if (dateStr.length \u0026gt; 0) { //Mon, 12 Mar 2018 07:21:32 GMT NSDateFormatter *formatter = [[NSDateFormatter alloc] init]; formatter.timeZone = [NSTimeZone timeZoneWithName:@\u0026#34;GMT\u0026#34;]; [formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:@\u0026#34;en_US_POSIX\u0026#34;]]; [formatter setDateFormat:@\u0026#34;EEE, dd MMM yyyy HH:mm:ss \u0026#39;GMT\u0026#39;\u0026#34;]; NSDate *date = [formatter dateFromString:dateStr]; if (date) { s_timeBase.systemUptimeBase = [[NSProcessInfo processInfo] systemUptime]; s_timeBase.networkTimBbase = [date timeIntervalSince1970] + s_timeBase.systemUptimeBase - systemUptime; s_timeBase.init_state = s_timeBase.init_state; return; } } } s_timeBase.init_state = s_timeBase.not_init; }]; [dataTask resume]; } @end ","permalink":"https://blog.z6z8.cn/2019/11/20/objective-c-%E7%BD%91%E7%BB%9C%E5%AF%B9%E6%97%B6%E7%9A%84%E7%AE%80%E5%8D%95%E5%AE%9E%E7%8E%B0/","summary":"\u003cp\u003e头文件\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-h\" data-lang=\"h\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//  ZLNetworkTime.h\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//  Created by zxs.zl on 2018/3/12.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#import \u0026lt;Foundation/Foundation.h\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e@\u003c/span\u003einterface ZLNetworkTime : NSObject\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)startSyncTimeFromNetwork;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e(BOOL)syncTimeFromNetworkDone;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e(NSTimeInterval)timeIntervalSince1970;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e@\u003c/span\u003eend\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e实现文件\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//  ZLNetworkTime.m\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//  Created by zxs.zl on 2018/3/12.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#if ! __has_feature(objc_arc)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#error This file must be compiled with ARC. Either turn on ARC for the project or use -fobjc-arc flag\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#endif\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#import \u0026#34;ZLNetworkTime.h\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e _ZLTimeBase_\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    _ZLTimeBase_()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        init_state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e not_init;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        init_count \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSTimeInterval systemUptimeBase;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSTimeInterval networkTimBbase;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eenum\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        not_init,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        initing,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        inited,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    } init_state;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e init_count;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}s_timeBase;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@implementation\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eZLNetworkTime\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e+(NSTimeInterval)\u003cspan style=\"color:#a6e22e\"\u003etimeIntervalSince1970\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (s_timeBase.init_state \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e s_timeBase.inited)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e s_timeBase.networkTimBbase \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e [[NSProcessInfo processInfo] systemUptime] \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e s_timeBase.systemUptimeBase;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e [[NSDate date] timeIntervalSince1970];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e+(\u003cspan style=\"color:#66d9ef\"\u003eBOOL\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003esyncTimeFromNetworkDone\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e s_timeBase.init_state \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e s_timeBase.inited;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e+(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003estartSyncTimeFromNetwork\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (s_timeBase.init_state \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e  s_timeBase.not_init)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (s_timeBase.init_count \u003cspan style=\"color:#f92672\"\u003e\u0026gt;=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003e@synchronized\u003c/span\u003e(self){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (s_timeBase.init_state \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e  s_timeBase.not_init)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        s_timeBase.init_state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e s_timeBase.initing;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    s_timeBase.init_count\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSURLSessionConfiguration \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003econfig \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [NSURLSessionConfiguration defaultSessionConfiguration];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    config.timeoutIntervalForRequest \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    config.requestCachePolicy \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e NSURLRequestReloadIgnoringCacheData;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSURLSession \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e session  \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [NSURLSession sessionWithConfiguration:config];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSURL \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e url \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [NSURL URLWithString:\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;http://time.tianqi.com/\u0026#34;\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSTimeInterval systemUptime \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[NSProcessInfo processInfo] systemUptime];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSURLSessionDataTask \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e dataTask \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [session dataTaskWithURL:url completionHandler:\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e(NSData \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e _Nullable data, NSURLResponse \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e _Nullable response, NSError \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e _Nullable error) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        NSHTTPURLResponse \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e httpResponse \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (NSHTTPURLResponse\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)response;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ([httpResponse isKindOfClass:[NSHTTPURLResponse \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e]] \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e httpResponse.statusCode \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e200\u003c/span\u003e )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            NSString \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e dateStr \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e httpResponse.allHeaderFields[\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;Date\u0026#34;\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (dateStr.length \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e//Mon, 12 Mar 2018 07:21:32 GMT\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                NSDateFormatter \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eformatter \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[NSDateFormatter alloc] init];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                formatter.timeZone \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [NSTimeZone timeZoneWithName:\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;GMT\u0026#34;\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                [formatter setLocale:[[NSLocale alloc] initWithLocaleIdentifier:\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;en_US_POSIX\u0026#34;\u003c/span\u003e]];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                [formatter setDateFormat:\u003cspan style=\"color:#e6db74\"\u003e@\u0026#34;EEE, dd MMM yyyy HH:mm:ss \u0026#39;GMT\u0026#39;\u0026#34;\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                NSDate \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003edate \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [formatter dateFromString:dateStr];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (date)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    s_timeBase.systemUptimeBase \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[NSProcessInfo processInfo] systemUptime];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    s_timeBase.networkTimBbase \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [date timeIntervalSince1970] \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e s_timeBase.systemUptimeBase \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e systemUptime;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    s_timeBase.init_state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e s_timeBase.init_state;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        s_timeBase.init_state \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e s_timeBase.not_init;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [dataTask resume];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Objective-C 网络对时的简单实现"},{"content":"运行一个sh脚本，以普通用户运行，提示 Permission denied,z再使用sudo运行，还是提示 Permission denied。 于是，我用 ls -all 打印脚本的属性\n-rw-rw-rw-@ 1 zjon staff 209535797 11 19 15:18 abc.sh 原来是没有执行属性 x,那么就分配属性\nchmod 0766 abc.sh ","permalink":"https://blog.z6z8.cn/2019/11/19/sudo-%E8%BF%90%E8%A1%8Csh%E8%84%9A%E6%9C%AC%EF%BC%8Cpermission-denied/","summary":"\u003cp\u003e运行一个sh脚本，以普通用户运行，提示 \u003ccode\u003ePermission denied\u003c/code\u003e,z再使用sudo运行，还是提示 \u003ccode\u003ePermission denied\u003c/code\u003e。\n于是，我用 \u003ccode\u003els -all\u003c/code\u003e 打印脚本的属性\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e-rw-rw-rw-@  \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e zjon  staff  \u003cspan style=\"color:#ae81ff\"\u003e209535797\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e11\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e19\u003c/span\u003e 15:18 abc.sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e原来是没有执行属性 \u003ccode\u003ex\u003c/code\u003e,那么就分配属性\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003echmod \u003cspan style=\"color:#ae81ff\"\u003e0766\u003c/span\u003e  abc.sh\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"sudo 运行sh脚本，Permission denied"},{"content":"UINavigationController 提供的常用接口是push和pop，但都是操作最顶层的页面 topViewController，若要操作指定的页面，可以访问属性 viewControllers\n@implementation UINavigationController(zlAddition) - (void)zl_popTheViewController:(UIViewController *)viewController animated:(BOOL)animated { if (viewController.navigationController == self) { if (self.topViewController == viewController) { [self popViewControllerAnimated:animated]; } else { NSMutableArray *arr = [self.viewControllers mutableCopy]; if (arr.lastObject != viewController) { [arr removeObject:viewController]; [self setViewControllers:arr animated:animated]; } } } } @end ","permalink":"https://blog.z6z8.cn/2019/11/19/ios-%E6%8E%A8%E5%87%BA%E6%8C%87%E5%AE%9A%E7%9A%84uiviewcontroller/","summary":"\u003cp\u003e\u003ccode\u003eUINavigationController\u003c/code\u003e 提供的常用接口是push和pop，但都是操作最顶层的页面 \u003ccode\u003etopViewController\u003c/code\u003e，若要操作指定的页面，可以访问属性 \u003ccode\u003eviewControllers\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@implementation\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eUINavigationController\u003c/span\u003e(zlAddition)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e- (\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003ezl_popTheViewController:\u003c/span\u003e(UIViewController \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)viewController \u003cspan style=\"color:#a6e22e\"\u003eanimated:\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eBOOL\u003c/span\u003e)animated\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (viewController.navigationController \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e self)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (self.topViewController \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e viewController)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            [self popViewControllerAnimated:animated];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            NSMutableArray \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003earr \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [self.viewControllers mutableCopy];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (arr.lastObject \u003cspan style=\"color:#f92672\"\u003e!=\u003c/span\u003e viewController)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                [arr removeObject:viewController];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                [self setViewControllers:arr animated:animated];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"iOS 推出指定的UIViewController"},{"content":"在Windows平台上，判断野指针的库函数有一些，如 IsBadReadPtr, IsBadWritePtr， AfxIsValidAddress 。\n在iOS 的Object-C 的MRC时代，也有一个类似的方法 malloc_zone_from_ptr\nextern malloc_zone_t *malloc_zone_from_ptr(const void *ptr); /* Returns the zone for a pointer, or NULL if not in any zone. The ptr must have been returned from a malloc or realloc call. */ 返回zone上的指针，或者返回NULL表示不在任何zone上。 ptr参数必须是已经调用malloc或realloc返回值。 ","permalink":"https://blog.z6z8.cn/2019/11/18/ios-%E5%88%A4%E6%96%AD%E6%8C%87%E9%92%88%E6%8C%87%E5%90%91%E7%9A%84%E5%AF%B9%E8%B1%A1%E6%98%AF%E5%90%A6%E5%B7%B2%E7%BB%8F%E8%A2%AB%E9%87%8A%E6%94%BE/","summary":"\u003cp\u003e在Windows平台上，判断野指针的库函数有一些，如 \u003ccode\u003eIsBadReadPtr\u003c/code\u003e, \u003ccode\u003eIsBadWritePtr\u003c/code\u003e， \u003ccode\u003eAfxIsValidAddress \u003c/code\u003e。\u003c/p\u003e\n\u003cp\u003e在iOS 的Object-C 的MRC时代，也有一个类似的方法 \u003ccode\u003emalloc_zone_from_ptr\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eextern\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003emalloc_zone_t\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003emalloc_zone_from_ptr\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eptr);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e/* Returns the zone for a pointer, or NULL if not in any zone.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e    The ptr must have been returned from a malloc or realloc call. */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e返回\u003c/span\u003ezone上的指针\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e，或者返回\u003c/span\u003eNULL表示不在任何zone上\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eptr参数必须是已经调用malloc或realloc返回值\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e。\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"iOS 判断指针指向的对象是否已经被释放"},{"content":"切换xcode命令行版本\nsudo xcode-select --switch /指定版本的xcode路径Xcode.app 恢复默认的xcode命令行版本 当使用 xcodebuild 莫名其妙的出问题时，可以考虑使用此命令恢复\nsudo xcode-select -r 使用对话框安装命令行工具\nsudo xcode-select --install ","permalink":"https://blog.z6z8.cn/2019/11/14/xcode-select%E5%88%87%E6%8D%A2%E6%88%96%E8%80%85%E6%8C%87%E5%AE%9Axcodebuild%E7%89%88%E6%9C%AC/","summary":"\u003cp\u003e切换xcode命令行版本\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo xcode-select --switch /指定版本的xcode路径Xcode.app\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e恢复默认的xcode命令行版本\n当使用 \u003ccode\u003excodebuild\u003c/code\u003e 莫名其妙的出问题时，可以考虑使用此命令恢复\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo xcode-select -r\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e使用对话框安装命令行工具\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo xcode-select --install\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"xcode-select切换或者指定xcode命令行版本"},{"content":" class __judge_little_endian { public: static inline bool isle() { static const int _a = 0xAABBCCDD; return *(unsigned char *)(\u0026amp;_a) == 0xDD; } }; 对于整数 0xAABBCCDD 大端机器 内存中的排布为： AA BB CC DD 小端机器 内存中的排布为： DD CC BB AA\n","permalink":"https://blog.z6z8.cn/2019/11/12/c-%E5%88%A4%E6%96%AD%E6%9C%BA%E5%99%A8%E7%9A%84%E5%A4%A7%E5%B0%8F%E7%AB%AF/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-cpp\" data-lang=\"cpp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__judge_little_endian\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e isle()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e _a \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0xAABBCCDD\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e_a) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0xDD\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    };\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e对于整数 0xAABBCCDD\n大端机器 内存中的排布为： AA BB CC DD\n小端机器 内存中的排布为： DD CC BB AA\u003c/p\u003e","title":"C++ 判断机器的大小端"},{"content":"使用C++的模板、自动类型推导技术\n#ifndef HtoN_h #define HtoN_h #include \u0026lt;arpa/inet.h\u0026gt; #if __ANDROID__ #ifndef htonll #define htonll(x) htonq(x) #endif #ifndef ntohll #define ntohll(x) ntohq(x) #endif #endif namespace zxszl { template \u0026lt;typename T\u0026gt; T zl_hton (T t) { return t;} template \u0026lt;\u0026gt; inline uint16_t zl_hton\u0026lt;uint16_t\u0026gt; (uint16_t t) { return htons(t); } template \u0026lt;\u0026gt; inline int16_t zl_hton\u0026lt;int16_t\u0026gt; (int16_t t) { return htons(t); } template \u0026lt;\u0026gt; inline uint32_t zl_hton\u0026lt;uint32_t\u0026gt; (uint32_t t) { return htonl(t); } template \u0026lt;\u0026gt; inline int32_t zl_hton\u0026lt;int32_t\u0026gt; (int32_t t) { return htonl(t); } template \u0026lt;\u0026gt; inline uint64_t zl_hton\u0026lt;uint64_t\u0026gt; (uint64_t t) { return htonll(t); } template \u0026lt;\u0026gt; inline int64_t zl_hton\u0026lt;int64_t\u0026gt; (int64_t t) { return htonll(t); } template \u0026lt;typename T\u0026gt; T zl_ntoh (T t) { return t;} template \u0026lt;\u0026gt; inline uint16_t zl_ntoh\u0026lt;uint16_t\u0026gt; (uint16_t t) { return ntohs(t); } template \u0026lt;\u0026gt; inline int16_t zl_ntoh\u0026lt;int16_t\u0026gt; (int16_t t) { return ntohs(t); } template \u0026lt;\u0026gt; inline uint32_t zl_ntoh\u0026lt;uint32_t\u0026gt; (uint32_t t) { return ntohl(t); } template \u0026lt;\u0026gt; inline int32_t zl_ntoh\u0026lt;int32_t\u0026gt; (int32_t t) { return ntohl(t); } template \u0026lt;\u0026gt; inline uint64_t zl_ntoh\u0026lt;uint64_t\u0026gt; (uint64_t t) { return ntohll(t); } template \u0026lt;\u0026gt; inline int64_t zl_ntoh\u0026lt;int64_t\u0026gt; (int64_t t) { return ntohll(t); } class __judge_little_endian { public: static inline bool isle() { static const int _a = 0xAABBCCDD; return *(unsigned char *)(\u0026amp;_a) == 0xDD;} }; #define zl_rorder_s(x) \\ ((__uint16_t)((((__uint16_t)(x) \u0026amp; 0xff00) \u0026gt;\u0026gt; 8) | \\ (((__uint16_t)(x) \u0026amp; 0x00ff) \u0026lt;\u0026lt; 8))) #define zl_rorder_l(x) \\ ((__uint32_t)((((__uint32_t)(x) \u0026amp; 0xff000000) \u0026gt;\u0026gt; 24) | \\ (((__uint32_t)(x) \u0026amp; 0x00ff0000) \u0026gt;\u0026gt; 8) | \\ (((__uint32_t)(x) \u0026amp; 0x0000ff00) \u0026lt;\u0026lt; 8) | \\ (((__uint32_t)(x) \u0026amp; 0x000000ff) \u0026lt;\u0026lt; 24))) #define zl_rorder_ll(x) \\ ((__uint64_t)((((__uint64_t)(x) \u0026amp; 0xff00000000000000ULL) \u0026gt;\u0026gt; 56) | \\ (((__uint64_t)(x) \u0026amp; 0x00ff000000000000ULL) \u0026gt;\u0026gt; 40) | \\ (((__uint64_t)(x) \u0026amp; 0x0000ff0000000000ULL) \u0026gt;\u0026gt; 24) | \\ (((__uint64_t)(x) \u0026amp; 0x000000ff00000000ULL) \u0026gt;\u0026gt; 8) | \\ (((__uint64_t)(x) \u0026amp; 0x00000000ff000000ULL) \u0026lt;\u0026lt; 8) | \\ (((__uint64_t)(x) \u0026amp; 0x0000000000ff0000ULL) \u0026lt;\u0026lt; 24) | \\ (((__uint64_t)(x) \u0026amp; 0x000000000000ff00ULL) \u0026lt;\u0026lt; 40) | \\ (((__uint64_t)(x) \u0026amp; 0x00000000000000ffULL) \u0026lt;\u0026lt; 56))) template \u0026lt;typename T\u0026gt; T zl_htole (T t) { return t;} template \u0026lt;\u0026gt; inline uint16_t zl_htole\u0026lt;uint16_t\u0026gt; (uint16_t t) {return __judge_little_endian::isle() ? t : zl_rorder_s(t);} template \u0026lt;\u0026gt; inline int16_t zl_htole\u0026lt;int16_t\u0026gt; (int16_t t) {return __judge_little_endian::isle() ? t : zl_rorder_s(t);} template \u0026lt;\u0026gt; inline uint32_t zl_htole\u0026lt;uint32_t\u0026gt; (uint32_t t) {return __judge_little_endian::isle() ? t : zl_rorder_l(t);} template \u0026lt;\u0026gt; inline int32_t zl_htole\u0026lt;int32_t\u0026gt; (int32_t t) {return __judge_little_endian::isle() ? t : zl_rorder_l(t);} template \u0026lt;\u0026gt; inline uint64_t zl_htole\u0026lt;uint64_t\u0026gt; (uint64_t t) { return __judge_little_endian::isle() ? t : zl_rorder_ll(t); } template \u0026lt;\u0026gt; inline int64_t zl_htole\u0026lt;int64_t\u0026gt; (int64_t t) { return __judge_little_endian::isle() ? t : zl_rorder_ll(t); } template \u0026lt;typename T\u0026gt; T zl_letoh (T t) { return t;} template \u0026lt;\u0026gt; inline uint16_t zl_letoh\u0026lt;uint16_t\u0026gt; (uint16_t t) {return __judge_little_endian::isle() ? t : zl_rorder_s(t);} template \u0026lt;\u0026gt; inline int16_t zl_letoh\u0026lt;int16_t\u0026gt; (int16_t t) {return __judge_little_endian::isle() ? t : zl_rorder_s(t);} template \u0026lt;\u0026gt; inline uint32_t zl_letoh\u0026lt;uint32_t\u0026gt; (uint32_t t) {return __judge_little_endian::isle() ? t : zl_rorder_l(t);} template \u0026lt;\u0026gt; inline int32_t zl_letoh\u0026lt;int32_t\u0026gt; (int32_t t) {return __judge_little_endian::isle() ? t : zl_rorder_l(t);} template \u0026lt;\u0026gt; inline uint64_t zl_letoh\u0026lt;uint64_t\u0026gt; (uint64_t t) { return __judge_little_endian::isle() ? t : zl_rorder_ll(t); } template \u0026lt;\u0026gt; inline int64_t zl_letoh\u0026lt;int64_t\u0026gt; (int64_t t) { return __judge_little_endian::isle() ? t : zl_rorder_ll(t); } #undef zl_rorder_s #undef zl_rorder_l #undef zl_rorder_ll } #endif /* HtoN_h */ 使用示例\nusing namespace zxszl; short m = 10; short n = zl_hton(m); m = zl_ntoh(n); int x = 100; int y = zl_hton(x); x = zl_ntoh(y); ","permalink":"https://blog.z6z8.cn/2019/11/12/%E5%A4%A7%E5%B0%8F%E7%AB%AF%E8%BD%AC%E6%8D%A2%E7%9A%84c-%E5%B0%81%E8%A3%85-%EF%BC%9Ahton-%EF%BC%8C-ntol/","summary":"\u003cp\u003e使用C++的模板、自动类型推导技术\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-cpp\" data-lang=\"cpp\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#ifndef  HtoN_h\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define HtoN_h\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;arpa/inet.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#if __ANDROID__\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e#ifndef htonll\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#75715e\"\u003e#define htonll(x) htonq(x)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e#endif\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e#ifndef ntohll\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#75715e\"\u003e#define ntohll(x) ntohq(x)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e#endif\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#endif\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003enamespace\u003c/span\u003e zxszl\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003etypename\u003c/span\u003e T\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e T zl_hton (T t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e t;}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003euint16_t\u003c/span\u003e zl_hton\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003euint16_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003euint16_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehtons\u003c/span\u003e(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint16_t\u003c/span\u003e zl_hton\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint16_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint16_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehtons\u003c/span\u003e(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003euint32_t\u003c/span\u003e zl_hton\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003euint32_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003euint32_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehtonl\u003c/span\u003e(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint32_t\u003c/span\u003e zl_hton\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint32_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint32_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehtonl\u003c/span\u003e(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003euint64_t\u003c/span\u003e zl_hton\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003euint64_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003euint64_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehtonll\u003c/span\u003e(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint64_t\u003c/span\u003e zl_hton\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint64_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint64_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehtonll\u003c/span\u003e(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003etypename\u003c/span\u003e T\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e T zl_ntoh (T t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e t;}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003euint16_t\u003c/span\u003e zl_ntoh\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003euint16_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003euint16_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003entohs\u003c/span\u003e(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint16_t\u003c/span\u003e zl_ntoh\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint16_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint16_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003entohs\u003c/span\u003e(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003euint32_t\u003c/span\u003e zl_ntoh\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003euint32_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003euint32_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003entohl\u003c/span\u003e(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint32_t\u003c/span\u003e zl_ntoh\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint32_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint32_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003entohl\u003c/span\u003e(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003euint64_t\u003c/span\u003e zl_ntoh\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003euint64_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003euint64_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003entohll\u003c/span\u003e(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint64_t\u003c/span\u003e zl_ntoh\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint64_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint64_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003entohll\u003c/span\u003e(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__judge_little_endian\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebool\u003c/span\u003e isle() { \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e _a \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0xAABBCCDD\u003c/span\u003e; \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)(\u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e_a) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0xDD\u003c/span\u003e;}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    };\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define zl_rorder_s(x) \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            ((__uint16_t)((((__uint16_t)(x) \u0026amp; 0xff00) \u0026gt;\u0026gt; 8) | \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            (((__uint16_t)(x) \u0026amp; 0x00ff) \u0026lt;\u0026lt; 8)))\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define zl_rorder_l(x) \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            ((__uint32_t)((((__uint32_t)(x) \u0026amp; 0xff000000) \u0026gt;\u0026gt; 24) | \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            (((__uint32_t)(x) \u0026amp; 0x00ff0000) \u0026gt;\u0026gt;  8) | \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            (((__uint32_t)(x) \u0026amp; 0x0000ff00) \u0026lt;\u0026lt;  8) | \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            (((__uint32_t)(x) \u0026amp; 0x000000ff) \u0026lt;\u0026lt; 24)))\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define zl_rorder_ll(x) \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            ((__uint64_t)((((__uint64_t)(x) \u0026amp; 0xff00000000000000ULL) \u0026gt;\u0026gt; 56) | \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            (((__uint64_t)(x) \u0026amp; 0x00ff000000000000ULL) \u0026gt;\u0026gt; 40) | \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            (((__uint64_t)(x) \u0026amp; 0x0000ff0000000000ULL) \u0026gt;\u0026gt; 24) | \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            (((__uint64_t)(x) \u0026amp; 0x000000ff00000000ULL) \u0026gt;\u0026gt;  8) | \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            (((__uint64_t)(x) \u0026amp; 0x00000000ff000000ULL) \u0026lt;\u0026lt;  8) | \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            (((__uint64_t)(x) \u0026amp; 0x0000000000ff0000ULL) \u0026lt;\u0026lt; 24) | \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            (((__uint64_t)(x) \u0026amp; 0x000000000000ff00ULL) \u0026lt;\u0026lt; 40) | \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            (((__uint64_t)(x) \u0026amp; 0x00000000000000ffULL) \u0026lt;\u0026lt; 56)))\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003etypename\u003c/span\u003e T\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e T zl_htole (T t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e t;}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003euint16_t\u003c/span\u003e zl_htole\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003euint16_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003euint16_t\u003c/span\u003e t) {\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e __judge_little_endian\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eisle() \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e t : zl_rorder_s(t);}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint16_t\u003c/span\u003e zl_htole\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint16_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint16_t\u003c/span\u003e t) {\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e __judge_little_endian\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eisle() \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e t :  zl_rorder_s(t);}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003euint32_t\u003c/span\u003e zl_htole\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003euint32_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003euint32_t\u003c/span\u003e t) {\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e __judge_little_endian\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eisle() \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e t :  zl_rorder_l(t);}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint32_t\u003c/span\u003e zl_htole\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint32_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint32_t\u003c/span\u003e t) {\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e __judge_little_endian\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eisle() \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e t :  zl_rorder_l(t);}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003euint64_t\u003c/span\u003e zl_htole\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003euint64_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003euint64_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e __judge_little_endian\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eisle() \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e t :  zl_rorder_ll(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint64_t\u003c/span\u003e zl_htole\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint64_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint64_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e __judge_little_endian\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eisle() \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e t :  zl_rorder_ll(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003etypename\u003c/span\u003e T\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e T zl_letoh (T t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e t;}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003euint16_t\u003c/span\u003e zl_letoh\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003euint16_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003euint16_t\u003c/span\u003e t) {\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e __judge_little_endian\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eisle() \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e t : zl_rorder_s(t);}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint16_t\u003c/span\u003e zl_letoh\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint16_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint16_t\u003c/span\u003e t) {\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e __judge_little_endian\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eisle() \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e t :  zl_rorder_s(t);}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003euint32_t\u003c/span\u003e zl_letoh\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003euint32_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003euint32_t\u003c/span\u003e t) {\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e __judge_little_endian\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eisle() \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e t :  zl_rorder_l(t);}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint32_t\u003c/span\u003e zl_letoh\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint32_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint32_t\u003c/span\u003e t) {\u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e __judge_little_endian\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eisle() \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e t :  zl_rorder_l(t);}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003euint64_t\u003c/span\u003e zl_letoh\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003euint64_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003euint64_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e __judge_little_endian\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eisle() \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e t :  zl_rorder_ll(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003etemplate\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003einline\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint64_t\u003c/span\u003e zl_letoh\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eint64_t\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint64_t\u003c/span\u003e t) { \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e __judge_little_endian\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003eisle() \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e t :  zl_rorder_ll(t); }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#undef zl_rorder_s\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#undef zl_rorder_l\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#undef zl_rorder_ll\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#endif \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e/* HtoN_h */\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e使用示例\u003c/p\u003e","title":"大小端转换的C++ 封装 ：hton ， ntol"},{"content":"我初学React，懵懵懂懂，我把基础的html语法直接搬到JSX文件中，React提示我:\nLine 17:36: Style prop value must be an object react/style-prop-object 我写的是:\nclass CYXQHome extends React.Component { render(){ return ( \u0026lt;div id=\u0026#34;showDiv1\u0026#34; style=\u0026#34;display:none;position:relative;left:69px;width:360px\u0026#34; /\u0026gt; ); } } 出现这种错误的原因是 style=xxxx 那部分，style必须是一个对象 。修改后\n\u0026lt;div id=\u0026#34;showDiv1\u0026#34; style={ { display:\u0026#34;none\u0026#34;,position:\u0026#34;relative\u0026#34;,left:\u0026#34;69px\u0026#34;,width:\u0026#34;360px\u0026#34; } } /\u0026gt; 如上，有两个花括号, {{ {} }},外部的 { {} } 表示这是Javascript句法，里面的 { {} } 是一个对象。\n参考 http://www.mamicode.com/info-detail-1682242.html\n","permalink":"https://blog.z6z8.cn/2019/11/11/react-style-prop-value-must-be-an-object-react-style-prop-object/","summary":"\u003cp\u003e我初学React，懵懵懂懂，我把基础的html语法直接搬到JSX文件中，React提示我:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e Line 17:36:  Style prop value must be an object  react/style-prop-object\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e我写的是:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-jsx\" data-lang=\"jsx\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eCYXQHome\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eextends\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eReact\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eComponent\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#a6e22e\"\u003erender\u003c/span\u003e(){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e             \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;showDiv1\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003estyle\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;display:none;position:relative;left:69px;width:360px\u0026#34;\u003c/span\u003e /\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e             );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e出现这种错误的原因是 \u003ccode\u003estyle=xxxx\u003c/code\u003e 那部分，style必须是一个对象 。修改后\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;div id=\u0026#34;showDiv1\u0026#34; style={ { display:\u0026#34;none\u0026#34;,position:\u0026#34;relative\u0026#34;,left:\u0026#34;69px\u0026#34;,width:\u0026#34;360px\u0026#34; } } /\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e如上，有两个花括号, \u003ccode\u003e{{ {} }}\u003c/code\u003e,外部的 \u003ccode\u003e{ {} } \u003c/code\u003e 表示这是Javascript句法，里面的 \u003ccode\u003e{ {} } \u003c/code\u003e 是一个对象。\u003c/p\u003e\n\u003cp\u003e参考 \u003ca href=\"http://www.mamicode.com/info-detail-1682242.html\"\u003ehttp://www.mamicode.com/info-detail-1682242.html\u003c/a\u003e\u003c/p\u003e","title":"React :  Style prop value must be an object  react/style-prop-object"},{"content":"如题，顺序为 Build Phases 中的显示顺序\n","permalink":"https://blog.z6z8.cn/2019/11/08/xcode-run-script%E7%9A%84%E6%89%A7%E8%A1%8C%E6%9C%89%E9%A1%BA%E5%BA%8F/","summary":"\u003cp\u003e如题，顺序为 \u003ccode\u003eBuild Phases\u003c/code\u003e 中的显示顺序\u003c/p\u003e","title":"Xcode Run Script的执行有顺序"},{"content":"1、 attribute DATA 宏\n#define ZL_PULGIN_DATA(sectname) __attribute((used, section(\u0026#34;__DATA,\u0026#34;#sectname\u0026#34; \u0026#34;))) #define ZL_PULGIN(key,value) \\ const char * k##key##_##value##_zl ZL_PULGIN_DATA(ZLABCEDFG) = \u0026#34;\u0026#34;#key\u0026#34;:\u0026#34;#value\u0026#34;\u0026#34;; //ZLABCEDFG 可以自由定义，但不能超过8个字符 2、在实现文件如 .m 中使用\nZL_PULGIN(hello,world) 3、在运行时读取\n读取函数\n#include \u0026lt;mach-o/getsect.h\u0026gt; #include \u0026lt;mach-o/loader.h\u0026gt; #include \u0026lt;mach-o/dyld.h\u0026gt; #include \u0026lt;dlfcn.h\u0026gt; #import \u0026lt;objc/runtime.h\u0026gt; #import \u0026lt;objc/message.h\u0026gt; static NSArray\u0026lt;NSString *\u0026gt;* BHReadConfiguration(const char *section) { NSMutableArray *configs = [NSMutableArray array]; Dl_info info; dladdr(BHReadConfiguration, \u0026amp;info); #ifndef __LP64__ // const struct mach_header *mhp = _dyld_get_image_header(0); // both works as below line const struct mach_header *mhp = (struct mach_header*)info.dli_fbase; unsigned long size = 0; uint32_t *memory = (uint32_t*)getsectiondata(mhp, \u0026#34;__DATA\u0026#34;, section, \u0026amp; size); #else /* defined(__LP64__) */ const struct mach_header_64 *mhp = (struct mach_header_64*)info.dli_fbase; unsigned long size = 0; uint64_t *memory = (uint64_t*)getsectiondata(mhp, \u0026#34;__DATA\u0026#34;, section, \u0026amp; size); #endif /* defined(__LP64__) */ for(int idx = 0; idx \u0026lt; size/sizeof(void*); ++idx){ char *string = (char*)memory[idx]; NSString *str = [NSString stringWithUTF8String:string]; if(!str)continue; if(str) [configs addObject:str]; } return configs; } 执行结果\nNSArray *ret = BHReadConfiguration(\u0026#34;ZLABCEDFG\u0026#34;); //ret 应为 [\u0026#34;hello:world\u0026#34;] 其一个应用场景就是iOS的组件注册。\n","permalink":"https://blog.z6z8.cn/2019/11/08/%E4%BD%BF%E7%94%A8__attribute-__data-%E5%B0%86%E5%B8%B8%E9%87%8F%E5%86%99%E5%85%A5mach-o%E6%96%87%E4%BB%B6/","summary":"\u003cp\u003e1、 \u003cstrong\u003eattribute\u003c/strong\u003e DATA 宏\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-c\" data-lang=\"c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define ZL_PULGIN_DATA(sectname) __attribute((used, section(\u0026#34;__DATA,\u0026#34;#sectname\u0026#34; \u0026#34;)))\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#define ZL_PULGIN(key,value) \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e    const char * k##key##_##value##_zl ZL_PULGIN_DATA(ZLABCEDFG) = \u0026#34;\u0026#34;#key\u0026#34;:\u0026#34;#value\u0026#34;\u0026#34;;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//ZLABCEDFG 可以自由定义，但不能超过8个字符\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e2、在实现文件如 \u003ccode\u003e.m\u003c/code\u003e 中使用\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eZL_PULGIN(hello,world)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e3、在运行时读取\u003c/p\u003e\n\u003cp\u003e读取函数\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;mach-o/getsect.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;mach-o/loader.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;mach-o/dyld.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#include\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e\u0026lt;dlfcn.h\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#import \u0026lt;objc/runtime.h\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#import \u0026lt;objc/message.h\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e NSArray\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003eNSString \u003cspan style=\"color:#f92672\"\u003e*\u0026gt;*\u003c/span\u003e BHReadConfiguration(\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003esection)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    NSMutableArray \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003econfigs \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [NSMutableArray array];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Dl_info info;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    dladdr(BHReadConfiguration, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003einfo);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#ifndef __LP64__\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e//        const struct mach_header *mhp = _dyld_get_image_header(0); // both works as below line\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e mach_header \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003emhp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e mach_header\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)info.dli_fbase;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    uint32_t \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ememory \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (uint32_t\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)getsectiondata(mhp, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;__DATA\u0026#34;\u003c/span\u003e, section, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e size);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#else \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e/* defined(__LP64__) */\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e mach_header_64 \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003emhp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003estruct\u003c/span\u003e mach_header_64\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)info.dli_fbase;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eunsigned\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e size \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    uint64_t \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003ememory \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (uint64_t\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)getsectiondata(mhp, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;__DATA\u0026#34;\u003c/span\u003e, section, \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e size);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#endif \u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e/* defined(__LP64__) */\u003c/span\u003e\u003cspan style=\"color:#75715e\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e idx \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e; idx \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e size\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003esizeof\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e); \u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003eidx){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003estring \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003echar\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)memory[idx];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        NSString \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003estr \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [NSString stringWithUTF8String:string];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003estr)\u003cspan style=\"color:#66d9ef\"\u003econtinue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(str) [configs addObject:str];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e configs;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e执行结果\u003c/p\u003e","title":"使用__attribute __DATA 将常量写入Mach-O文件"},{"content":"接手一个项目，Debug运行后打开WKWebView的页面，Xcode报出日志\nCould not signal service com.apple.WebKit.WebContent: 113: Could not find specified service 解决办法： 在WKWebView在Window上显示之前，不要加载网页 直白的代码如下：\n[self.view addSubView:wkwebView]; [wkwebView loadRequest:request] ","permalink":"https://blog.z6z8.cn/2019/11/07/could-not-signal-service-com-apple-webkit-webcontent-113-could-not-find-specified-service/","summary":"\u003cp\u003e接手一个项目，Debug运行后打开WKWebView的页面，Xcode报出日志\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eCould \u003cspan style=\"color:#f92672\"\u003enot\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003esignal\u003c/span\u003e service com\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eapple\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eWebKit\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eWebContent: \u003cspan style=\"color:#ae81ff\"\u003e113\u003c/span\u003e: Could \u003cspan style=\"color:#f92672\"\u003enot\u003c/span\u003e find specified service\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e解决办法：\n\u003ccode\u003e在WKWebView在Window上显示之前，不要加载网页\u003c/code\u003e\n直白的代码如下：\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objc\" data-lang=\"objc\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[self.view addSubView:wkwebView];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e[wkwebView loadRequest:request]\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Could not signal service com.apple.WebKit.WebContent: 113: Could not find specified service"},{"content":"一般的同样的html代码，在UIWebView和WKWebView中显示效果是不一样的。例如\n\u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;body\u0026gt; \u0026lt;span\u0026gt;test_input\u0026lt;/span\u0026gt; \u0026lt;input id=\u0026#34;test_input\u0026#34; type=\u0026#34;text\u0026#34;\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; 显示效果：\n可以看出两者有明显的区别。 那么如何适配呢？有两个方法（本质上是一个）。 1、如果是H5适配WKWebView的话，需要在H5添加如下代码\n\u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width\u0026#34;\u0026gt; 完整的html如下\n\u0026lt;!DOCTYPE html\u0026gt; \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width\u0026#34;\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;span\u0026gt;test_input\u0026lt;/span\u0026gt; \u0026lt;input id=\u0026#34;test_input\u0026#34; type=\u0026#34;text\u0026#34;\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; 2、如果是WKWebView适配H5的话，那么就需要替前端添加相同的H5代码，实现如下\n//js代码，在文档加载完毕后，添加head的子节点 //节点内容为\u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width\u0026#34;\u0026gt; let jScript = \u0026#34;var meta = document.createElement(\u0026#39;meta\u0026#39;); meta.setAttribute(\u0026#39;name\u0026#39;, \u0026#39;viewport\u0026#39;); meta.setAttribute(\u0026#39;content\u0026#39;, \u0026#39;width=device-width\u0026#39;); document.getElementsByTagName(\u0026#39;head\u0026#39;)[0].appendChild(meta);\u0026#34;; let wkUScript = WKUserScript.init(source: jScript, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: true); let wkUController = WKUserContentController.init(); wkUController.addUserScript(wkUScript); let wkconfig = WKWebViewConfiguration.init(); wkconfig.userContentController = wkUController; _webView = WKWebView.init(frame: CGRect.init(x: 0, y: 0, width: self.view.bounds.size.width, height: self.view.bounds.size.height), configuration: wkconfig); self.view.addSubview(_webView); let htmlfile = Bundle.main.path(forResource: \u0026#34;test\u0026#34;, ofType: \u0026#34;.html\u0026#34;); let url = URL.init(fileURLWithPath: htmlfile!); let request = URLRequest.init(url: url); _webView.load(request); 参考 https://blog.csdn.net/GYMotgm/article/details/77944163\n","permalink":"https://blog.z6z8.cn/2019/11/04/wkwebview%EF%BC%9A%E9%80%82%E9%85%8Dh5%E9%A1%B5%E9%9D%A2%E7%9A%84%E6%98%BE%E7%A4%BA%E5%B0%BA%E5%AF%B8/","summary":"\u003cp\u003e一般的同样的html代码，在UIWebView和WKWebView中显示效果是不一样的。例如\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u0026lt;!DOCTYPE html\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003ehtml\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003espan\u003c/span\u003e\u0026gt;test_input\u0026lt;/\u003cspan style=\"color:#f92672\"\u003espan\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003einput\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test_input\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;text\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ehtml\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e显示效果：\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2019/11/wkwebview_uiwebview.png\"\u003e\u003c/p\u003e\n\u003cp\u003e可以看出两者有明显的区别。\n那么如何适配呢？有两个方法（本质上是一个）。\n1、如果是H5适配WKWebView的话，需要在H5添加如下代码\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003emeta\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;viewport\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econtent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;width=device-width\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e完整的html如下\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u0026lt;!DOCTYPE html\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003ehtml\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003ehead\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003emeta\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ename\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;viewport\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003econtent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;width=device-width\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ehead\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003espan\u003c/span\u003e\u0026gt;test_input\u0026lt;/\u003cspan style=\"color:#f92672\"\u003espan\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;\u003cspan style=\"color:#f92672\"\u003einput\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test_input\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;text\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ehtml\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e2、如果是WKWebView适配H5的话，那么就需要替前端添加相同的H5代码，实现如下\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-swift\" data-lang=\"swift\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#75715e\"\u003e//js代码，在文档加载完毕后，添加head的子节点\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#75715e\"\u003e//节点内容为\u0026lt;meta name=\u0026#34;viewport\u0026#34; content=\u0026#34;width=device-width\u0026#34;\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e jScript = \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;var meta = document.createElement(\u0026#39;meta\u0026#39;); meta.setAttribute(\u0026#39;name\u0026#39;, \u0026#39;viewport\u0026#39;); meta.setAttribute(\u0026#39;content\u0026#39;, \u0026#39;width=device-width\u0026#39;); document.getElementsByTagName(\u0026#39;head\u0026#39;)[0].appendChild(meta);\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e wkUScript = WKUserScript.\u003cspan style=\"color:#66d9ef\"\u003einit\u003c/span\u003e(source: jScript, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e wkUController = WKUserContentController.\u003cspan style=\"color:#66d9ef\"\u003einit\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        wkUController.addUserScript(wkUScript);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e wkconfig = WKWebViewConfiguration.\u003cspan style=\"color:#66d9ef\"\u003einit\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        wkconfig.userContentController = wkUController;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        _webView = WKWebView.\u003cspan style=\"color:#66d9ef\"\u003einit\u003c/span\u003e(frame: CGRect.\u003cspan style=\"color:#66d9ef\"\u003einit\u003c/span\u003e(x: \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, y: \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e, width: \u003cspan style=\"color:#66d9ef\"\u003eself\u003c/span\u003e.view.bounds.size.width, height: \u003cspan style=\"color:#66d9ef\"\u003eself\u003c/span\u003e.view.bounds.size.height), configuration: wkconfig);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eself\u003c/span\u003e.view.addSubview(_webView);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e htmlfile = Bundle.main.path(forResource: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test\u0026#34;\u003c/span\u003e, ofType: \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;.html\u0026#34;\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e url = URL.\u003cspan style=\"color:#66d9ef\"\u003einit\u003c/span\u003e(fileURLWithPath: htmlfile!);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elet\u003c/span\u003e request = URLRequest.\u003cspan style=\"color:#66d9ef\"\u003einit\u003c/span\u003e(url: url);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        _webView.load(request);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e参考 \u003ca href=\"https://blog.csdn.net/GYMotgm/article/details/77944163\"\u003ehttps://blog.csdn.net/GYMotgm/article/details/77944163\u003c/a\u003e\u003c/p\u003e","title":"WKWebView：适配H5页面的显示尺寸"},{"content":"sudo rm -rf /Applications/Xcode.app sudo rm -rf /Library/Preferences/com.apple.dt.Xcode.plist rm -rf ~/Library/Preferences/com.apple.dt.Xcode.plist rm -rf ~/Library/Caches/com.apple.dt.Xcode rm -rf ~/Library/Application\\ Support/Xcode rm -rf ~/Library/Developer/Xcode rm -rf ~/Library/Developer/CoreSimulator rm -rf ~/Library/Developer/XCPGDevices ","permalink":"https://blog.z6z8.cn/2019/11/01/%E5%8D%B8%E8%BD%BDxcode%E7%9A%84%E5%91%BD%E4%BB%A4/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo rm -rf /Applications/Xcode.app\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo rm -rf /Library/Preferences/com.apple.dt.Xcode.plist\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erm -rf ~/Library/Preferences/com.apple.dt.Xcode.plist\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erm -rf ~/Library/Caches/com.apple.dt.Xcode\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erm -rf ~/Library/Application\u003cspan style=\"color:#ae81ff\"\u003e\\ \u003c/span\u003eSupport/Xcode\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erm -rf ~/Library/Developer/Xcode\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erm -rf ~/Library/Developer/CoreSimulator\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003erm -rf ~/Library/Developer/XCPGDevices\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"卸载Xcode的命令"},{"content":"因为一些编译构建问题，我需要降级CocoaPods 过程如下:\n卸载当前版本的CocoaPods sudo gem uninstall cocoapods 下载指定版本的CocoaPods，编译gem包 下载地址https://github.com/CocoaPods/CocoaPods/releases 将源码下载后解压，进入源码目录，编译gem包\ngem build cocopods.gemspec 编译产物是 cocopods-版本号.gem\n使用本地gem包安装CocoaPods sudo gem install cocopods-版本号.gem ","permalink":"https://blog.z6z8.cn/2019/10/31/%E5%AE%89%E8%A3%85%E6%8C%87%E5%AE%9A%E7%89%88%E6%9C%AC%E7%9A%84cocoapods/","summary":"\u003cp\u003e因为一些编译构建问题，我需要降级CocoaPods\n过程如下:\u003c/p\u003e\n\u003ch1 id=\"卸载当前版本的cocoapods\"\u003e卸载当前版本的CocoaPods\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo gem uninstall cocoapods\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"下载指定版本的cocoapods编译gem包\"\u003e下载指定版本的CocoaPods，编译gem包\u003c/h1\u003e\n\u003cp\u003e下载地址https://github.com/CocoaPods/CocoaPods/releases\n将源码下载后解压，进入源码目录，编译gem包\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egem build cocopods.gemspec\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e编译产物是 cocopods-版本号.gem\u003c/p\u003e\n\u003ch1 id=\"使用本地gem包安装cocoapods\"\u003e使用本地gem包安装CocoaPods\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo gem install cocopods-版本号.gem\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"安装指定版本的CocoaPods"},{"content":"列出工作空间中的所有scheme xcodebuild -list -workspace abc.xcworkspace 输出 Information about workspace \u0026#34;abc\u0026#34;: Schemes: abc AFNetworking FMDB GTMBase64 Minizip Pods-abc 列出项目的所有target及Configurations xcodebuild -list -project abc.xcodeproj 输出 Information about project \u0026#34;abc\u0026#34;: Targets: abc Build Configurations: Debug Release If no build configuration is specified and -scheme is not passed then \u0026#34;Release\u0026#34; is used. Schemes: abc 编译指定的scheme或Target 指定scheme xcodebuild -workspace abc.xcworkspace -scheme test 或者 xcodebuild -project abc.xcodeproj -scheme test 此时默认编译 Release 版\n指定target xcodebuild -project abc.xcodeproj -target test 指定 configuration xcodebuild -workspace abc.xcworkspace -scheme test -configuration Debug 此时编译 Debug 版\n指定编译依赖的sdk环境 xcodebuild -workspace abc.xcworkspace -scheme test -configuration Debug -sdk iphoneos 将使用名字为 iphoneos（真机版）的sdk环境编译，同样的 -sdk iphonesimulator 指定编译模拟器版本\n需要注意的，当不指定 -sdk 参数时，xcodebuild的某些版本会同时构建mac ,iPhone, iPad对应的版本\n指定编译输出产物的目录 BUILD_DIR，在自动打包时很有用\nxcodebuild -workspace abc.xcworkspace -scheme test -configuration Debug -sdk iphoneos BUILD_DIR=/a/b/c/d/e 指定Xcode支持的其他配置 以bitcode为例，设置键 ENABLE_BITCODE 的值：\nxcodebuild -workspace abc.xcworkspace -scheme test ENABLE_BITCODE=NO 其他配置的键需要打开xcode的具体项目配置文件自行寻找\n","permalink":"https://blog.z6z8.cn/2019/10/30/ios-xcodebuild%E8%87%AA%E5%8A%A8%E6%9E%84%E5%BB%BA%E5%B8%B8%E7%94%A8%E5%91%BD%E4%BB%A4/","summary":"\u003ch1 id=\"列出工作空间中的所有scheme\"\u003e列出工作空间中的所有scheme\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003excodebuild -list -workspace abc.xcworkspace\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e输出\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eInformation about workspace \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;abc\u0026#34;\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Schemes:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            abc\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        AFNetworking\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        FMDB\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        GTMBase64\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Minizip\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Pods-abc\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"列出项目的所有target及configurations\"\u003e列出项目的所有target及Configurations\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003excodebuild -list -project abc.xcodeproj\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e输出\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eInformation about project \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;abc\u0026#34;\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Targets:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        abc\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Build Configurations:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Debug\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        Release\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    If no build configuration is specified and -scheme is not passed \u003cspan style=\"color:#66d9ef\"\u003ethen\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;Release\u0026#34;\u003c/span\u003e is used.\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Schemes:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        abc\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"编译指定的scheme或target\"\u003e编译指定的scheme或Target\u003c/h1\u003e\n\u003ch2 id=\"指定scheme\"\u003e指定scheme\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003excodebuild -workspace abc.xcworkspace -scheme test\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e或者\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003excodebuild -project abc.xcodeproj -scheme test\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e此时默认编译 \u003ccode\u003eRelease\u003c/code\u003e 版\u003c/p\u003e","title":"iOS xcodebuild自动构建常用命令"},{"content":"JSONModel，模型和JSON数据之间相互转换，或者模型和JSON数据的序列化、反序列化。\n不同语言实现细节不一样，也并不是所有语言都可以实现。这里我参考Objective-C语言的JSONModel实现机制，设计了一种Python运行时JSON和Model的互转方案思路。\nobject类 用dir打印object\n\u0026gt;\u0026gt;\u0026gt; dir(object) [\u0026#39;__class__\u0026#39;, \u0026#39;__delattr__\u0026#39;, \u0026#39;__doc__\u0026#39;, \u0026#39;__format__\u0026#39;, \u0026#39;__getattribute__\u0026#39;, \u0026#39;__hash__\u0026#39;, \u0026#39;__init__\u0026#39;, \u0026#39;__new__\u0026#39;, \u0026#39;__reduce__\u0026#39;, \u0026#39;__reduce_ex__\u0026#39;, \u0026#39;__repr__\u0026#39;, \u0026#39;__setattr__\u0026#39;, \u0026#39;__sizeof__\u0026#39;, \u0026#39;__str__\u0026#39;, \u0026#39;__subclasshook__\u0026#39;] 挨个找，看到两个方法 __setattr__ 和 __getattribute__，看名字也大概知道用途,基本意思就是可以通过 __setattr__ 和 __getattribute__ 访问object实例的属性值。\n具体可参考https://www.cnblogs.com/elie/p/6685429.html\n__setattr__ 如果类自定义了 __setattr__ 方法，当通过实例获取属性尝试赋值时，就会调用 __setattr__。常规的对实例属性赋值，被赋值的属性和值会存入实例属性字典 __dict__ 中；如下类自定义了 __setattr__,对实例属性的赋值就会调用它。类定义中的self.attr也同样，所以在 __setattr__ 下还有self.attr的赋值操作就会出现无线递归的调用 __setattr__ 的情况。自己实现 __setattr__ 有很大风险，一般情况都还是继承object类的 __setattr__ 方法。\n__getattribute__ 实例instance通过instance.name访问属性name， __getattribute__ 方法一直会被调用，无论属性name是否追溯到。如果类还定义了 __getattr__ 方法，除非通过 __getattribute__ 显式的调用它，或者 __getattribute__ 方法出现AttributeError错误，否则 __getattr__ 方法不会被调用了。如果在 __getattribute__(self, attr) 方法下存在通过self.attr访问属性，会出现无限递归错误。\n步骤 只讨论最小场景（当然可以自行扩展）\njson -\u0026gt; model 这里假设json是一个字典，且没有嵌套情况。 并且假设应知道model的类名，一个字典对应一个model。\n遍历json所有key ,然后按照key名称给model的属性赋值。\n示意代码\ndict = json数据 model=类的实例 for (key,value) in dict.items(): model.__setattr__(key,value) model -\u0026gt; json 这里假设model的所有属性都能转化为对应的json数据，且没有嵌套。 这里，还需要借助 __dict__ 函数\n示意代码\ndict = {} for (name,_) in model.__dict__.items(): value = model.__getattribute__(name) if value != None: dict[name] = value ","permalink":"https://blog.z6z8.cn/2019/10/28/python-jsonmodel%E7%9A%84%E5%AE%9E%E7%8E%B0%E6%80%9D%E8%B7%AF/","summary":"\u003cp\u003eJSONModel，模型和JSON数据之间相互转换，或者模型和JSON数据的序列化、反序列化。\u003c/p\u003e\n\u003cp\u003e不同语言实现细节不一样，也并不是所有语言都可以实现。这里我参考Objective-C语言的JSONModel实现机制，设计了一种Python运行时JSON和Model的互转方案思路。\u003c/p\u003e\n\u003ch1 id=\"object类\"\u003eobject类\u003c/h1\u003e\n\u003cp\u003e用dir打印object\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026gt;\u0026gt;\u0026gt; dir\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eobject\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__class__\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__delattr__\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__doc__\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__format__\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__getattribute__\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__hash__\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__init__\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__new__\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__reduce__\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__reduce_ex__\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__repr__\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__setattr__\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__sizeof__\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__str__\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;__subclasshook__\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e挨个找，看到两个方法 \u003ccode\u003e__setattr__\u003c/code\u003e 和 \u003ccode\u003e__getattribute__\u003c/code\u003e，看名字也大概知道用途,基本意思就是可以通过 \u003ccode\u003e__setattr__\u003c/code\u003e 和 \u003ccode\u003e__getattribute__ \u003c/code\u003e 访问object实例的属性值。\u003c/p\u003e\n\u003cp\u003e具体可参考https://www.cnblogs.com/elie/p/6685429.html\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e__setattr__\u003c/code\u003e 如果类自定义了 \u003ccode\u003e__setattr__\u003c/code\u003e 方法，当通过实例获取属性尝试赋值时，就会调用 \u003ccode\u003e__setattr__\u003c/code\u003e。常规的对实例属性赋值，被赋值的属性和值会存入实例属性字典 \u003ccode\u003e__dict__\u003c/code\u003e 中；如下类自定义了 \u003ccode\u003e__setattr__\u003c/code\u003e,对实例属性的赋值就会调用它。类定义中的self.attr也同样，所以在 \u003ccode\u003e__setattr__\u003c/code\u003e 下还有self.attr的赋值操作就会出现无线递归的调用 \u003ccode\u003e__setattr__\u003c/code\u003e 的情况。自己实现 \u003ccode\u003e__setattr__\u003c/code\u003e 有很大风险，一般情况都还是继承object类的 \u003ccode\u003e__setattr__\u003c/code\u003e 方法。\u003c/p\u003e\n\u003c/li\u003e\n\u003cli\u003e\n\u003cp\u003e\u003ccode\u003e__getattribute__ \u003c/code\u003e 实例instance通过instance.name访问属性name， \u003ccode\u003e__getattribute__\u003c/code\u003e 方法一直会被调用，无论属性name是否追溯到。如果类还定义了 \u003ccode\u003e__getattr__\u003c/code\u003e 方法，除非通过 \u003ccode\u003e__getattribute__\u003c/code\u003e 显式的调用它，或者 \u003ccode\u003e__getattribute__\u003c/code\u003e 方法出现AttributeError错误，否则 \u003ccode\u003e__getattr__\u003c/code\u003e 方法不会被调用了。如果在 \u003ccode\u003e__getattribute__(self, attr)\u003c/code\u003e 方法下存在通过self.attr访问属性，会出现无限递归错误。\u003c/p\u003e\n\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"步骤\"\u003e步骤\u003c/h1\u003e\n\u003cp\u003e只讨论最小场景（当然可以自行扩展）\u003c/p\u003e\n\u003ch2 id=\"json---model\"\u003ejson -\u0026gt; model\u003c/h2\u003e\n\u003cp\u003e这里假设json是一个字典，且没有嵌套情况。\n并且假设应知道model的类名，一个字典对应一个model。\u003c/p\u003e\n\u003cp\u003e遍历json所有key ,然后按照key名称给model的属性赋值。\u003c/p\u003e\n\u003cp\u003e示意代码\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edict \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e json数据\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emodel\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e类的实例\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (key,value) \u003cspan style=\"color:#f92672\"\u003ein\u003c/span\u003e dict\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eitems():\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            model\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003e__setattr__\u003c/span\u003e(key,value)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"model---json\"\u003emodel -\u0026gt; json\u003c/h2\u003e\n\u003cp\u003e这里假设model的所有属性都能转化为对应的json数据，且没有嵌套。\n这里，还需要借助 \u003ccode\u003e__dict__\u003c/code\u003e 函数\u003c/p\u003e","title":"Python JSONModel的实现思路"},{"content":"ssh登陆，添加 -v 参数，可以打印详细的登陆过程\nssh -v 主机配置 例如 ssh -v -T -D 62403 -o ConnectTimeout=15 我的主机配置 但是经常超时，卡在了\ndebug1：pledge: network 主要原因是大量的爆破扫描，因此导致btmp这个文件巨大。\n解决办法\necho \u0026#34;\u0026#34; \u0026gt; /var/log/btmp 或者 直接删除这个日志文件 重启sshd服务 参考: https://blog.csdn.net/Liv2005/article/details/84258580\n","permalink":"https://blog.z6z8.cn/2019/10/28/ssh%E7%99%BB%E9%99%86%E6%85%A2%EF%BC%8C%E7%BB%8F%E5%B8%B8%E8%B6%85%E6%97%B6%EF%BC%8C%E5%8D%A1%E5%9C%A8pledge-network%E4%B9%8B%E5%90%8E/","summary":"\u003cp\u003essh登陆，添加 \u003ccode\u003e-v\u003c/code\u003e 参数，可以打印详细的登陆过程\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003essh -v  主机配置\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e例如\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003essh -v -T -D 62403 -o ConnectTimeout=15  我的主机配置\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e但是经常超时，卡在了\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003edebug1：pledge: network\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e主要原因是大量的爆破扫描，因此导致btmp这个文件巨大。\u003c/p\u003e\n\u003cp\u003e解决办法\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eecho \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003elog\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003ebtmp\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e或者\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e直接删除这个日志文件\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e重启\u003c/span\u003esshd服务\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e参考: \u003ca href=\"https://blog.csdn.net/Liv2005/article/details/84258580\"\u003ehttps://blog.csdn.net/Liv2005/article/details/84258580\u003c/a\u003e\u003c/p\u003e","title":"ssh登陆慢，经常超时，卡在pledge: network之后"},{"content":"我用wxGlade生成Python的UI代码，但添加监听EVT_CLOSE事件代码时，运行崩溃\nTraceback (most recent call last): File \u0026#34;/Users/zxs.zl/Desktop/Yan/github/XcodeBuildPyUI/zlBuild/app.py\u0026#34;, line 16, in OnInit self.frame = mainFrame(None, wx.ID_ANY, \u0026#34;\u0026#34;) File \u0026#34;/Users/zxs.zl/Desktop/Yan/github/XcodeBuildPyUI/zlBuild/mainFrame.py\u0026#34;, line 38, in __init__ self.Bind(wx.EVT_CLOSE, self.onWindowClose, self.frame) AttributeError: \u0026#39;mainFrame\u0026#39; object has no attribute \u0026#39;frame\u0026#39; 生成的代码部分:\nclass mainFrame(wx.Frame): def __init__(self, *args, **kwds): # begin wxGlade: mainFrame.__init__ 部分代码如下 self.Bind(wx.EVT_BUTTON, self.onClickBuildLibButton, self.buildLibButton) self.Bind(wx.EVT_CLOSE, self.onWindowClose, self.frame) # end wxGlade 将生成的代码 self.frame 改为 self，运行正常\n# self.Bind(wx.EVT_CLOSE, self.onWindowClose, self.frame) self.Bind(wx.EVT_CLOSE, self.onWindowClose, self) ","permalink":"https://blog.z6z8.cn/2019/10/23/wxglade-%E7%94%9F%E6%88%90%E7%9A%84evt_close%E5%85%B3%E9%97%AD%E4%BA%8B%E4%BB%B6%E4%BB%A3%E7%A0%81%EF%BC%8C%E8%BF%90%E8%A1%8C%E5%B4%A9%E6%BA%83/","summary":"\u003cp\u003e我用wxGlade生成Python的UI代码，但添加监听EVT_CLOSE事件代码时，运行崩溃\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eTraceback \u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003emost recent call last\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e:\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  File \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/Users/zxs.zl/Desktop/Yan/github/XcodeBuildPyUI/zlBuild/app.py\u0026#34;\u003c/span\u003e, line 16, in OnInit\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    self.frame \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e mainFrame\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003eNone, wx.ID_ANY, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  File \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/Users/zxs.zl/Desktop/Yan/github/XcodeBuildPyUI/zlBuild/mainFrame.py\u0026#34;\u003c/span\u003e, line 38, in __init__\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    self.Bind\u003cspan style=\"color:#f92672\"\u003e(\u003c/span\u003ewx.EVT_CLOSE, self.onWindowClose, self.frame\u003cspan style=\"color:#f92672\"\u003e)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eAttributeError: \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;mainFrame\u0026#39;\u003c/span\u003e object has no attribute \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;frame\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e生成的代码部分:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emainFrame\u003c/span\u003e(wx\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eFrame):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003edef\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__init__\u003c/span\u003e(self, \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003eargs, \u003cspan style=\"color:#f92672\"\u003e**\u003c/span\u003ekwds):\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e# begin wxGlade: mainFrame.__init__\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e       部分代码如下\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eBind(wx\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eEVT_BUTTON, self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eonClickBuildLibButton, self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003ebuildLibButton)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eBind(wx\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eEVT_CLOSE, self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eonWindowClose, self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eframe)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e# end wxGlade\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e将生成的代码 \u003ccode\u003eself.frame\u003c/code\u003e 改为 \u003ccode\u003eself\u003c/code\u003e，运行正常\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-python\" data-lang=\"python\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e# self.Bind(wx.EVT_CLOSE, self.onWindowClose, self.frame)\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eself\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eBind(wx\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eEVT_CLOSE, self\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003eonWindowClose, self)\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"wxGlade : 生成的EVT_CLOSE关闭事件代码，运行崩溃"},{"content":"升级到macOS Catalina 10.15后，打开一些应用程序，会弹出 xxx向访问\u0026quot;桌面\u0026quot;文件夹 对话框。 如果点击 不允许，有些应用程序会触发崩溃退出，但是再次打开这些应用程序，系统不会重新弹出上门的对话框，应用程序也就再次退出了。 解决办法是在 系统偏好设置 -\u0026gt; 安全和隐私 -\u0026gt; 文件和文件夹 找到对应的应用程序，设置 允许 权限就好了。 ","permalink":"https://blog.z6z8.cn/2019/10/22/macos-catalina-10-15-xxx%E5%90%91%E8%AE%BF%E9%97%AE%E6%A1%8C%E9%9D%A2%E6%96%87%E4%BB%B6%E5%A4%B9/","summary":"\u003cp\u003e升级到macOS Catalina 10.15后，打开一些应用程序，会弹出 \u003ccode\u003exxx向访问\u0026quot;桌面\u0026quot;文件夹\u003c/code\u003e 对话框。\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2019/10/macos%E8%AE%BF%E9%97%AE%E6%A1%8C%E9%9D%A2%E6%96%87%E4%BB%B6%E5%A4%B9.png\"\u003e\u003c/p\u003e\n\u003cp\u003e如果点击 \u003ccode\u003e不允许\u003c/code\u003e，有些应用程序会触发崩溃退出，但是再次打开这些应用程序，系统不会重新弹出上门的对话框，应用程序也就再次退出了。\n解决办法是在 \u003ccode\u003e系统偏好设置 -\u0026gt; 安全和隐私 -\u0026gt; 文件和文件夹 \u003c/code\u003e 找到对应的应用程序，设置 \u003ccode\u003e允许\u003c/code\u003e 权限就好了。\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2019/10/macOS-Catalina-%E6%96%87%E4%BB%B6%E5%92%8C%E6%96%87%E4%BB%B6%E5%A4%B9%E9%9A%90%E7%A7%81.png\"\u003e\u003c/p\u003e","title":"macOS Catalina 10.15 : xxx向访问\"桌面\"文件夹"},{"content":"在做swift和OC混编时，学到的. 使用 attribute 指令，将Objective-C的类标记为objc_subclassing_restricted。 如\n//标记ClassA不能被继承 __attribute__((objc_subclassing_restricted)) @interface ClassA : NSObject @end @implementation ClassA @end //下面代码会报错 //error: Cannot subclass a class that was declared with the \u0026#39;objc_subclassing_restricted\u0026#39; attribute @interface ClassB: ClassA @end @implementation ClassB @end ","permalink":"https://blog.z6z8.cn/2019/10/18/%E6%A0%87%E8%AE%B0objective-c%E7%9A%84%E7%B1%BB%E4%B8%8D%E8%83%BD%E8%A2%AB%E7%BB%A7%E6%89%BF/","summary":"\u003cp\u003e在做swift和OC混编时，学到的.\n使用 \u003cstrong\u003eattribute\u003c/strong\u003e 指令，将Objective-C的类标记为objc_subclassing_restricted。\n如\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objectivec\" data-lang=\"objectivec\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//标记ClassA不能被继承\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e__attribute__((objc_subclassing_restricted))\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@interface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eClassA\u003c/span\u003e : \u003cspan style=\"color:#a6e22e\"\u003eNSObject\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@implementation\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eClassA\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//下面代码会报错\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//error: Cannot subclass a class that was declared with the \u0026#39;objc_subclassing_restricted\u0026#39; attribute\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e@interface\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eClassB\u003c/span\u003e: \u003cspan style=\"color:#a6e22e\"\u003eClassA\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@implementation\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eClassB\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003e@end\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"标记Objective-C的类不能被继承"},{"content":"@ 这次iOS13的发布，其改动步子有点大了，尤其是是其多场景窗口（多任务）已经颠覆了老应用的设计基础了\u0026mdash;-数据的协同共享处理机制（本文不谈，哈哈） 这里记录下一些界面层面的适配体会：\n如果是 Xcode 10 及以下创建的老项目，用 Xcode 11 打开，老项目基本能正常运行。但是如果用 Xcode 11 创建新项目，还按照老项目思路写代码就会有坑了。\n用 Xcode 11 创建一个 Single View App 项目，会多生成一些文件和代码\n多了SceneDelegate代理 Info.plist里面多了Application Scene Manifest配置 多出来的这些文件和代码，影响最直观的是多场景窗口和导航控制器。\n适配方案——不支持多场景窗口 这种适配方案最简单。 将多出来的文件和代码删除就好了\n删除SceneDelegate代理文件 (可选) 删除 Info.plist里面的Application Scene Manifest配置（一定要删除） 删除 AppDelegate代理的两个方法： application:configurationForConnectingSceneSession:options: application: didDiscardSceneSessions: 这两个方法一定要删除，否则使用纯代码创建的 Window 和导航控制器 UINavigationController 不会生效。 适配方案——支持多场景窗口 先说我遇到的一些现象。 尽管我不会为每个应用自定义窗口和导航，但我我依然会使用纯代码创建 UIWindow 和 UINavigationController，具体如下\n//AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //在Xcode11创建的项目中，需要自行给AppDelegate添加属性window //自定义Window self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; //自定义导航控制器 UINavigationController *rootNavgationController = [[UINavigationController alloc] initWithRootViewController:[ViewController new]]; //导航控制是rootViewController self.window.rootViewController = rootNavgationController; //现实Window [self.window makeKeyAndVisible]; return YES; } Xcode 11 创建的项目中，写入上述代码运行App，结果发现这部分代码虽然执行了，但是通过UIViewController的 self.navigationController 获取的导航竟然是 nil。 从现象反推过程，既然代码执行了，那么很大可能是 self.window 没有显示在屏幕上。 查看iOS13下 UIWindow 的定义，有这么一条\n// If nil, window will not appear on any screen. // changing the UIWindowScene may be an expensive operation and should not be done in performance-sensitive code @property(nullable, nonatomic, weak) UIWindowScene *windowScene API_AVAILABLE(ios(13.0)); 如果 UIWindow 的属性 windowScene 为nil，那么这个 UIWindow 则不会显示在任何屏幕上。\n既然问题找到了，那么解决起来也就容易了，一番断点调试跟踪代码后，加单的解决办法是在 SceneDelegate 的方法 scene:willConnectToSession:options: 中创建 UIWindow 和 UINavigationController\n//SceneDelegate - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.windowScene = (UIWindowScene*)scene; UINavigationController *rootNavgationController = [[UINavigationController alloc] initWithRootViewController:[ViewController new]]; self.window.rootViewController = rootNavgationController; [self.window makeKeyAndVisible]; } 同时兼容iOS13和iOS12及以下 多场景窗口、SceneDelegate等只有在iOS13才可以，若要考虑iOS12及以下的运行环境，那么上述解决方案就要考虑环境版本匹配了，完整代码如下\nAppDelegate部分代码\n//AppDelegate.h @interface AppDelegate : UIResponder \u0026lt;UIApplicationDelegate\u0026gt; @property (strong, nonatomic) UIWindow *window; @end //AppDelegate.m @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. if (@available(iOS 13,*)) { return YES; } else { self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; UINavigationController *rootNavgationController = [[UINavigationController alloc] initWithRootViewController:[ViewController new]]; self.window.rootViewController = rootNavgationController; [self.window makeKeyAndVisible]; return YES; } } #pragma mark - UISceneSession lifecycle - (UISceneConfiguration *)application:(UIApplication *)application configurationForConnectingSceneSession:(UISceneSession *)connectingSceneSession options:(UISceneConnectionOptions *)options { return [[UISceneConfiguration alloc] initWithName:@\u0026#34;Default Configuration\u0026#34; sessionRole:connectingSceneSession.role]; } @end SceneDelegate部分代码\n//SceneDelegate.h @interface SceneDelegate : UIResponder \u0026lt;UIWindowSceneDelegate\u0026gt; @property (strong, nonatomic) UIWindow * window; @end //SceneDelegate.m @implementation SceneDelegate - (void)scene:(UIScene *)scene willConnectToSession:(UISceneSession *)session options:(UISceneConnectionOptions *)connectionOptions { self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds]; self.window.windowScene = (UIWindowScene*)scene; UINavigationController *rootNavgationController = [[UINavigationController alloc] initWithRootViewController:[ViewController new]]; self.window.rootViewController = rootNavgationController; [self.window makeKeyAndVisible]; } @end ","permalink":"https://blog.z6z8.cn/2019/10/17/ios13%E9%80%82%E9%85%8D%EF%BC%9Auiwindow%E7%AA%97%E5%8F%A3%E5%92%8C%E5%AF%BC%E8%88%AA%E6%8E%A7%E5%88%B6%E5%99%A8/","summary":"\u003cp\u003e@\n这次iOS13的发布，其改动步子有点大了，尤其是是其多场景窗口（多任务）已经颠覆了老应用的设计基础了\u0026mdash;-数据的协同共享处理机制（本文不谈，哈哈）\n这里记录下一些界面层面的适配体会：\u003c/p\u003e\n\u003cp\u003e如果是 \u003ccode\u003eXcode 10\u003c/code\u003e 及以下创建的老项目，用 \u003ccode\u003eXcode 11\u003c/code\u003e 打开，老项目基本能正常运行。但是如果用 \u003ccode\u003eXcode 11\u003c/code\u003e 创建新项目，还按照老项目思路写代码就会有坑了。\u003c/p\u003e\n\u003cp\u003e用 \u003ccode\u003eXcode 11\u003c/code\u003e 创建一个 \u003ccode\u003eSingle View App\u003c/code\u003e 项目，会多生成一些文件和代码\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e多了SceneDelegate代理\u003c/li\u003e\n\u003cli\u003eInfo.plist里面多了Application Scene Manifest配置\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e多出来的这些文件和代码，影响最直观的是多场景窗口和导航控制器。\u003c/p\u003e\n\u003ch1 id=\"适配方案不支持多场景窗口\"\u003e适配方案——不支持多场景窗口\u003c/h1\u003e\n\u003cp\u003e这种适配方案最简单。\n将多出来的文件和代码删除就好了\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e删除SceneDelegate代理文件 (可选)\u003c/li\u003e\n\u003cli\u003e删除 Info.plist里面的Application Scene Manifest配置（一定要删除）\u003c/li\u003e\n\u003cli\u003e删除 AppDelegate代理的两个方法：\n\u003ccode\u003eapplication:configurationForConnectingSceneSession:options:\u003c/code\u003e \u003ccode\u003eapplication: didDiscardSceneSessions:\u003c/code\u003e\n这两个方法一定要删除，否则使用纯代码创建的 \u003ccode\u003eWindow\u003c/code\u003e 和导航控制器 \u003ccode\u003eUINavigationController\u003c/code\u003e 不会生效。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"适配方案支持多场景窗口\"\u003e适配方案——支持多场景窗口\u003c/h1\u003e\n\u003cp\u003e先说我遇到的一些现象。\n尽管我不会为每个应用自定义窗口和导航，但我我依然会使用纯代码创建 \u003ccode\u003eUIWindow\u003c/code\u003e 和 \u003ccode\u003eUINavigationController\u003c/code\u003e，具体如下\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-objectivec\" data-lang=\"objectivec\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//AppDelegate\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e- (\u003cspan style=\"color:#66d9ef\"\u003eBOOL\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003eapplication:\u003c/span\u003e(UIApplication \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)application \u003cspan style=\"color:#a6e22e\"\u003edidFinishLaunchingWithOptions:\u003c/span\u003e(NSDictionary \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e)launchOptions {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//在Xcode11创建的项目中，需要自行给AppDelegate添加属性window\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#75715e\"\u003e//自定义Window\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    self.window \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//自定义导航控制器\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    UINavigationController \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003erootNavgationController \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[UINavigationController alloc] initWithRootViewController:[ViewController new]];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//导航控制是rootViewController\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    self.window.rootViewController \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e rootNavgationController;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//现实Window\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    [self.window makeKeyAndVisible];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e YES;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003ccode\u003eXcode 11\u003c/code\u003e 创建的项目中，写入上述代码运行App，结果发现这部分代码虽然执行了，但是通过UIViewController的 \u003ccode\u003eself.navigationController\u003c/code\u003e 获取的导航竟然是 \u003ccode\u003enil\u003c/code\u003e。\n从现象反推过程，既然代码执行了，那么很大可能是 \u003ccode\u003eself.window\u003c/code\u003e 没有显示在屏幕上。\n查看iOS13下 \u003ccode\u003eUIWindow\u003c/code\u003e 的定义，有这么一条\u003c/p\u003e","title":"iOS13适配：UIWindow窗口和导航控制器"},{"content":"用create-react-app 脚手架创建的react项目，使用 npm run build 打包后，默认会产生 source-map 文件，通常项目上线后这种文件是不必要的。\n现在需要配置以关闭这种文件的产生。\n打开项目的 package.json 文件，找到下面类似的配置\n\u0026#34;scripts\u0026#34;: { \u0026#34;analyze\u0026#34;: \u0026#34;source-map-explorer \u0026#39;build/static/js/*.js\u0026#39;\u0026#34;, \u0026#34;start\u0026#34;: \u0026#34;react-scripts start\u0026#34;, \u0026#34;build\u0026#34;: \u0026#34;react-scripts build\u0026#34;, \u0026#34;test\u0026#34;: \u0026#34;react-scripts test\u0026#34;, \u0026#34;eject\u0026#34;: \u0026#34;react-scripts eject\u0026#34; }, 可以看到 build 命令执行的脚本是 react-scripts build,然后打开 node_modules/react-scripts/config/webpack.config.js 文件。\n一般情况下，定位到这，基本就知道了怎么关闭 source-map 文件产生\u0026ndash;搜索 shouldUseSourceMap，将其置为false就行了。\n如果仔细查看 shouldUseSourceMap 定义\nconst shouldUseSourceMap = process.env.GENERATE_SOURCEMAP !== \u0026#39;false\u0026#39;; 会发现shouldUseSourceMap和 process.env.GENERATE_SOURCEMAP 环境变量有关,那么在不修改 webpack.config.js 文件的情况，其实还可以修改环境变量。( 环境变量修改参考 https://139.155.43.7/2019/10/15/create-react-app-%e8%87%aa%e5%ae%9a%e4%b9%89%e7%8e%af%e5%a2%83%e5%8f%98%e9%87%8f/ )\n在项目目录下创建.env文件,添加内容\nGENERATE_SOURCEMAP=false 然后重新执行 npm run build，这时应不会产生 source-map 文件\n","permalink":"https://blog.z6z8.cn/2019/10/15/create-react-app-%EF%BC%9A%E4%B8%8D%E4%BA%A7%E7%94%9Fsource-map%E6%9D%A5%E7%BC%A9%E5%87%8F%E6%89%93%E5%8C%85%E6%96%87%E4%BB%B6%E4%BD%93%E7%A7%AF/","summary":"\u003cp\u003e用create-react-app 脚手架创建的react项目，使用 \u003ccode\u003enpm run build\u003c/code\u003e 打包后，默认会产生 \u003ccode\u003esource-map\u003c/code\u003e 文件，通常项目上线后这种文件是不必要的。\u003c/p\u003e\n\u003cp\u003e现在需要配置以关闭这种文件的产生。\u003c/p\u003e\n\u003cp\u003e打开项目的 \u003ccode\u003epackage.json\u003c/code\u003e 文件，找到下面类似的配置\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;scripts\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;analyze\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;source-map-explorer \u0026#39;build/static/js/*.js\u0026#39;\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;start\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;react-scripts start\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;build\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;react-scripts build\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;test\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;react-scripts test\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;eject\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;react-scripts eject\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  },\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e可以看到 \u003ccode\u003ebuild\u003c/code\u003e 命令执行的脚本是 \u003ccode\u003ereact-scripts build\u003c/code\u003e,然后打开\n\u003ccode\u003enode_modules/react-scripts/config/webpack.config.js\u003c/code\u003e 文件。\u003c/p\u003e\n\u003cp\u003e一般情况下，定位到这，基本就知道了怎么关闭 \u003ccode\u003esource-map\u003c/code\u003e 文件产生\u0026ndash;搜索 \u003ccode\u003eshouldUseSourceMap\u003c/code\u003e，将其置为false就行了。\u003c/p\u003e\n\u003cp\u003e如果仔细查看 \u003ccode\u003eshouldUseSourceMap\u003c/code\u003e 定义\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003econst\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eshouldUseSourceMap\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eenv\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eGENERATE_SOURCEMAP\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;false\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e会发现shouldUseSourceMap和 \u003ccode\u003eprocess.env.GENERATE_SOURCEMAP\u003c/code\u003e 环境变量有关,那么在不修改 \u003ccode\u003ewebpack.config.js\u003c/code\u003e 文件的情况，其实还可以修改环境变量。( 环境变量修改参考 \u003ca href=\"https://139.155.43.7/2019/10/15/create-react-app-%e8%87%aa%e5%ae%9a%e4%b9%89%e7%8e%af%e5%a2%83%e5%8f%98%e9%87%8f/\"\u003ehttps://139.155.43.7/2019/10/15/create-react-app-%e8%87%aa%e5%ae%9a%e4%b9%89%e7%8e%af%e5%a2%83%e5%8f%98%e9%87%8f/\u003c/a\u003e )\u003c/p\u003e\n\u003cp\u003e在项目目录下创建.env文件,添加内容\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eGENERATE_SOURCEMAP\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e然后重新执行 \u003ccode\u003enpm run build\u003c/code\u003e，这时应不会产生 \u003ccode\u003esource-map\u003c/code\u003e 文件\u003c/p\u003e","title":"create-react-app ：不产生source-map来缩减打包文件体积"},{"content":"create-react-app是一款非常好用的react项目脚手架，其创建的react项目除了可以访问默认的环境变量,还可以自定义环境变量，只要在项目目录下创建 .env 文件，然后直接写入环境变量就可以了。 具体如下：\n1、创建.env文件 在react项目目录下创建 .env 文件。 2、写入环境变量，例如\nABCD=1 3、访问环境变量 对于默认定义好的环境变量，使用 process.env.默认环境变量名 访问 对于自定义环境变量，需要添加 REACT_ 前缀,即使用 process.env.REACT_自定义环境变量名 访问\n例如\nrender() { if (process.env.REACT_ABCD !== 0 ) { \u0026#39;示例\u0026#39; } return ( \u0026lt;div\u0026gt; \u0026lt;span\u0026gt; 默认环境变量示例 {process.env.NODE_ENV \u0026lt;/span\u0026gt; \u0026lt;span\u0026gt; 自定义环境变量示例 {process.env.REACT_ABCD \u0026lt;/span\u0026gt; \u0026lt;/div\u0026gt; ); } 参考 ： https://create-react-app.dev/docs/adding-custom-environment-variables\n","permalink":"https://blog.z6z8.cn/2019/10/15/create-react-app-%E8%87%AA%E5%AE%9A%E4%B9%89%E7%8E%AF%E5%A2%83%E5%8F%98%E9%87%8F/","summary":"\u003cp\u003ecreate-react-app是一款非常好用的react项目脚手架，其创建的react项目除了可以访问默认的环境变量,还可以自定义环境变量，只要在项目目录下创建 \u003ccode\u003e.env\u003c/code\u003e 文件，然后直接写入环境变量就可以了。\n具体如下：\u003c/p\u003e\n\u003cp\u003e1、创建.env文件\n在react项目目录下创建 \u003ccode\u003e.env\u003c/code\u003e 文件。\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2019/10/react-env.png\"\u003e\u003c/p\u003e\n\u003cp\u003e2、写入环境变量，例如\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eABCD\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e3、访问环境变量\n对于默认定义好的环境变量，使用 \u003ccode\u003eprocess.env.默认环境变量名\u003c/code\u003e 访问\n对于自定义环境变量，需要添加 \u003ccode\u003eREACT_\u003c/code\u003e 前缀,即使用 \u003ccode\u003eprocess.env.REACT_自定义环境变量名\u003c/code\u003e 访问\u003c/p\u003e\n\u003cp\u003e例如\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003erender\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (\u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eenv\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eREACT_ABCD\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;示例\u0026#39;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ediv\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003espan\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e默认环境变量示例\u003c/span\u003e {\u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eenv\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eNODE_ENV\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/span\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003espan\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e自定义环境变量示例\u003c/span\u003e {\u003cspan style=\"color:#a6e22e\"\u003eprocess\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eenv\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eREACT_ABCD\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/span\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/div\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e参考 ： \u003ca href=\"https://create-react-app.dev/docs/adding-custom-environment-variables\"\u003ehttps://create-react-app.dev/docs/adding-custom-environment-variables\u003c/a\u003e\u003c/p\u003e","title":"create-react-app : 自定义环境变量"},{"content":"为了方便学习React路由，这里记录示例创建过程。\n1、创建react app\n#创建 npx create-react-app sample #进入目录 cd sample 2、修改public/index.html\n\u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;title\u0026gt;React 路由\u0026lt;/title\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body\u0026gt; \u0026lt;div id=\u0026#34;root\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; 3、修改 src/index.js\nimport React from \u0026#39;react\u0026#39;; import ReactDOM from \u0026#39;react-dom\u0026#39;; import App from \u0026#39;./App\u0026#39;; ReactDOM.render(\u0026lt;App /\u0026gt;, document.getElementById(\u0026#39;root\u0026#39;)); 4、修改src/App.js\nimport React from \u0026#39;react\u0026#39;; import { BrowserRouter as Router,Route,Link} from \u0026#39;react-router-dom\u0026#39;; function Home () { return ( \u0026lt;div\u0026gt; \u0026lt;span\u0026gt;主页\u0026lt;/span\u0026gt; \u0026lt;Link to=\u0026#34;/page\u0026#34;\u0026gt;其他页面\u0026lt;/Link\u0026gt; \u0026lt;/div\u0026gt; ); } function Page () { return ( \u0026lt;div\u0026gt; \u0026lt;span\u0026gt;其他页面\u0026lt;/span\u0026gt; \u0026lt;Link to=\u0026#34;/\u0026#34;\u0026gt;主页\u0026lt;/Link\u0026gt; \u0026lt;/div\u0026gt; ); } function App() { return ( \u0026lt;Router\u0026gt; \u0026lt;div\u0026gt; \u0026lt;Route path=\u0026#34;/\u0026#34; exact={true} component={Home} /\u0026gt; \u0026lt;Route path=\u0026#34;/page\u0026#34; exact={true} component={Page} /\u0026gt; \u0026lt;/div\u0026gt; \u0026lt;/Router\u0026gt; ); } export default App; 5、安装依赖 react-router-dom\nyarn add react-router-dom 6、执行看效果\nyarn start ","permalink":"https://blog.z6z8.cn/2019/10/15/react-%E4%B8%80%E4%B8%AA%E7%AE%80%E7%9F%AD%E7%9A%84%E8%B7%AF%E7%94%B1%E9%85%8D%E7%BD%AE%E7%A4%BA%E4%BE%8B/","summary":"\u003cp\u003e为了方便学习React路由，这里记录示例创建过程。\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2019/10/react%E8%B7%AF%E7%94%B1%E6%BC%94%E7%A4%BA.gif\"\u003e\u003c/p\u003e\n\u003cp\u003e1、创建react app\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#创建\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003enpx create-react-app sample\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#进入目录\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd sample\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e2、修改public/index.html\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003ehtml\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;\u003cspan style=\"color:#f92672\"\u003ehead\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003etitle\u003c/span\u003e\u0026gt;React 路由\u0026lt;/\u003cspan style=\"color:#f92672\"\u003etitle\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ehead\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;\u003cspan style=\"color:#f92672\"\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;root\u0026#34;\u003c/span\u003e\u0026gt;\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ehtml\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e3、修改 src/index.js\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eReact\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;react\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eReactDOM\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;react-dom\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eApp\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;./App\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#a6e22e\"\u003eReactDOM\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003erender\u003c/span\u003e(\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eApp\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e, document.\u003cspan style=\"color:#a6e22e\"\u003egetElementById\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;root\u0026#39;\u003c/span\u003e));\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e4、修改src/App.js\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eReact\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;react\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eimport\u003c/span\u003e { \u003cspan style=\"color:#a6e22e\"\u003eBrowserRouter\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eas\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eRouter\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003eRoute\u003c/span\u003e,\u003cspan style=\"color:#a6e22e\"\u003eLink\u003c/span\u003e} \u003cspan style=\"color:#a6e22e\"\u003efrom\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;react-router-dom\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eHome\u003c/span\u003e () {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ediv\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003espan\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003e主页\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/span\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eLink\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eto\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/page\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003e其他页面\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/Link\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/div\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePage\u003c/span\u003e () {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ediv\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003espan\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003e其他页面\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/span\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eLink\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eto\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003e主页\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/Link\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/div\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eApp\u003c/span\u003e() {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e (\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eRouter\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ediv\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eRoute\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epath\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eexact\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e} \u003cspan style=\"color:#a6e22e\"\u003ecomponent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003eHome\u003c/span\u003e} \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eRoute\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003epath\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/page\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eexact\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e} \u003cspan style=\"color:#a6e22e\"\u003ecomponent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e{\u003cspan style=\"color:#a6e22e\"\u003ePage\u003c/span\u003e} \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/div\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e/Router\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eexport\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003edefault\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eApp\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e5、安装依赖 react-router-dom\u003c/p\u003e","title":"React : 一个简短的路由配置示例"},{"content":"由于在升级Wordpress时，Wordpress会在数据库wp_options表中增加core_updater.lock记录。如中途打断Wordpress升级，这个记录会留在数据库中。当下次升级时，Wordpress检测到此记录的存在就会返回”另一更新正在进行”。\n参考https://www.wpdaxue.com/wordpress-update-problem.html\n解决： 通过终端登录WordPress数据库\nmysql -u 数据库用户名字 -p mysql\u0026gt; use wordpress的数据库名字; 从下面结果中，找到 xxxx_options表\n# 查询数据库中所有表名 mysql\u0026gt; select table_name from information_schema.tables where table_schema=\u0026#39;wordpress的数据库名字\u0026#39;; 查询\nmysql\u0026gt; select * from xxx_options where option_name=\u0026#39;core_updater.lock\u0026#39;; 删除\nmysql\u0026gt; delete from xxx_options where option_name=\u0026#39;core_updater.lock\u0026#39;; ","permalink":"https://blog.z6z8.cn/2019/10/15/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9A%E5%8D%87%E7%BA%A7-wordpress-%E6%97%B6%E6%8F%90%E7%A4%BA%E5%8F%A6%E4%B8%80%E6%9B%B4%E6%96%B0%E6%AD%A3%E5%9C%A8%E8%BF%9B%E8%A1%8C/","summary":"\u003cp\u003e由于在升级Wordpress时，Wordpress会在数据库wp_options表中增加core_updater.lock记录。如中途打断Wordpress升级，这个记录会留在数据库中。当下次升级时，Wordpress检测到此记录的存在就会返回”另一更新正在进行”。\u003c/p\u003e\n\u003cp\u003e参考https://www.wpdaxue.com/wordpress-update-problem.html\u003c/p\u003e\n\u003cp\u003e解决：\n通过终端登录WordPress数据库\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emysql -u 数据库用户名字 -p\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emysql\u0026gt;  use wordpress的数据库名字;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e从下面结果中，找到 xxxx_options表\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 查询数据库中所有表名\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emysql\u0026gt;  select table_name from information_schema.tables where table_schema=\u0026#39;wordpress的数据库名字\u0026#39;;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e查询\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emysql\u0026gt; select * from xxx_options where option_name=\u0026#39;core_updater.lock\u0026#39;;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e删除\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003emysql\u0026gt; delete from xxx_options where option_name=\u0026#39;core_updater.lock\u0026#39;;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"学习笔记：升级 WordPress 时提示”另一更新正在进行”"},{"content":"超链接的四种状态 一个超链接示例\n\u0026lt;a href=\u0026#34;https://www.z6z8.cn\u0026#34;\u0026gt;z6z8\u0026lt;/a\u0026gt; 有四种状态：\na:link - 普通的、未被访问的链接 a:visited - 用户已访问的链接 a:hover - 鼠标指针位于链接的上方 a:active - 链接被点击的时刻 CSS 改变超链接颜色 在未指定适用范围时，下面css影响全局\na:link { /*前景色*/ color:blue; /*背景色*/ background-color: orange; } a:visited { color:red; } a:hover{ ... } a:active{ ... } CSS 改变部分超链接颜色 需要将新颜色设置指定给具体的CSS块，例如\n.testcss { width:100%; height:20%; } .testcss a:visited { color:red; } ","permalink":"https://blog.z6z8.cn/2019/10/11/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9Acss%E6%8C%87%E5%AE%9A%E8%B6%85%E9%93%BE%E6%8E%A5%E7%9A%84%E6%96%87%E5%AD%97%E9%A2%9C%E8%89%B2/","summary":"\u003ch1 id=\"超链接的四种状态\"\u003e超链接的四种状态\u003c/h1\u003e\n\u003cp\u003e一个超链接示例\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003ea\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ehref\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;https://www.z6z8.cn\u0026#34;\u003c/span\u003e\u0026gt;z6z8\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ea\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e有四种状态：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003ea:link - 普通的、未被访问的链接\u003c/li\u003e\n\u003cli\u003ea:visited - 用户已访问的链接\u003c/li\u003e\n\u003cli\u003ea:hover - 鼠标指针位于链接的上方\u003c/li\u003e\n\u003cli\u003ea:active - 链接被点击的时刻\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"css-改变超链接颜色\"\u003eCSS 改变超链接颜色\u003c/h1\u003e\n\u003cp\u003e在未指定适用范围时，下面css影响全局\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ea\u003c/span\u003e:\u003cspan style=\"color:#a6e22e\"\u003elink\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e/*前景色*/\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ecolor\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003eblue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e/*背景色*/\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ebackground-color\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eorange\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ea\u003c/span\u003e:\u003cspan style=\"color:#a6e22e\"\u003evisited\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ecolor\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003ered\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ea\u003c/span\u003e:\u003cspan style=\"color:#a6e22e\"\u003ehover\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003ea\u003c/span\u003e:\u003cspan style=\"color:#a6e22e\"\u003eactive\u003c/span\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e...\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"css-改变部分超链接颜色\"\u003eCSS 改变部分超链接颜色\u003c/h1\u003e\n\u003cp\u003e需要将新颜色设置指定给具体的CSS块，例如\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-css\" data-lang=\"css\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e.\u003cspan style=\"color:#a6e22e\"\u003etestcss\u003c/span\u003e  {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ewidth\u003c/span\u003e:\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e%\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eheight\u003c/span\u003e:\u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e%\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e.\u003cspan style=\"color:#a6e22e\"\u003etestcss\u003c/span\u003e  \u003cspan style=\"color:#f92672\"\u003ea\u003c/span\u003e:\u003cspan style=\"color:#a6e22e\"\u003evisited\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#66d9ef\"\u003ecolor\u003c/span\u003e:\u003cspan style=\"color:#66d9ef\"\u003ered\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"学习笔记：CSS指定超链接的文字颜色"},{"content":"效果图 \u0026lt;html\u0026gt; \u0026lt;head\u0026gt; \u0026lt;style type=\u0026#34;text/css\u0026#34;\u0026gt; /* 整体Body */ .flex-body { width: 100%; height: 100%; margin: 0px; } /* 头 高70px*/ .flex-header { background-color: aqua; height: 70px; width: 100%; } /* 中间左侧，绝对定位，宽度50%，高度由top和bottom决定， top和bottom分别是 flex-header ，flex-footer的高度*/ .flex-left-main { position: absolute; background-color: red; width: 50%; top: 70px; bottom: 60px; } /* 中间左侧，绝对定位，宽度50%，高度由top和bottom决定， margin-left: 50% top和bottom分别是 flex-header ，flex-footer的高度*/ .flex-right-main { position: absolute; background-color: blue; width: 50%; top: 70px; bottom: 60px; margin-left: 50%; } /* 脚 高60px */ .flex-footer { position: absolute; bottom: 0px; width:100%; height: 60px; background-color: bisque; } \u0026lt;/style\u0026gt; \u0026lt;/head\u0026gt; \u0026lt;body class=\u0026#34;flex-body\u0026#34;\u0026gt; \u0026lt;div id=\u0026#34;flex-header\u0026#34; class=\u0026#34;flex-header\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; \u0026lt;div id=\u0026#34;flex-left-main\u0026#34; class=\u0026#34;flex-left-main\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; \u0026lt;div id=\u0026#34;flex-right-main\u0026#34; class=\u0026#34;flex-right-main\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; \u0026lt;div id=\u0026#34;flex-footer\u0026#34; class=\u0026#34;flex-footer\u0026#34;\u0026gt;\u0026lt;/div\u0026gt; \u0026lt;/body\u0026gt; \u0026lt;/html\u0026gt; ","permalink":"https://blog.z6z8.cn/2019/10/10/css-%E5%A4%B4%E8%84%9A%E4%B8%AD%E9%97%B4%E4%B8%A4%E5%88%97%E5%B8%83%E5%B1%80/","summary":"\u003cp\u003e效果图\n\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2019/10/css%E5%A4%B4%E8%84%9A%E4%B8%AD%E9%97%B4%E4%B8%A4%E5%88%97.png\"\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-html\" data-lang=\"html\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;\u003cspan style=\"color:#f92672\"\u003ehtml\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;\u003cspan style=\"color:#f92672\"\u003ehead\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u0026lt;\u003cspan style=\"color:#f92672\"\u003estyle\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etype\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;text/css\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u003cspan style=\"color:#75715e\"\u003e/* 整体Body */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003eflex-body\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ewidth\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e%\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eheight\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e%\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003emargin\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e/* 头 高70px*/\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003eflex-header\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ebackground-color\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eaqua\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eheight\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e70\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ewidth\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e%\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e/* 中间左侧，绝对定位，宽度50%，高度由top和bottom决定，\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            top和bottom分别是 flex-header ，flex-footer的高度*/\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003eflex-left-main\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eposition\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eabsolute\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ebackground-color\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003ered\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ewidth\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e50\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e%\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003etop\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e70\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ebottom\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e60\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e/* 中间左侧，绝对定位，宽度50%，高度由top和bottom决定，\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            margin-left: 50%\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e            top和bottom分别是 flex-header ，flex-footer的高度*/\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003eflex-right-main\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eposition\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eabsolute\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ebackground-color\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eblue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ewidth\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e50\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e%\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003etop\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e70\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ebottom\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e60\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003emargin-left\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e50\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e%\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e/* 脚 高60px */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            .\u003cspan style=\"color:#a6e22e\"\u003eflex-footer\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eposition\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003eabsolute\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ebottom\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ewidth\u003c/span\u003e:\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e%\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eheight\u003c/span\u003e: \u003cspan style=\"color:#ae81ff\"\u003e60\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003epx\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ebackground-color\u003c/span\u003e: \u003cspan style=\"color:#66d9ef\"\u003ebisque\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e      \u0026lt;/\u003cspan style=\"color:#f92672\"\u003estyle\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ehead\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;\u003cspan style=\"color:#f92672\"\u003ebody\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;flex-body\u0026#34;\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;flex-header\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;flex-header\u0026#34;\u003c/span\u003e\u0026gt;\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;flex-left-main\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;flex-left-main\u0026#34;\u003c/span\u003e\u0026gt;\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;flex-right-main\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;flex-right-main\u0026#34;\u003c/span\u003e\u0026gt;\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u0026lt;\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eid\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;flex-footer\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eclass\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;flex-footer\u0026#34;\u003c/span\u003e\u0026gt;\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ediv\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u0026lt;/\u003cspan style=\"color:#f92672\"\u003ebody\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;/\u003cspan style=\"color:#f92672\"\u003ehtml\u003c/span\u003e\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"CSS 头脚+中间两列布局"},{"content":"全文请看 https://www.jb51.net/article/40413.htm\n//获取坐标位置 function getpos(obj) { var top=obj.offsetTop; var left=obj.offsetLeft; var height=obj.offsetHeight; var width=obj.offsetWidth; while(obj=obj.offsetParent) { top+=obj.offsetTop; left+=obj.offsetLeft; } } obj.offsetTop 指 obj 距离上方或上层控件的位置，整型，单位像素。 obj.offsetLeft 指 obj 距离左方或上层控件的位置，整型，单位像素。 obj.offsetWidth 指 obj 控件自身的宽度，整型，单位像素。 obj.offsetHeight 指 obj 控件自身的高度，整型，单位像素。 ","permalink":"https://blog.z6z8.cn/2019/10/10/%E8%BD%AC%E8%BD%BDjs%E8%8E%B7%E5%8F%96%E6%8E%A7%E4%BB%B6%E5%9D%90%E6%A0%87%E4%BD%8D%E7%BD%AE/","summary":"\u003cp\u003e全文请看 \u003ca href=\"https://www.jb51.net/article/40413.htm\"\u003ehttps://www.jb51.net/article/40413.htm\u003c/a\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-javascript\" data-lang=\"javascript\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//获取坐标位置\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003egetpos\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eobj\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etop\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eobj\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eoffsetTop\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eobj\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eoffsetLeft\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eheight\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eobj\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eoffsetHeight\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewidth\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eobj\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eoffsetWidth\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003eobj\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eobj\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eoffsetParent\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003etop\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eobj\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eoffsetTop\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eobj\u003c/span\u003e.\u003cspan style=\"color:#a6e22e\"\u003eoffsetLeft\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cul\u003e\n\u003cli\u003eobj.offsetTop 指 obj 距离上方或上层控件的位置，整型，单位像素。\u003c/li\u003e\n\u003cli\u003eobj.offsetLeft 指 obj 距离左方或上层控件的位置，整型，单位像素。\u003c/li\u003e\n\u003cli\u003eobj.offsetWidth 指 obj 控件自身的宽度，整型，单位像素。\u003c/li\u003e\n\u003cli\u003eobj.offsetHeight 指 obj 控件自身的高度，整型，单位像素。\u003c/li\u003e\n\u003c/ul\u003e","title":"转载:js获取控件坐标位置"},{"content":"闲暇无事看了看系统日志，发现ssh被暴力了，类似下面的日志几乎一秒一条\nOct 3 21:30:38 localhost sshd[11266]: Failed password for invalid user minecraftserver from 84.93.153.9 port 54913 ssh2 索性禁用ssh密码登陆 打开文件 /etc/ssh/sshd_config，将 PasswordAuthentication 值修改为no\n#开启公钥算法鉴权 PubkeyAuthentication yes #禁用密码鉴权 PasswordAuthentication no #鉴权挑战响应 ChallengeResponseAuthentication no 保存文件后，重启sshd服务\nsudo systemctl restart sshd.service 清净多了\n","permalink":"https://blog.z6z8.cn/2019/10/03/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9Aubuntu-%E7%A6%81%E7%94%A8ssh%E5%AF%86%E7%A0%81%E7%99%BB%E9%99%86/","summary":"\u003cp\u003e闲暇无事看了看系统日志，发现ssh被暴力了，类似下面的日志几乎一秒一条\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eOct  \u003cspan style=\"color:#ae81ff\"\u003e3\u003c/span\u003e 21:30:38 localhost sshd\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e11266\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e: Failed password \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e invalid user minecraftserver from 84.93.153.9 port \u003cspan style=\"color:#ae81ff\"\u003e54913\u003c/span\u003e ssh2\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e索性禁用ssh密码登陆\n打开文件 \u003ccode\u003e/etc/ssh/sshd_config\u003c/code\u003e，将 \u003ccode\u003ePasswordAuthentication\u003c/code\u003e 值修改为no\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   #开启公钥算法鉴权\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   PubkeyAuthentication yes\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  #禁用密码鉴权\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   PasswordAuthentication no\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   #鉴权挑战响应\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   ChallengeResponseAuthentication no\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e保存文件后，重启sshd服务\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl restart sshd.service\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e清净多了\u003c/p\u003e","title":"学习笔记：ubuntu 禁用ssh密码登陆"},{"content":"默认长度是40，取值范围是20到40，显然是不够用的。 需要我们手动修改代码，具体如下:\nwordpress安装目录/wp-content/themes/gucherry-blog/inc/customizer/functions/customizer-fields.php\n$wp_customize-\u0026gt;add_control( \u0026#39;gucherry_blog_excerpt_length\u0026#39;, array( \u0026#39;label\u0026#39; =\u0026gt; esc_html__( \u0026#39;Excerpt Length\u0026#39;, \u0026#39;gucherry-blog\u0026#39; ), \u0026#39;description\u0026#39; =\u0026gt; esc_html__( \u0026#39;Maximum excerpt length 40 and minimum excerpt length 20 can be set.\u0026#39;, \u0026#39;gucherry-blog\u0026#39; ), \u0026#39;section\u0026#39; =\u0026gt; \u0026#39;gucherry_blog_excerpt_length_section\u0026#39;, \u0026#39;type\u0026#39; =\u0026gt; \u0026#39;number\u0026#39;, \u0026#39;input_attrs\u0026#39; =\u0026gt; array( \u0026#39;min\u0026#39; =\u0026gt; 20, \u0026#39;max\u0026#39; =\u0026gt; 40, ), ) ); 手动修改其中的 max 值，就可增大取值范围了\n","permalink":"https://blog.z6z8.cn/2019/10/01/wordpress-gucherry-blog-theme%EF%BC%8C%E4%BF%AE%E6%94%B9%E6%91%98%E8%A6%81%E9%95%BF%E5%BA%A6/","summary":"\u003cp\u003e默认长度是40，取值范围是20到40，显然是不够用的。\n需要我们手动修改代码，具体如下:\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003ewordpress安装目录/wp-content/themes/gucherry-blog/inc/customizer/functions/customizer-fields.php\u003c/code\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$wp_customize\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eadd_control\u003c/span\u003e( \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;gucherry_blog_excerpt_length\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#66d9ef\"\u003earray\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;label\u0026#39;\u003c/span\u003e                    \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eesc_html__\u003c/span\u003e( \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Excerpt Length\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;gucherry-blog\u0026#39;\u003c/span\u003e ),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;description\u0026#39;\u003c/span\u003e              \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eesc_html__\u003c/span\u003e( \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;Maximum excerpt length 40 and minimum excerpt length 20 can be set.\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;gucherry-blog\u0026#39;\u003c/span\u003e ),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;section\u0026#39;\u003c/span\u003e                  \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;gucherry_blog_excerpt_length_section\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;type\u0026#39;\u003c/span\u003e                     \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;number\u0026#39;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;input_attrs\u0026#39;\u003c/span\u003e              \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003earray\u003c/span\u003e(\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;min\u0026#39;\u003c/span\u003e  \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;max\u0026#39;\u003c/span\u003e  \u003cspan style=\"color:#f92672\"\u003e=\u0026gt;\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e40\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ),\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e) );\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e手动修改其中的 \u003ccode\u003emax\u003c/code\u003e 值，就可增大取值范围了\u003c/p\u003e","title":"WordPress GuCherry Blog Theme，修改摘要长度"},{"content":"GuCherry Blog Theme自身是支持在不修改代码的情况下自定义网页页脚文案的，只不过灵活度不够。 该主题footer部分代码在 wordpress安装目录/wp-content/themes/gucherry-blog/footer.php 文件中，位置如下:\n//该主题footer部分代码在\u0026lt;code\u0026gt;wordpress安装目录/wp-content/themes/gucherry-blog/footer.php\u0026lt;/code\u0026gt;文件中，位置如下: \u0026lt;?php $footer_copyright_text = get_theme_mod( \u0026#39;gucherry_blog_site_footer_copyright_text\u0026#39; ); if( !empty( $footer_copyright_text ) ) { /* translators: 1: Copyright Text 2: Theme name, 3: Theme author. */ printf( esc_html__( \u0026#39;%1$s %2$s by %3$s\u0026#39;,\u0026#39;gucherry-blog\u0026#39; ), $footer_copyright_text, \u0026#39;GuCherry Blog\u0026#39;, \u0026#39;\u0026lt;a href=\u0026#34;\u0026#39;. esc_url( \u0026#39;https://everestthemes.com\u0026#39; ) . \u0026#39;\u0026#34;\u0026gt;Everestthemes\u0026lt;/a\u0026gt;\u0026#39; ); } else { /* translators: 1: Theme name, 2: Theme author. */ printf( esc_html__( \u0026#39;%1$s by %2$s\u0026#39;, \u0026#39;gucherry-blog\u0026#39; ), \u0026#39;GuCherry Blog\u0026#39;, \u0026#39;\u0026lt;a href=\u0026#34;\u0026#39;. esc_url( \u0026#39;https://everestthemes.com\u0026#39; ) . \u0026#39;\u0026#34;\u0026gt;Everestthemes\u0026lt;/a\u0026gt;\u0026#39; ); } ?\u0026gt; 重点在 $footer_copyright_text = get_theme_mod( 'gucherry_blog_site_footer_copyright_text' );，其返回值是我们需要修改的文案。\n全目录搜索寻找关键词 gucherry_blog_site_footer_copyright_text，按图索骥就好。 应能找到 wordpress安装目录/wp-content/themes/gucherry-blog/inc/customizer/functions/customizer-fields.php 中\n//Option : Footer Copyright Text $wp_customize-\u0026gt;add_setting( \u0026#39;gucherry_blog_site_footer_copyright_text\u0026#39;, array( \u0026#39;sanitize_callback\u0026#39; =\u0026gt; \u0026#39;gucherry_blog_sanitize_copyright_credit\u0026#39;, \u0026#39;default\u0026#39; =\u0026gt; \u0026#39;\u0026#39;, ) ); $wp_customize-\u0026gt;add_control( \u0026#39;gucherry_blog_site_footer_copyright_text\u0026#39;, array( \u0026#39;label\u0026#39; =\u0026gt; esc_html__( \u0026#39;Copyright Text\u0026#39;, \u0026#39;gucherry-blog\u0026#39; ), \u0026#39;description\u0026#39; =\u0026gt; esc_html__( \u0026#39;You can use \u0026lt;a\u0026gt; \u0026amp; \u0026lt;span\u0026gt; tags with the copyright and credit text.\u0026#39;, \u0026#39;gucherry-blog\u0026#39; ), \u0026#39;section\u0026#39; =\u0026gt; \u0026#39;gucherry_blog_site_footer_section\u0026#39;, \u0026#39;type\u0026#39; =\u0026gt; \u0026#39;text\u0026#39;, ) ); 从代码中，可以看到作者只允许和两个标签。\n继续搜索 gucherry_blog_sanitize_copyright_credit，\n应能找到 wordpress安装目录/wp-content/themes/gucherry-blog/inc/customizer/functions/sanitize-callback.php 中\nif ( !function_exists(\u0026#39;gucherry_blog_sanitize_copyright_credit\u0026#39;) ) : function gucherry_blog_sanitize_copyright_credit( $input ) { $allowed_tags = array( \u0026#39;a\u0026#39; =\u0026gt; array( \u0026#39;href\u0026#39; =\u0026gt; array(), \u0026#39;title\u0026#39; =\u0026gt; array(), \u0026#39;_target\u0026#39; =\u0026gt; array(), ), \u0026#39;span\u0026#39; =\u0026gt; array(), ); return wp_kses( $input, $allowed_tags ); } endif; 再次看到作者确实只允许和两个标签. 好了，限制代码找到了，那么修改就简单了。\n","permalink":"https://blog.z6z8.cn/2019/09/30/wordpress-gucherry-blog-theme%EF%BC%8C%E8%A7%A3%E9%99%A4-footer%E6%96%87%E6%A1%88%E7%9A%84html%E6%A0%87%E7%AD%BE%E9%99%90%E5%88%B6/","summary":"\u003cp\u003eGuCherry Blog Theme自身是支持在不修改代码的情况下自定义网页页脚文案的，只不过灵活度不够。\n该主题footer部分代码在 \u003ccode\u003ewordpress安装目录/wp-content/themes/gucherry-blog/footer.php\u003c/code\u003e 文件中，位置如下:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//该主题footer部分代码在\u0026lt;code\u0026gt;wordpress安装目录/wp-content/themes/gucherry-blog/footer.php\u0026lt;/code\u0026gt;文件中，位置如下:\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;?\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ephp\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$footer_copyright_text \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eget_theme_mod\u003c/span\u003e( \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;gucherry_blog_site_footer_copyright_text\u0026#39;\u003c/span\u003e );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e( \u003cspan style=\"color:#f92672\"\u003e!\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eempty\u003c/span\u003e( $footer_copyright_text ) ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#75715e\"\u003e/* translators: 1: Copyright Text 2: Theme name, 3: Theme author. */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e( \u003cspan style=\"color:#a6e22e\"\u003eesc_html__\u003c/span\u003e( \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;%1$s %2$s by %3$s\u0026#39;\u003c/span\u003e,\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;gucherry-blog\u0026#39;\u003c/span\u003e ), $footer_copyright_text, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;GuCherry Blog\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026lt;a href=\u0026#34;\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eesc_url\u003c/span\u003e( \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;https://everestthemes.com\u0026#39;\u003c/span\u003e ) \u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#34;\u0026gt;Everestthemes\u0026lt;/a\u0026gt;\u0026#39;\u003c/span\u003e );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e } \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e/* translators: 1: Theme name, 2: Theme author. */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   \u003cspan style=\"color:#a6e22e\"\u003eprintf\u003c/span\u003e( \u003cspan style=\"color:#a6e22e\"\u003eesc_html__\u003c/span\u003e( \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;%1$s by %2$s\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;gucherry-blog\u0026#39;\u003c/span\u003e ), \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;GuCherry Blog\u0026#39;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026lt;a href=\u0026#34;\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eesc_url\u003c/span\u003e( \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;https://everestthemes.com\u0026#39;\u003c/span\u003e ) \u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026#34;\u0026gt;Everestthemes\u0026lt;/a\u0026gt;\u0026#39;\u003c/span\u003e );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#75715e\"\u003e?\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e重点在 \u003ccode\u003e$footer_copyright_text = get_theme_mod( 'gucherry_blog_site_footer_copyright_text' );\u003c/code\u003e，其返回值是我们需要修改的文案。\u003c/p\u003e\n\u003cp\u003e全目录搜索寻找关键词 \u003ccode\u003egucherry_blog_site_footer_copyright_text\u003c/code\u003e，按图索骥就好。\n应能找到\n\u003ccode\u003ewordpress安装目录/wp-content/themes/gucherry-blog/inc/customizer/functions/customizer-fields.php\u003c/code\u003e 中\u003c/p\u003e","title":"WordPress GuCherry Blog Theme，解除 footer文案的html标签限制"},{"content":"扫描结果\n漏洞名称 Nginx server_tokens基线 危险等级 中危 漏洞类型 安全基线 漏洞描述 server_tokens指令负责在错误页面和ServerHTTP响应头字段中显示NGINX版本号和操作系统版本。 不应显示此信息。 修复方案 在nginx配置文件中配置 server_tokens off; ","permalink":"https://blog.z6z8.cn/2019/09/27/%E8%85%BE%E8%AE%AF%E4%BA%91%E4%B8%BB%E6%9C%BA%E5%AE%89%E5%85%A8%E6%89%AB%E6%8F%8F%EF%BC%9A%E5%85%B3%E9%97%ADnginx-server_tokens/","summary":"\u003cp\u003e扫描结果\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e漏洞名称    Nginx server_tokens基线\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e危险等级    中危\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e漏洞类型    安全基线\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e漏洞描述    server_tokens指令负责在错误页面和ServerHTTP响应头字段中显示NGINX版本号和操作系统版本。 不应显示此信息。\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e修复方案    在nginx配置文件中配置 server_tokens off;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"腾讯云主机安全扫描：关闭Nginx server_tokens"},{"content":"扫描结果 漏洞名称 启用authpriv和cron系统日志审计 危险等级 中危 漏洞类型 安全基线 漏洞描述 启用authpriv和cron系统日志审计。 authpriv －包括特权信息如用户名在内的认证活动 cron －与 cron 和 at 有关的计划任务信息 参考链接 修复方案 1. 修改/etc/rsyslog.conf，添加或取消注释如下配置（中间的分隔符是tab）： authpriv.* /var/log/secure cron.* /var/log/cron 1. 重启rsyslog服务 名词解释 authpriv 参考 http://www.kbase101.com/question/32969.html 可知 authpriv - 非系统授权消息 auth - 认证和授权相关命令 早期的LOG_AUTHPRIV用于隐藏受保护的敏感日志消息文件，例如/var/log/auth.log。而Linux上的LOG_AUTH通常没有配置限制访问，而LOG_AUTHPRIV是。\ncron linux 上的定时任务服务\n","permalink":"https://blog.z6z8.cn/2019/09/27/%E8%85%BE%E8%AE%AF%E4%BA%91%E4%B8%BB%E6%9C%BA%E5%AE%89%E5%85%A8%E6%89%AB%E6%8F%8F%EF%BC%9A%E5%90%AF%E7%94%A8authpriv%E5%92%8Ccron%E7%B3%BB%E7%BB%9F%E6%97%A5%E5%BF%97%E5%AE%A1%E8%AE%A1/","summary":"\u003ch1 id=\"扫描结果\"\u003e扫描结果\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-gdscript3\" data-lang=\"gdscript3\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e漏洞名称\u003c/span\u003e    \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e启用\u003c/span\u003eauthpriv和cron系统日志审计\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e危险等级\u003c/span\u003e    \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e中危\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e漏洞类型\u003c/span\u003e    \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e安全基线\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e漏洞描述\u003c/span\u003e    \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e启用\u003c/span\u003eauthpriv和cron系统日志审计\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e。\u003c/span\u003e authpriv \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e－包括特权信息如用户名在内的认证活动\u003c/span\u003e cron \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e－与\u003c/span\u003e cron \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e和\u003c/span\u003e at \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e有关的计划任务信息\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e参考链接\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e修复方案\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#ae81ff\"\u003e1.\u003c/span\u003e \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e修改\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003eetc\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003ersyslog\u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003econf\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e，添加或取消注释如下配置（中间的分隔符是\u003c/span\u003etab\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e）：\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eauthpriv\u003cspan style=\"color:#f92672\"\u003e.*\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003elog\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003esecure\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecron\u003cspan style=\"color:#f92672\"\u003e.*\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003evar\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003elog\u003cspan style=\"color:#f92672\"\u003e/\u003c/span\u003ecron\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#ae81ff\"\u003e1.\u003c/span\u003e \u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e重启\u003c/span\u003ersyslog服务\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"名词解释\"\u003e名词解释\u003c/h1\u003e\n\u003ch2 id=\"authpriv\"\u003eauthpriv\u003c/h2\u003e\n\u003cp\u003e参考 \u003ca href=\"http://www.kbase101.com/question/32969.html\"\u003ehttp://www.kbase101.com/question/32969.html\u003c/a\u003e\n可知\n\u003ccode\u003eauthpriv\u003c/code\u003e - 非系统授权消息\n\u003ccode\u003eauth\u003c/code\u003e - 认证和授权相关命令\n早期的LOG_AUTHPRIV用于隐藏受保护的敏感日志消息文件，例如/var/log/auth.log。而Linux上的LOG_AUTH通常没有配置限制访问，而LOG_AUTHPRIV是。\u003c/p\u003e\n\u003ch2 id=\"cron\"\u003ecron\u003c/h2\u003e\n\u003cp\u003elinux 上的定时任务服务\u003c/p\u003e","title":"腾讯云主机安全扫描：启用authpriv和cron系统日志审计"},{"content":"集成 Yoga是Facebook开源的基于CSS FlexBox布局框架，核心使用C++实现的，在iOS上并不需要直接集成C++代码，只需通过CocoaPod引入 YogaKit（间接集成C++代码）\n# Podfile platform :ios, \u0026#39;8.0\u0026#39; use_frameworks! target \u0026#34;TestProject\u0026#34; do pod \u0026#39;YogaKit\u0026#39; end 使用 集成后，YogaKit提供了UIView的方法扩展\n// UIView+Yoga.h @property (nonatomic, readonly, strong) YGLayout *yoga; yoga 类型为 YGLayout，描述了UIView如何布局。\n简单示例\n//代码源自 https://www.jianshu.com/p/95bf92143141 -(void)test { [self.view configureLayoutWithBlock:^(YGLayout * layout) { layout.isEnabled = YES; layout.width = YGPointValue(self.view.bounds.size.width); layout.height = YGPointValue(self.view.bounds.size.height); layout.alignItems = YGAlignCenter; }]; UIView *contentView = [[UIView alloc]init]; contentView.backgroundColor = [UIColor lightGrayColor]; [contentView configureLayoutWithBlock:^(YGLayout * layout) { layout.isEnabled = true; // 4 layout.flexDirection = YGFlexDirectionRow; layout.width = YGPointValue(320); layout.height = YGPointValue(80); layout.marginTop = YGPointValue(100); layout.padding = YGPointValue(10);//设置了全部子项目的填充值 }]; UIView *child1 = [[UIView alloc]init]; child1.backgroundColor = [UIColor redColor]; [child1 configureLayoutWithBlock:^(YGLayout * layout) { layout.isEnabled = YES; layout.width = YGPointValue(80); layout.marginRight = YGPointValue(10); }]; UIView *child2 = [[UIView alloc]init]; child2.backgroundColor = [UIColor blueColor]; [child2 configureLayoutWithBlock:^(YGLayout * layout) { layout.isEnabled = YES; layout.width = YGPointValue(80); layout.flexGrow = 1; layout.height = YGPointValue(20); layout.alignSelf = YGAlignCenter; }]; [contentView addSubview:child1]; [contentView addSubview:child2]; [self.view addSubview:contentView]; [self.view.yoga applyLayoutPreservingOrigin:YES]; } 注意:\n无特殊情况，方法 applyLayoutPreservingOrigin 最好由根节点执行\n","permalink":"https://blog.z6z8.cn/2019/09/26/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9Aios-%E4%BD%BF%E7%94%A8yoga%E5%B8%83%E5%B1%80-%E4%B8%80%E7%A7%8Dflexbox%E5%B8%83%E5%B1%80%E5%AE%9E%E7%8E%B0/","summary":"\u003ch1 id=\"集成\"\u003e集成\u003c/h1\u003e\n\u003cp\u003eYoga是Facebook开源的基于CSS FlexBox布局框架，核心使用C++实现的，在iOS上并不需要直接集成C++代码，只需通过CocoaPod引入 \u003ccode\u003eYogaKit\u003c/code\u003e（间接集成C++代码）\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# Podfile\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eplatform :ios, \u0026#39;8.0\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003euse_frameworks!\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003etarget \u0026#34;TestProject\u0026#34; do\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    pod \u0026#39;YogaKit\u0026#39;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eend\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003cimg loading=\"lazy\" src=\"http://139.155.43.7/wp-content/uploads/2019/09/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7-2019-09-27-%E4%B8%8A%E5%8D%8811.59.57.png\"\u003e\u003c/p\u003e\n\u003ch1 id=\"使用\"\u003e使用\u003c/h1\u003e\n\u003cp\u003e集成后，YogaKit提供了UIView的方法扩展\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e// UIView+Yoga.h\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e@property (nonatomic, readonly, strong) YGLayout *yoga;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e\u003ccode\u003eyoga\u003c/code\u003e 类型为 \u003ccode\u003eYGLayout\u003c/code\u003e，描述了UIView如何布局。\u003c/p\u003e\n\u003cp\u003e简单示例\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-obj-c\" data-lang=\"obj-c\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//代码源自 https://www.jianshu.com/p/95bf92143141\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e-(\u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e)\u003cspan style=\"color:#a6e22e\"\u003etest\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [self.view configureLayoutWithBlock:\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e(YGLayout \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e layout) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.isEnabled \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YES;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.width \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YGPointValue(self.view.bounds.size.width);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.height \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YGPointValue(self.view.bounds.size.height);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.alignItems \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YGAlignCenter;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    UIView \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003econtentView \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[UIView alloc]init];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    contentView.backgroundColor \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [UIColor lightGrayColor];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [contentView configureLayoutWithBlock:\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e(YGLayout \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e layout) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.isEnabled \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e true;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// 4\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        layout.flexDirection \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e  YGFlexDirectionRow;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.width \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YGPointValue(\u003cspan style=\"color:#ae81ff\"\u003e320\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.height \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YGPointValue(\u003cspan style=\"color:#ae81ff\"\u003e80\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.marginTop \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YGPointValue(\u003cspan style=\"color:#ae81ff\"\u003e100\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.padding \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e  YGPointValue(\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e);\u003cspan style=\"color:#75715e\"\u003e//设置了全部子项目的填充值\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    }];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    UIView \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003echild1 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[UIView alloc]init];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    child1.backgroundColor \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [UIColor redColor];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [child1 configureLayoutWithBlock:\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e(YGLayout \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e layout) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.isEnabled \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YES;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.width \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YGPointValue(\u003cspan style=\"color:#ae81ff\"\u003e80\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.marginRight \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YGPointValue(\u003cspan style=\"color:#ae81ff\"\u003e10\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    UIView \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003echild2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [[UIView alloc]init];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    child2.backgroundColor \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [UIColor blueColor];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [child2 configureLayoutWithBlock:\u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e(YGLayout \u003cspan style=\"color:#f92672\"\u003e*\u003c/span\u003e layout) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.isEnabled \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YES;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.width \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YGPointValue(\u003cspan style=\"color:#ae81ff\"\u003e80\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.flexGrow \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.height \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YGPointValue(\u003cspan style=\"color:#ae81ff\"\u003e20\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        layout.alignSelf \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e YGAlignCenter;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [contentView addSubview:child1];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [contentView addSubview:child2];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [self.view addSubview:contentView];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    [self.view.yoga applyLayoutPreservingOrigin:YES];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e注意:\u003c/p\u003e","title":"学习笔记：iOS 使用Yoga布局----一种FlexBox布局实现"},{"content":"[TOC]\nDSL基本语法 可阅读的文件，其语法首先遵循xml规范\n\u0026lt;节点名 节点类型 其他属性\u0026gt; \u0026lt;节点名 节点类型 其他属性\u0026gt; \u0026lt;节点名 节点类型 其他属性\u0026gt; .... \u0026lt;节点名/\u0026gt; \u0026lt;节点名/\u0026gt; \u0026lt;节点名 节点类型 其他属性\u0026gt; \u0026lt;节点名/\u0026gt; \u0026lt;节点名/\u0026gt; 节点类型 ， 指当前节点的类型 ：\n视图类型，表示当前节点描述一个视图属性；此时节点名表示视图的类名，如Text，Button控件类名 其他待扩展 其他属性：\n布局属性 数据属性 其他待扩展 示例:\n\u0026lt;Button type=\u0026#34;view\u0026#34; width=\u0026#34;10\u0026#34;,height=\u0026#34;10%\u0026#34; title=\u0026#34;点击\u0026#34;\u0026gt; \u0026lt;ImageView type=\u0026#34;view\u0026#34; img=\u0026#34;xxx.png\u0026#34; /\u0026gt; \u0026lt;JS type=\u0026#34;javascript\u0026#34;\u0026gt; 此处为示例，不一定支持 \u0026lt;/JS\u0026gt; \u0026lt;/Button\u0026gt; 主轴和交叉轴 (main axis/cross axis) 布局方式 大致和css flex box一致\n文件格式 应支持两种格式\n.xml .ffx（名称暂定)，.xml的二进制化，加速解析效率 布局引擎可根据扩展名判断文件格式\n基本属性 取名尽量和css flex box保持一致\n布局方向 direction direction，子元素在父容器的布局方向。 布局方向也会影响边的起点和终点。\n默认情况下(ltr) “start”是指左侧，“end”是指右侧。\nltr（默认）从左到右排列。 rtl 从右到左排列。 yoga使用RTL方向时，应通过将方向传递给CalculateLayout调用或在根节点上设置方向来自定义此功能\nflex-direction flex-direction，属性指明flex子元素在flex父容器内的布局方向(相对于于主轴和交叉轴来说的)，也就是flex父容器的排列方向：\nrow ，（主轴方向）按行的方向排列。如果启用了换行，则下一行将从容器左侧第一项下方开始。 row-reverse ，（主轴方向）类似 row 值，但是反向。 column ，（交叉轴方向）按列的方向排列。如果启用了换行，则下一行将从容器顶部的左第一项开始。 column-reverse ，（交叉轴方向）类似 column 值，但是反向。 宽度和高度 计量单位待定\n绝对宽度/高度，这可能是节点的最终尺寸，也可能不是， 取决于Yoga节点上设置的其他属性( 译者注:如flex grow ，padding)\nwidth 支持绝对数字、百分比数字、auto。例如 10，10%，auto。\nheight 支持绝对数字、百分比数字、auto。例如 10，10%，auto。\nmax-width 高优先级，默认值 undefined，即无此属性的约束。\n支持绝对数字、百分比数字、auto。例如 10，10%，auto。\nmin-width 高优先级，默认值 undefined，即无此属性的约束。\n支持绝对数字、百分比数字、auto。例如 10，10%，auto。\nmax-height 高优先级，默认值 undefined，即无此属性的约束。\n支持绝对数字、百分比数字、auto。例如 10，10%，auto。\nmin-height 高优先级，默认值 undefined，即无此属性的约束。\n支持绝对数字、百分比数字、auto。例如 10，10%，auto。\n换行 flex-wrap flex-wrap 属性控制着flex容器是单行还是多行，默认情况下，子元素沿着 主轴 排布\nnowrap 默认值，不换行 wrap，多行 wrap-reverse，和wrap类似，但是换行方向相反 对齐 justify-content 沿主轴对齐内容，描述了如何沿主轴对齐子项。\nflex-start，（默认值）将子元素与容器主轴的起点对齐。第一个子元素的起始边跟主轴的起始边对齐，之后的子元素的起始边跟前一个的末边对齐，依次类推 flex-end，末端对齐，和flex-start相反 center，将子元素与容器主轴的中心对齐。子元素相互靠拢，然后整体向主轴的中间对齐。行首和行末的剩余空间是相等的。如果子元素总长度超出容器宽度，那两边溢出的宽度的相同的 space-between， 子元素在容器的主轴上顶两端分布。子元素平均分布在主轴上。如果子元素总长度溢出或只有一个子元素，那它的效果等同于 flex-start 的效果。否则，第一个子元素的起始边和主轴的起始边对齐，最后一个子元素的终边和主轴的末边对齐，剩余其它元素都等距离分布在剩余空间里。 space-around，和space-between 有些像，但不顶两端。子元素平均分布在主轴上，但行首和行末留有1/2的其它子元素之间的空间。如果子元素总长度溢出，或只有一个子元素，那么时的效果等同于 center 效果。否则，子元素平均分布在主轴上，它们之间的空间距离是相同的。而且行首和行末也空间，但空间的宽度只有子元素之间的宽度的一半 space-evenly，子元素沿主轴均匀分布。间距以及和容器开始边缘的间距、结束边缘的间距相同。 演示效果参见 https://yogalayout.com/docs/justify-content\nalign-content 沿交叉轴对齐内容 ，作用是在子元素是多行时，而且容器内还有剩余空间时，设定子元素的对齐方式，跟 justify-content 相似。注意： 这个属性对单行子元素无效果。属性值的含义是：\nflex-start，（默认值） 对齐到容器交叉轴的起点。子元素向交叉轴首对齐，子元素各行紧挨着前一行向交叉轴首对齐 flex-end，对齐到容器交叉轴的末端。子元素向交叉轴尾对齐，子元素各行紧挨着后一行向交叉轴尾对齐。 stretch， 各行（指代主轴方向）等高度拉伸以填满容器交叉轴的高度。如果子元素高度溢出，在此属性效果等同于flex-start center， 对齐到容器交叉轴的中心。子元素各行（指代主轴方向）向交叉轴中心对齐。各行之间不留空间。而交叉轴首和交叉轴尾剩余的空间是相同高度。如果子元素高度溢出，在交叉轴首和交叉轴尾溢出的高度相同。 space-between， 顶交叉轴的两端对齐。子元素各行（指代主轴方向）平均分布在交叉轴高度上。并且交叉轴首和交叉轴尾不留空间，各子元素之间的空间距离相等。 space-around， 和space-between 有些像。子元素各行平均分布在交叉轴高度上，各行（指代主轴方向）之间的距离相等，并且交叉轴首和交叉轴尾也有空间，高度是各行（指代主轴方向）之间的距离的一半。如果子元素的高度溢出，则此属性的效果等同于 center。 align-items 描述子元素如何围绕交叉轴对齐，和 justify-content 的作用非常相似，align-items用于设定容器里子元素的 缺省列对齐方式。\nstretch （默认），拉伸子元素以使其与容器交叉轴的高度匹配。如果子元素交叉轴方向上的高度值为auto，并且交叉轴方向上没有设定margin值，则子元素会拉伸。拉伸的高度是最大化的和列的高度相同。但同时还会受min-height/min-width/max-height/max-width的约束。\n注意: 如果flex容器的高度小于这些约束高度，则子元素会溢出。溢出时，交叉轴首边和子元素起始边对齐，另外一端溢出。\nflex-start， 子元素与容器交叉轴的开始端对齐。\nflex-end， 子元素与容器交叉轴的结束端对齐。\ncenter，交叉轴中心对齐。子元素向交叉轴中靠拢对齐。如果子元素在交叉轴方向上的高度溢出，则上下溢出的长度相同。\n？？？baseline， 使子元素沿着共同的基线对齐。\nalign-self 此属性和justify-content的作用很相似。此属性是作用在单个子元素上，设定指定子元素的交叉轴对齐方式，会覆盖父元素align-items的缺省设定。\n如果子元素的交叉轴方向上的margin有值，则无效。\n对于绝对定位的元素，值为 auto 时，系统自动计算效果。其它情况下，如果align-self值为auto，效果根据父元素的align-self而定，如果没有父元素，则设置为stretch\n默认值auto，取值参考align-items\n伸缩 flex-grow 描述了容器空间应如何 沿主轴 分配给子元素。 放置其子元素后，容器将根据其子元素指定的flex-grow值分配所有剩余空间。 flex-grow接受大于等于0的任何浮点值，默认值为0。 容器将在孩子之间分配剩余的空间，该剩余空间将根据孩子的弹性增长值来加权。\n1、假设主轴为宽度方向 2、那么再假设容器宽度为10 3、假设有3个宽度为2的子项a,b,c 4、再假设a的flex grow为3，b的flex grow为1，c的flex grow为0 先沿着主轴布局a,b,c，三个子项占据宽度3x2=6 还剩下宽度4,根据各自的flex grow,计算加权比重得出 a占据剩余宽度的3/(3+1+0)=75%，也就是3 b占据剩余宽度的1/(3+1+0)=25%，也就是1 c占据剩余宽度的0/(3+1+0)=0%，也就是0 最后 a的宽度为 2+3 = 5 b的宽度为 2+1 = 3 c的宽度为 2+0 = 2 flex-shrink 描述了在子项 主轴上 的总大小溢出容器大小的情况下如何沿主轴收缩子项。 flex shrink 与flex grow非常相似，也计算加权比重和负空间（溢出大小）相乘，得出需要缩小的尺寸。 flex-shink接受任何大于等于0的浮点值，默认值为1。 容器将根据其子项的flex shink值对子项进行收缩。 （如何收缩可以参考上面flex-grow的示例）\nflex-basis flex-basis是一种与轴无关的方式。 如果子元素的父级是具有flex row方向的容器，则设置子项的flex basis似于设置子项的宽度； 如果子元素的父级是具有flex column方向的容器，则设置子项的flex basis似于设置子项的高度。 flex-basis的默认大小在执行flex grow动作和flex shrink动作之前计算。\n边距和填充 ","permalink":"https://blog.z6z8.cn/2019/09/25/%E5%9F%BA%E4%BA%8Eyoga%E7%9A%84%E7%A7%BB%E5%8A%A8%E7%AB%AF%E5%B8%83%E5%B1%80%E8%AE%BE%E8%AE%A1%E6%96%B9%E6%A1%88/","summary":"\u003cp\u003e[TOC]\u003c/p\u003e\n\u003ch1 id=\"dsl基本语法\"\u003eDSL基本语法\u003c/h1\u003e\n\u003cp\u003e可阅读的文件，其语法首先遵循xml规范\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u0026lt;节点名 节点类型  其他属性\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;节点名 节点类型  其他属性\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;节点名 节点类型  其他属性\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         ....\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;节点名/\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;节点名/\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;节点名 节点类型  其他属性\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u0026lt;节点名/\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026lt;节点名/\u0026gt;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e节点类型 ， 指当前节点的类型 ：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e视图类型，表示当前节点描述一个视图属性；此时节点名表示视图的类名，如Text，Button控件类名\u003c/li\u003e\n\u003cli\u003e其他待扩展\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e其他属性：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e布局属性\u003c/li\u003e\n\u003cli\u003e数据属性\u003c/li\u003e\n\u003cli\u003e其他待扩展\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e示例:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-xml\" data-lang=\"xml\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;Button\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etype=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;view\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ewidth=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;10\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#960050;background-color:#1e0010\"\u003e,\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eheight=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;10%\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etitle=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;点击\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026lt;ImageView\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etype=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;view\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eimg=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;xxx.png\u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e/\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026lt;JS\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etype=\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;javascript\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    此处为示例，不一定支持\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#f92672\"\u003e\u0026lt;/JS\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;/Button\u0026gt;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"主轴和交叉轴-main-axiscross-axis\"\u003e主轴和交叉轴 (main axis/cross axis)\u003c/h1\u003e\n\u003cp\u003e\u003cimg alt=\"img\" loading=\"lazy\" src=\"http://pic.caibaojian.com/uploads/2014/05/flexbox.png\"\u003e\u003c/p\u003e\n\u003ch1 id=\"布局方式\"\u003e布局方式\u003c/h1\u003e\n\u003cp\u003e大致和css flex box一致\u003c/p\u003e\n\u003ch1 id=\"文件格式\"\u003e文件格式\u003c/h1\u003e\n\u003cp\u003e应支持两种格式\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e.xml\u003c/li\u003e\n\u003cli\u003e.ffx（名称暂定)，.xml的二进制化，加速解析效率\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e布局引擎可根据扩展名判断文件格式\u003c/p\u003e\n\u003ch1 id=\"基本属性\"\u003e基本属性\u003c/h1\u003e\n\u003cp\u003e取名尽量和css flex box保持一致\u003c/p\u003e\n\u003ch2 id=\"布局方向\"\u003e布局方向\u003c/h2\u003e\n\u003ch3 id=\"direction\"\u003edirection\u003c/h3\u003e\n\u003cp\u003e\u003ccode\u003edirection\u003c/code\u003e，子元素在父容器的布局方向。 布局方向也会影响边的起点和终点。\u003c/p\u003e\n\u003cp\u003e默认情况下(ltr) “start”是指左侧，“end”是指右侧。\u003c/p\u003e","title":"基于Yoga的移动端布局设计方案"},{"content":"使用示例\nString str = \u0026#34;hello world\u0026#34;; int key[] = {-123,-456,789,123,456,7890,456,456}; int noc[] = {-123,-456,789,123}; byte[] encryptData = Chacha20.crytpoCounter32(str.getBytes(),key,noc); byte[] decryptData = Chacha20.crytpoCounter32(encryptData,key,noc); String str2 = new String(decryptData); boolean equal = str.equals(str2); 具体代码\npackage com.zxs.zl; /* * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved. * * Licensed under the Apache License 2.0 (the \u0026#34;License\u0026#34;). You may not use * this file except in compliance with the License. You can obtain a copy * in the file LICENSE in the source distribution or at * https://www.openssl.org/source/license.html */ public class Chacha20 { /* * ChaCha20_ctr32 encrypts |len| bytes from |inp| with the given key and * nonce and writes the result to |out|, which may be equal to |inp|. * The |key| is not 32 bytes of verbatim key material though, but the * said material collected into 8 32-bit elements array in host byte * order. Same approach applies to nonce: the |counter| argument is * pointer to concatenated nonce and counter values collected into 4 * 32-bit elements. This, passing crypto material collected into 32-bit * elements as opposite to passing verbatim byte vectors, is chosen for * efficiency in multi-call scenarios. */ /** * function same ,encrypt and decrypt * @param inp source data (encrypt data or decrypt data) * @param key int[8] array * @param counter int[4] array * @return decrypt data or encrypt data ; see inp param. */ public static byte[] crytpoCounter32(byte[] inp, int[] key,int[] counter) { byte[] out = new byte[inp.length]; int[] input = new int[16]; byte[] buf = new byte[64]; int todo, i; /* sigma constant \u0026#34;expand 32-byte k\u0026#34; in little-endian encoding */ input[0] = ((int)\u0026#39;e\u0026#39;) | ((int)\u0026#39;x\u0026#39;\u0026lt;\u0026lt;8) | ((int)\u0026#39;p\u0026#39;\u0026lt;\u0026lt;16) | ((int)\u0026#39;a\u0026#39;\u0026lt;\u0026lt;24); input[1] = ((int)\u0026#39;n\u0026#39;) | ((int)\u0026#39;d\u0026#39;\u0026lt;\u0026lt;8) | ((int)\u0026#39; \u0026#39;\u0026lt;\u0026lt;16) | ((int)\u0026#39;3\u0026#39;\u0026lt;\u0026lt;24); input[2] = ((int)\u0026#39;2\u0026#39;) | ((int)\u0026#39;-\u0026#39;\u0026lt;\u0026lt;8) | ((int)\u0026#39;b\u0026#39;\u0026lt;\u0026lt;16) | ((int)\u0026#39;y\u0026#39;\u0026lt;\u0026lt;24); input[3] = ((int)\u0026#39;t\u0026#39;) | ((int)\u0026#39;e\u0026#39;\u0026lt;\u0026lt;8) | ((int)\u0026#39; \u0026#39;\u0026lt;\u0026lt;16) | ((int)\u0026#39;k\u0026#39;\u0026lt;\u0026lt;24); input[4] = key[0]; input[5] = key[1]; input[6] = key[2]; input[7] = key[3]; input[8] = key[4]; input[9] = key[5]; input[10] = key[6]; input[11] = key[7]; input[12] = counter[0]; input[13] = counter[1]; input[14] = counter[2]; input[15] = counter[3]; int len = inp.length; int offset = 0; while (len \u0026gt; 0) { todo = 64;// equal to buf.length; if (len \u0026lt; todo) todo = len; chacha20_core(buf, input); for (i = 0; i \u0026lt; todo; i++){ out[i+offset] = (byte) (inp[i+offset] ^ buf[i]); } offset += todo; len -= todo; /* * Advance 32-bit counter. Note that as subroutine is so to * say nonce-agnostic, this limited counter width doesn\u0026#39;t * prevent caller from implementing wider counter. It would * simply take two calls split on counter overflow... */ input[12]++; } return out; } /* chacha_core performs 20 rounds of ChaCha on the input words in * |input| and writes the 64 output bytes to |output|. */ private static void chacha20_core(byte[] output, int[] input) { //output byte[64] long[] x = new long[16]; for (int i = 0 ; i \u0026lt; 16 ;i++){ x[i] = (input[i] \u0026amp; 0xFFFFFFFFL ); } for (int i = 20; i \u0026gt; 0; i -= 2) { QUARTERROUND(x,0, 4, 8, 12); QUARTERROUND(x,1, 5, 9, 13); QUARTERROUND(x,2, 6, 10, 14); QUARTERROUND(x,3, 7, 11, 15); QUARTERROUND(x,0, 5, 10, 15); QUARTERROUND(x,1, 6, 11, 12); QUARTERROUND(x,2, 7, 8, 13); QUARTERROUND(x,3, 4, 9, 14); } for (int i = 0; i \u0026lt; 16; ++i) { long v = (x[i] + input[i]) \u0026amp; 0xFFFFFFFFL; output[i\u0026lt;\u0026lt;2] = (byte) (v \u0026amp; 0xFF); output[(i\u0026lt;\u0026lt;2) + 1] = (byte) ((v\u0026gt;\u0026gt;8) \u0026amp; 0xFF); output[(i\u0026lt;\u0026lt;2) + 2] = (byte) ((v\u0026gt;\u0026gt;16) \u0026amp; 0xFF); output[(i\u0026lt;\u0026lt;2) + 3] = (byte) ((v\u0026gt;\u0026gt;24) \u0026amp; 0xFF); } } /* QUARTERROUND updates a, b, c, d with a ChaCha \u0026#34;quarter\u0026#34; round. */ private static void QUARTERROUND(long[]x, int a,int b,int c,int d){ x[a] = (x[a] + x[b]) \u0026amp; 0xFFFFFFFFL; x[d] = ROTATE((x[d] ^ x[a]),16) \u0026amp; 0xFFFFFFFFL; x[c] = (x[c] + x[d]) \u0026amp; 0xFFFFFFFFL; x[b] = ROTATE((x[b] ^ x[c]),12) \u0026amp; 0xFFFFFFFFL; x[a] = (x[a] + x[b]) \u0026amp; 0xFFFFFFFFL; x[d] = ROTATE((x[d] ^ x[a]), 8) \u0026amp; 0xFFFFFFFFL; x[c] = (x[c] + x[d]) \u0026amp; 0xFFFFFFFFL; x[b] = ROTATE((x[b] ^ x[c]), 7) \u0026amp; 0xFFFFFFFFL; } private static long ROTATE(long v,int n) { v = v \u0026amp; 0xFFFFFFFFL; return (((v) \u0026lt;\u0026lt; (n)) | ((v) \u0026gt;\u0026gt; (32 - (n)))); } } ","permalink":"https://blog.z6z8.cn/2019/09/24/java%EF%BC%9Achacha20%E7%AE%97%E6%B3%95%EF%BC%88%E4%BB%8Eopenssl%E7%A7%BB%E6%A4%8D%EF%BC%89/","summary":"\u003cp\u003e使用示例\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        String str \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hello world\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e key\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e123,\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e456,789,123,456,7890,456,456};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e noc\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e {\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e123,\u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e456,789,123};\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e encryptData \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Chacha20.\u003cspan style=\"color:#a6e22e\"\u003ecrytpoCounter32\u003c/span\u003e(str.\u003cspan style=\"color:#a6e22e\"\u003egetBytes\u003c/span\u003e(),key,noc);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e decryptData \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e Chacha20.\u003cspan style=\"color:#a6e22e\"\u003ecrytpoCounter32\u003c/span\u003e(encryptData,key,noc);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        String str2 \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e String(decryptData);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eboolean\u003c/span\u003e equal \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e str.\u003cspan style=\"color:#a6e22e\"\u003eequals\u003c/span\u003e(str2);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e具体代码\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-java\" data-lang=\"java\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003epackage\u003c/span\u003e com.zxs.zl;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e/*\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e * Copyright 2015-2018 The OpenSSL Project Authors. All Rights Reserved.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e *\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e * Licensed under the Apache License 2.0 (the \u0026#34;License\u0026#34;).  You may not use\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e * this file except in compliance with the License.  You can obtain a copy\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e * in the file LICENSE in the source distribution or at\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e * https://www.openssl.org/source/license.html\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eChacha20\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e/*\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * ChaCha20_ctr32 encrypts |len| bytes from |inp| with the given key and\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * nonce and writes the result to |out|, which may be equal to |inp|.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * The |key| is not 32 bytes of verbatim key material though, but the\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * said material collected into 8 32-bit elements array in host byte\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * order. Same approach applies to nonce: the |counter| argument is\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * pointer to concatenated nonce and counter values collected into 4\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * 32-bit elements. This, passing crypto material collected into 32-bit\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * elements as opposite to passing verbatim byte vectors, is chosen for\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * efficiency in multi-call scenarios.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e/**\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * function same  ,encrypt and decrypt\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * @param inp source data (encrypt data or decrypt data)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * @param key int[8] array\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * @param counter int[4] array\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * @return  decrypt data or encrypt data ; see inp param.\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ecrytpoCounter32\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e inp, \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e key,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e counter)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e out \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003einp.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e input \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e16\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e buf \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e64\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e todo, i;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e/* sigma constant \u0026#34;expand 32-byte k\u0026#34; in little-endian encoding */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e0\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;e\u0026#39;\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;x\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e8) \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;p\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e16) \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;a\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e24);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e1\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;n\u0026#39;\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;d\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e8) \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e16) \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;3\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e24);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;2\u0026#39;\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;-\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e8) \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;b\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e16) \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;y\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e24);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e3\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;t\u0026#39;\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;e\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e8) \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39; \u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e16) \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ((\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e)\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;k\u0026#39;\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e24);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e4\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e key\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e0\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e5\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e key\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e1\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e6\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e key\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e7\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e key\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e3\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e8\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e key\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e4\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e9\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e key\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e5\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e10\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e key\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e6\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e11\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e key\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e7\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e12\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e counter\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e0\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e13\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e counter\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e1\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e14\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e counter\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e15\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e counter\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e3\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e len \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e inp.\u003cspan style=\"color:#a6e22e\"\u003elength\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e offset \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 0;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e (len \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e 0) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            todo \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 64;\u003cspan style=\"color:#75715e\"\u003e// equal to buf.length;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e (len \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e todo)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                todo \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e len;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            chacha20_core(buf, input);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 0; i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e todo; i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                out\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ei\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003eoffset\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e) (inp\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ei\u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003eoffset\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e buf\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ei\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            offset \u003cspan style=\"color:#f92672\"\u003e+=\u003c/span\u003e todo;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            len \u003cspan style=\"color:#f92672\"\u003e-=\u003c/span\u003e todo;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e/*\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e             * Advance 32-bit counter. Note that as subroutine is so to\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e             * say nonce-agnostic, this limited counter width doesn\u0026#39;t\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e             * prevent caller from implementing wider counter. It would\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e             * simply take two calls split on counter overflow...\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e             */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e12\u003cspan style=\"color:#f92672\"\u003e]++\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e out;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e/* chacha_core performs 20 rounds of ChaCha on the input words in\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e     * |input| and writes the 64 output bytes to |output|. */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003echacha20_core\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e output, \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e input)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e//output byte[64]\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003e x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e16\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 0 ; i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e 16 ;i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ei\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ei\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFFFFFFFFL );\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 20; i \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e 0; i \u003cspan style=\"color:#f92672\"\u003e-=\u003c/span\u003e 2) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            QUARTERROUND(x,0, 4, 8, 12);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            QUARTERROUND(x,1, 5, 9, 13);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            QUARTERROUND(x,2, 6, 10, 14);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            QUARTERROUND(x,3, 7, 11, 15);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            QUARTERROUND(x,0, 5, 10, 15);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            QUARTERROUND(x,1, 6, 11, 12);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            QUARTERROUND(x,2, 7, 8, 13);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            QUARTERROUND(x,3, 4, 9, 14);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e 0; i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e 16; \u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003ei) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e v \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ei\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e input\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ei\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFFFFFFFFL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            output\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ei\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e) (v \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFF);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            output\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e(i\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e2) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e 1\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e) ((v\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e8) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFF);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            output\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e(i\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e2) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e 2\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e) ((v\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e16) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFF);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            output\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003e(i\u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e2) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e 3\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (\u003cspan style=\"color:#66d9ef\"\u003ebyte\u003c/span\u003e) ((v\u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e24) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFF);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e/* QUARTERROUND updates a, b, c, d with a ChaCha \u0026#34;quarter\u0026#34; round. */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003evoid\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eQUARTERROUND\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e[]\u003c/span\u003ex, \u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e a,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e b,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e c,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e d){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ea\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ea\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eb\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFFFFFFFFL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ed\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ROTATE((x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ed\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ea\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e),16) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFFFFFFFFL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ec\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ec\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ed\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFFFFFFFFL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eb\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ROTATE((x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eb\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ec\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e),12) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFFFFFFFFL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ea\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ea\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eb\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFFFFFFFFL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ed\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ROTATE((x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ed\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ea\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e), 8) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFFFFFFFFL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ec\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e (x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ec\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ed\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFFFFFFFFL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eb\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e ROTATE((x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003eb\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e^\u003c/span\u003e x\u003cspan style=\"color:#f92672\"\u003e[\u003c/span\u003ec\u003cspan style=\"color:#f92672\"\u003e]\u003c/span\u003e), 7) \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFFFFFFFFL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eROTATE\u003c/span\u003e(\u003cspan style=\"color:#66d9ef\"\u003elong\u003c/span\u003e v,\u003cspan style=\"color:#66d9ef\"\u003eint\u003c/span\u003e n)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        v \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e v \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u003c/span\u003e 0xFFFFFFFFL;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e (((v) \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u0026lt;\u003c/span\u003e (n)) \u003cspan style=\"color:#f92672\"\u003e|\u003c/span\u003e ((v) \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u0026gt;\u003c/span\u003e (32 \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e (n))));\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"Java：Chacha20算法（从openssl移植）"},{"content":"本文为Google翻译+人工修正文章 参考 https://yogalayout.com/docs\n[TOC]\n主轴和交叉轴 (main axis/cross axis) 绝对布局和相对布局 (Absolute/Relative Layout) 元素布局分为两种，一种是绝对布局，一种是相对布局。\n相对布局 (默认) 默认情况下，元素的位置相对。 这意味着元素将根据布局的正常流程进行定位，然后根据上，右，下和左的值相对于该位置偏移。 偏移量不会影响任何同级元素或父元素的位置。\n绝对布局 绝对位置绝对放置时，元素不会参与正常的布局流程。 相反，它的布局与兄弟姐妹无关。 根据上，右，下和左的值确定位置。\n译者注：注意取值顺序，上（top），右（right），下（bottom），左（left）\n位置值上（top），右（right），下（bottom），左（left）的行为取决于元素的位置类型(相对布局或绝对布局)。 对于相对布局元素，它们沿指定方向偏移元素的位置。 对于绝对布局元素，这些属性指定了元素的相对于父元素的同一边的偏移量（ 译者注，这句有点绕，其实就是同边对同边，例如子元素的上（top）是从父元素的上（top）开始算起）。\n演示效果参见 https://yogalayout.com/docs/absolute-relative-layout\n布局方向（Layout direction） 指在层次结构中，子项和文本的布局方向。 布局方向也会影响边的起点和终点。\n默认情况下，Yoga沿LTR布局方向进行布局。在此模式下，“start”是指左侧，“end”是指右侧。\n使用RTL方向时，应通过将方向传递给CalculateLayout调用或在根节点上设置方向来自定义此功能。\nLTR（默认）从左到右排列。 应用于元素边距和填充的开始在左侧。 RTL 从右到左排列。 应用于元素边距和填充的开始在右侧。 宽度和高度（ Width and Height） Yoga中的width属性指定元素内容区域的宽度。 同样，height属性指定元素内容区域的高度。\n宽度和高度都可以采用以下值：\nAUTO是默认值，Yoga根据元素的内容（无论是其他子元素，文本还是图像）计算元素的宽度/高度。 PIXELS 定义绝对像素的宽度/高度。 取决于Yoga节点上设置的其他属性( 译者注:如flex grow ，padding)，这可能是节点的最终尺寸，也可能不是。 PERCENTAGE 分别以其父对象的宽度或高度的百分比定义宽度或高度。 演示效果参见 https://yogalayout.com/docs/width-height\n宽高的最值(Max / Min Width and Height) 以下所有属性均设置元素的最大和最小尺寸限制。 这些属性的优先级高于所有其他属性，并且将始终受到(布局动作)的考虑。 约束可以指定为绝对像素值，也可以指定为其父级大小的百分比。 默认情况下，所有这些约束都是 undefined。\nMAX WIDTH MIN WIDTH MAX HEIGHT MIN HEIGHT 演示效果参见 https://yogalayout.com/docs/min-max\n宽高比(Aspect ratio) AspectRatio是Yoga引入的属性，在CSS Flexbox规范中未作为可设置的属性显示。Flexbox确实具有宽高比的概念，尽管对于具有固有高宽比的事物（例如图像）。\nYoga中的宽高比属性具有以下属性：\n接受任何大于0的浮点值，默认值为undefined。 定义为节点的宽度与高度之比，例如 如果节点的宽高比为2，则其宽度是其高度的两倍。 遵守项目(item，这里只布局元素)的最小和最大尺寸。 具有比 flex grow（弹性增长） 更高的优先级 如果设置了宽高比，宽度和高度，则将覆盖交叉轴尺寸。 演示效果参见 https://yogalayout.com/docs/aspect-ratio/\n对齐(Align) 沿交叉轴对齐内容 （Align Content） 定义沿交叉轴（cross-axis，也主轴垂直的轴）的线分布。 仅当使用flex wrap将项目包装到多行时，此功能才有效。\n可用值有：\nFLEX START（DEFAULT）将环绕线（wraped line）对齐到容器交叉轴的起点。 FLEX END 将环绕线（wraped line）对齐到容器交叉轴的末端。 STRETCH 拉伸环绕线（wraped line）以匹配容器交叉轴的高度。 CENTER 将环绕线（wraped line）对齐到容器交叉轴的中心。 SPACE BETWEEN 顶交叉轴的两端对齐。 SPACE AROUND 沿交叉轴均匀分布，和SPACE BETWEEN 有些像，但不相同，可参考演示效果。 演示效果参见 https://yogalayout.com/docs/align-content\n沿主轴对齐内容(Justify Content) 描述了如何沿主轴对齐子项。\nFLEX START（DEFAULT）将容器的子项与容器主轴的起点对齐。 FLEX END 将容器的子项与容器主轴的末端对齐。 CENTER 将容器的子项与容器主轴的中心对齐。 SPACE BETWEEN 子项在容器的主轴上顶两端分布。 SPACE AROUND 和SPACE BETWEEN 有些像，但不顶两端。 SPACE EVENLY，子项沿主轴均匀分布。间距以及和容器开始边缘的间距、结束边缘的间距相同。 演示效果参见 https://yogalayout.com/docs/justify-content\n对齐项（Align Item） 描述子项如何围绕交叉轴对齐。 对齐项与 (内容对齐)justify-content 非常相似，但是对齐项不是应用于主轴，而是应用于交叉轴。\nSTRETCH （默认）拉伸子项以使其与容器交叉轴的高度匹配。 FLEX START 将子项与容器交叉轴的开始端对齐。 FLEX END 将子项与容器交叉轴的结束端对齐。 CENTER 将容器的子代与容器的交叉轴中心对齐。 BASELINE 使子项沿着共同的基线对齐。可以将单个孩子设置为其父母的参考基准。 演示效果参见 https://yogalayout.com/docs/align-items\n自我对齐(Align Self) 自我对齐具有与对齐项（Align Items）相同的选项和效果，但是可以对单个子项应用此属性以更改其在其父级中的对齐方式，而不是影响容器中的子项目。 自我对齐(Align self)会覆盖父项通过(Align items)项目设置的任何选项。\n译者注，Align Item影响子项，而Align Self只针对自己，会覆盖通过Align Item赋予的值\n演示效果参见 https://yogalayout.com/docs/align-items\n伸缩(Flex) 伸缩方向（Flex Direction） 伸缩方向控制子项的伸缩方向。伸缩方向是相对于于主轴和交叉轴来说的。\nROW （默认）（主轴方向）从左到右对齐子项。 如果启用了环绕(wrap)，则下一行将从容器左侧第一项下方开始。 COLUMN （交叉轴方向） 从上至下对齐子项。 如果启用了环绕(wrap)，则下一行将从容器顶部的左第一项开始。 ROW REVERSE （主轴方向）从右向左对齐子项。 如果启用了环绕(wrap)，则下一行将从容器右侧的第一项开始。 COLUMN REVERSE （交叉轴方向）从下到上对齐子项。 如果启用了环绕(wrap)，则下一行将从容器底部的第一行开始。 演示效果参见 https://yogalayout.com/docs/flex-direction\n环绕换行(Flex Wrap) 默认情况下，可伸缩子项被强制排布为一行。\nflex wrap 属性是在容器上设置的，并控制当子项沿主轴布局溢出容器大小时发生的情况。 如果允许环绕，则根据需要将项目沿主轴布成多行。 wrap reverse 换行的行为相同，但顺序相反。 换行时，可以使用 对齐内容 (align content ) 指定行在容器中的放置方式。\n演示效果参见 https://yogalayout.com/docs/flex-wrap\n伸缩(Flex)\u0026ndash;基础(Basis),增长(Grow)和缩小(Shrink) FLEX GROW 描述了容器空间应如何 沿主轴 分配给子项。 放置其子项后，容器将根据其子项指定的flex grow值分配所有剩余空间。 Flex grow接受大于等于0的任何浮点值，默认值为0。 容器将在孩子之间分配剩余的空间，该剩余空间将根据孩子的弹性增长值来加权。 译者注： 1、假设主轴为宽度方向 2、那么再假设容器宽度为10 3、假设有3个宽度为2的子项a,b,c 4、再假设a的flex grow为3，b的flex grow为1，c的flex grow为0 先沿着主轴布局a,b,c，三个子项占据宽度3x2=6 还剩下宽度4,根据各自的flex grow,计算加权比重得出 a占据剩余宽度的3/(3+1+0)=75%，也就是3 b占据剩余宽度的1/(3+1+0)=25%，也就是1 c占据剩余宽度的0/(3+1+0)=0%，也就是0 最后 a的宽度为 2+3 = 5 b的宽度为 2+1 = 3 c的宽度为 2+0 = 2 FLEX SHRINK 描述了在子项 主轴上 的总大小溢出容器大小的情况下如何沿主轴收缩子项。 flex shrink 与flex grow非常相似，也计算加权比重和负空间（溢出大小）相乘，得出需要缩小的尺寸。 Flex Shink接受任何大于等于0的浮点值，默认值为1。 容器将根据其子项的flex shink值对子项进行收缩。 （如何收缩可以参考上面flex grow的示例） FLEX BASIS 是一种与轴无关的方式，用于沿主轴提供子项的默认大小。 如果子项的父级是具有flex row方向的容器，则设置子项的flex basis似于设置子项的宽度； 如果子项的父级是具有flex column方向的容器，则设置子项的flex basis似于设置子项的高度。 flex basis的默认大小在执行flex grow动作和flex shrink动作之前计算。 演示效果参见 https://yogalayout.com/docs/flex/\n边距（Margins）,填充( Paddings), 边框( Borders) MARGIN 影响节点外部周围的间距。 具有边距的节点将使其自身偏离其父级的边界，但也会偏移所有同级的位置。 如果父节点是自动调整大小的，则节点的边距将对其父节点的总大小有所贡献。 PADDING 会影响它所应用的节点的大小。在 Yoga中，填充就像 box-sizing:border-box; 一样。 也就是说，如果元素具有显式大小，则填充不会增加元素的总大小。 对于自动调整大小的节点，填充将增加节点的大小以及偏移任何子节点的位置。 BORDER 在Yoga中的行为与填充(PADDING)完全一样，因为作为单独的属性存在，优先级高于框架的暗示（注，类似于框架的全局设定）。 然而，Yoga并没有做任何绘图，因此仅在布局过程中使用此信息，边框的行为完全类似于填充。 演示效果参见 https://yogalayout.com/docs/margins-paddings-borders/\n","permalink":"https://blog.z6z8.cn/2019/09/23/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9Ayoga-%E5%B8%83%E5%B1%80%E5%B1%9E%E6%80%A7/","summary":"\u003cp\u003e本文为Google翻译+人工修正文章 参考 \u003ca href=\"https://yogalayout.com/docs\"\u003ehttps://yogalayout.com/docs\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e[TOC]\u003c/p\u003e\n\u003ch1 id=\"主轴和交叉轴-main-axiscross-axis\"\u003e主轴和交叉轴 (main axis/cross axis)\u003c/h1\u003e\n\u003cp\u003e\u003cimg alt=\"图片名称\" loading=\"lazy\" src=\"/wp-content/uploads/2019/09/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7-2019-09-23-%E4%B8%8B%E5%8D%885.17.36-1.png\"\u003e\u003c/p\u003e\n\u003ch1 id=\"绝对布局和相对布局-absoluterelative-layout\"\u003e绝对布局和相对布局 (Absolute/Relative Layout)\u003c/h1\u003e\n\u003cp\u003e元素布局分为两种，一种是绝对布局，一种是相对布局。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e相对布局 (默认)\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e默认情况下，元素的位置相对。 这意味着元素将根据布局的正常流程进行定位，然后根据上，右，下和左的值相对于该位置偏移。 偏移量不会影响任何同级元素或父元素的位置。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003e绝对布局\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e绝对位置绝对放置时，元素不会参与正常的布局流程。 相反，它的布局与兄弟姐妹无关。 根据上，右，下和左的值确定位置。\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003e译者注：注意取值顺序，上（top），右（right），下（bottom），左（left）\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e位置值上（top），右（right），下（bottom），左（left）的行为取决于元素的位置类型(相对布局或绝对布局)。 对于相对布局元素，它们沿指定方向偏移元素的位置。 对于绝对布局元素，这些属性指定了元素的相对于父元素的同一边的偏移量（ \u003ccode\u003e译者注，这句有点绕，其实就是同边对同边，例如子元素的上（top）是从父元素的上（top）开始算起\u003c/code\u003e）。\u003c/p\u003e\n\u003cp\u003e演示效果参见 \u003ca href=\"https://yogalayout.com/docs/absolute-relative-layout\"\u003ehttps://yogalayout.com/docs/absolute-relative-layout\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"布局方向layout-direction\"\u003e布局方向（Layout direction）\u003c/h1\u003e\n\u003cp\u003e指在层次结构中，子项和文本的布局方向。 布局方向也会影响边的起点和终点。\u003c/p\u003e\n\u003cp\u003e默认情况下，Yoga沿LTR布局方向进行布局。在此模式下，“start”是指左侧，“end”是指右侧。\u003c/p\u003e\n\u003cp\u003e\u003ccode\u003e使用RTL方向时，应通过将方向传递给CalculateLayout调用或在根节点上设置方向来自定义此功能\u003c/code\u003e。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eLTR（默认）从左到右排列。 应用于元素边距和填充的开始在左侧。\u003c/li\u003e\n\u003cli\u003eRTL 从右到左排列。 应用于元素边距和填充的开始在右侧。\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"宽度和高度-width-and-height\"\u003e宽度和高度（ Width and Height）\u003c/h1\u003e\n\u003cp\u003eYoga中的width属性指定元素内容区域的宽度。 同样，height属性指定元素内容区域的高度。\u003c/p\u003e\n\u003cp\u003e宽度和高度都可以采用以下值：\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eAUTO是默认值，Yoga根据元素的内容（无论是其他子元素，文本还是图像）计算元素的宽度/高度。\u003c/li\u003e\n\u003cli\u003ePIXELS 定义绝对像素的宽度/高度。 取决于Yoga节点上设置的其他属性( \u003ccode\u003e译者注:如flex grow ，padding\u003c/code\u003e)，这可能是节点的最终尺寸，也可能不是。\u003c/li\u003e\n\u003cli\u003ePERCENTAGE 分别以其父对象的宽度或高度的百分比定义宽度或高度。\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e演示效果参见 \u003ca href=\"https://yogalayout.com/docs/width-height\"\u003ehttps://yogalayout.com/docs/width-height\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"宽高的最值max--min-width-and-height\"\u003e宽高的最值(Max / Min Width and Height)\u003c/h2\u003e\n\u003cp\u003e以下所有属性均设置元素的最大和最小尺寸限制。 \u003ccode\u003e 这些属性的优先级高于所有其他属性，并且将始终受到(布局动作)的考虑\u003c/code\u003e。 约束可以指定为绝对像素值，也可以指定为其父级大小的百分比。 默认情况下，所有这些约束都是 \u003ccode\u003eundefined\u003c/code\u003e。\u003c/p\u003e\n\u003cul\u003e\n\u003cli\u003eMAX WIDTH\u003c/li\u003e\n\u003cli\u003eMIN WIDTH\u003c/li\u003e\n\u003cli\u003eMAX HEIGHT\u003c/li\u003e\n\u003cli\u003eMIN HEIGHT\u003c/li\u003e\n\u003c/ul\u003e\n\u003cp\u003e演示效果参见 \u003ca href=\"https://yogalayout.com/docs/min-max\"\u003ehttps://yogalayout.com/docs/min-max\u003c/a\u003e\u003c/p\u003e","title":"学习笔记：Yoga 布局属性"},{"content":"支持SSL/TLS 在nginx的虚拟主机配置文件中添加\nserver { # http配置 listen 80; listen [::]:80; server_name test.abc.com; ####### SSL配置 ######### listen 443 ssl; listen [::]:443 ssl; #解决The plain HTTP request was sent to HTTPS port # https://www.centos.bz/2018/01/nginx%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3the-plain-http-request-was-sent-to-https-port%E9%94%99%E8%AF%AF/ ssl off; #ssl 会话超时 ssl_session_timeout 5m; #支持的SSL/TLS协议版本 ，如SSLv2 SSLv3 TLSv1; ssl_protocols SSLv3 TLSv1; #支持的协商算法 ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; ssl_prefer_server_ciphers on; # SSL证书位置 ssl_certificate /xxxx/xxxx/123.crt; ssl_certificate_key /xxxx/xxxx/456.key; ################ 其他配置略 ..... } 自动转发HTTP到HTTPS 原理是rerwite规则，重定向到https，所以需要创建两个虚拟主机，一个http，一个https\n配置如下\nserver { listen 80; listen [::]:80; server_name test.abc.com; #转发到https://xxxx rewrite ^(.*) https://$server_name$1 permanent; } server { server_name test.abc.com; #以下内容不变 ####### SSL配置 ######### listen 443 ssl; listen [::]:443 ssl; #解决The plain HTTP request was sent to HTTPS port # https://www.centos.bz/2018/01/nginx%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3the-plain-http-request-was-sent-to-https-port%E9%94%99%E8%AF%AF/ ssl off; #ssl 会话超时 ssl_session_timeout 5m; #支持的SSL/TLS协议版本 ，如SSLv2 SSLv3 TLSv1; ssl_protocols SSLv3 TLSv1; #支持的协商算法 ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP; ssl_prefer_server_ciphers on; # SSL证书位置 ssl_certificate /xxxx/xxxx/123.crt; ssl_certificate_key /xxxx/xxxx/456.key; ################ 其他配置略 ..... } ","permalink":"https://blog.z6z8.cn/2019/09/23/nginx-%E9%85%8D%E7%BD%AEssl%E8%AF%81%E4%B9%A6/","summary":"\u003ch1 id=\"支持ssltls\"\u003e支持SSL/TLS\u003c/h1\u003e\n\u003cp\u003e在nginx的虚拟主机配置文件中添加\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eserver {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    # http配置\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    listen 80;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    listen [::]:80;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    server_name  test.abc.com;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    #######  SSL配置 #########\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    listen 443 ssl;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    listen [::]:443 ssl;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    #解决The plain HTTP request was sent to HTTPS port\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    # https://www.centos.bz/2018/01/nginx%E5%A6%82%E4%BD%95%E8%A7%A3%E5%86%B3the-plain-http-request-was-sent-to-https-port%E9%94%99%E8%AF%AF/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ssl off;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    #ssl 会话超时\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ssl_session_timeout  5m;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    #支持的SSL/TLS协议版本 ，如SSLv2 SSLv3 TLSv1;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ssl_protocols  SSLv3 TLSv1;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    #支持的协商算法\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ssl_ciphers  ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ssl_prefer_server_ciphers   on;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    # SSL证书位置\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ssl_certificate        /xxxx/xxxx/123.crt;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    ssl_certificate_key    /xxxx/xxxx/456.key;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   ################\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   其他配置略\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e   .....\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"自动转发http到https\"\u003e自动转发HTTP到HTTPS\u003c/h1\u003e\n\u003cp\u003e原理是rerwite规则，重定向到https，所以需要创建两个虚拟主机，一个http，一个https\u003c/p\u003e","title":"nginx 配置SSL证书"},{"content":"Windows10上遇到过ssh的坑，记录下过程\n参考 https://code.visualstudio.com/docs/remote/troubleshooting#_installing-a-supported-ssh-client\n环境和知识准备 远程主机，并开启ssh-server服务（通常端口22） Windows环境（本文Windwos10家庭版） Visual Studio Code 公钥加密算法，对SSH，通常为RSA 已经生成好的ssh公钥文件和私有文件 步骤 安装ssh-client 对于Windows10的一些版本，可以通过 设置--系统--应用和功能--管理可选功能--添加功能 来开启ssh-client，奈何本穷的Windows10不支持。\n还有两种方法来安装ssh-client\n通过PowerShell安装，以管理员方式启动PowerShell，具体参考 这里，反正本穷是没有成功。\n于是，只有通过安装Git for Windows来安装ssh-client了， 下载地址\n安装RemoteSSH 这里需要给Visual Studio Code 安装扩展包，以支持RemoteSSH。 Visual Studio Code -- 查看 --扩展,在扩展中搜索 Remote Development，然后安装这个扩展包，会自动安装相关依赖包。\n配置Vistual Studio Code SSH Visual Studio Code -- 设置，搜索SSH，在结果列表中找到 扩展--Remote-SSH -- Remote.SSH:Config File，自定义RemoteSSH的配置文件路径，然后创建这个配置文件，内容如下:\nHost 自定义别名 User 远程主机ssh登陆的用户名 HostName 远程主机名字，可以是ip地址 Port 远程主机ssh端口号，一般是22 IdentityFile 身份验证文件路径，即ssh私钥文件路径 访问 Vistual Studio Code \u0026ndash; 查看 \u0026ndash;命令面板 \u0026ndash;Remote-SSH：Connect ToHost\n选择配置文件中配置好的主机即可。\n","permalink":"https://blog.z6z8.cn/2019/09/21/windows10%EF%BC%9A%E9%85%8D%E7%BD%AEvisual-studio-code-%E4%BB%A5ssh%E6%96%B9%E5%BC%8F%E8%AE%BF%E9%97%AE%E8%BF%9C%E7%A8%8B%E4%B8%BB%E6%9C%BA/","summary":"\u003cp\u003eWindows10上遇到过ssh的坑，记录下过程\u003c/p\u003e\n\u003cp\u003e参考 \u003ca href=\"https://code.visualstudio.com/docs/remote/troubleshooting#_installing-a-supported-ssh-client\"\u003ehttps://code.visualstudio.com/docs/remote/troubleshooting#_installing-a-supported-ssh-client\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"环境和知识准备\"\u003e环境和知识准备\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003e远程主机，并开启ssh-server服务（通常端口22）\u003c/li\u003e\n\u003cli\u003eWindows环境（本文Windwos10家庭版）\u003c/li\u003e\n\u003cli\u003eVisual Studio Code\u003c/li\u003e\n\u003cli\u003e公钥加密算法，对SSH，通常为RSA\u003c/li\u003e\n\u003cli\u003e已经生成好的ssh公钥文件和私有文件\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"步骤\"\u003e步骤\u003c/h1\u003e\n\u003ch2 id=\"安装ssh-client\"\u003e安装ssh-client\u003c/h2\u003e\n\u003cp\u003e对于Windows10的一些版本，可以通过 \u003ccode\u003e设置--系统--应用和功能--管理可选功能--添加功能\u003c/code\u003e 来开启ssh-client，奈何本穷的Windows10不支持。\u003c/p\u003e\n\u003cp\u003e还有两种方法来安装ssh-client\u003c/p\u003e\n\u003cp\u003e通过PowerShell安装，以管理员方式启动PowerShell，具体参考 \u003ca href=\"https://docs.microsoft.com/zh-cn/windows-server/administration/openssh/openssh_install_firstuse\" title=\"这里\"\u003e这里\u003c/a\u003e，反正本穷是没有成功。\u003c/p\u003e\n\u003cp\u003e于是，只有通过安装Git for Windows来安装ssh-client了， \u003ca href=\"https://git-scm.com/download/win\" title=\"下载地址\"\u003e下载地址\u003c/a\u003e\u003c/p\u003e\n\u003ch2 id=\"安装remotessh\"\u003e安装RemoteSSH\u003c/h2\u003e\n\u003cp\u003e这里需要给Visual Studio Code 安装扩展包，以支持RemoteSSH。 \u003ccode\u003eVisual Studio Code -- 查看 --扩展\u003c/code\u003e,在扩展中搜索 \u003ccode\u003eRemote Development\u003c/code\u003e，然后安装这个扩展包，会自动安装相关依赖包。\u003c/p\u003e\n\u003ch2 id=\"配置vistual-studio-code-ssh\"\u003e配置Vistual Studio Code SSH\u003c/h2\u003e\n\u003cp\u003e\u003ccode\u003eVisual Studio Code -- 设置\u003c/code\u003e，搜索SSH，在结果列表中找到 \u003ccode\u003e扩展--Remote-SSH -- Remote.SSH:Config File\u003c/code\u003e，自定义RemoteSSH的配置文件路径，然后创建这个配置文件，内容如下:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eHost 自定义别名\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    User 远程主机ssh登陆的用户名\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    HostName 远程主机名字，可以是ip地址\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Port 远程主机ssh端口号，一般是22\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    IdentityFile 身份验证文件路径，即ssh私钥文件路径\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"访问\"\u003e访问\u003c/h2\u003e\n\u003cp\u003eVistual Studio Code \u0026ndash; 查看 \u0026ndash;命令面板 \u0026ndash;Remote-SSH：Connect ToHost\u003c/p\u003e\n\u003cp\u003e选择配置文件中配置好的主机即可。\u003c/p\u003e","title":"Windows10：配置Visual Studio Code 以SSH方式访问远程主机"},{"content":"/** * @param string $url * @return array */ function ParseQuery($url) { //按照？号切割 $tmpArr = explode(\u0026#34;?\u0026#34;,$url); //按照\u0026amp;号切割 （索引count($tmpArr) -1 ，和大部分语言保持一致，便于理解和移植） $queryParts = explode(\u0026#39;\u0026amp;\u0026#39;, $tmpArr[count($tmpArr) -1]); $ret = array(); foreach ($queryParts as $param) { $item = explode(\u0026#39;=\u0026#39;, $param); if(count($item) == 2){ $ret [$item[0]] = $item[1]; } } return $ret; } ","permalink":"https://blog.z6z8.cn/2019/09/19/%E4%BB%A3%E7%A0%81%E7%89%87%E6%AE%B5%EF%BC%9Aphp%E8%A7%A3%E6%9E%90url%E7%9A%84query%E5%8F%82%E6%95%B0/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e/**\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e * @param string $url\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e * @return array\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eParseQuery\u003c/span\u003e($url)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//按照？号切割\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    $tmpArr \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eexplode\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;?\u0026#34;\u003c/span\u003e,$url);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//按照\u0026amp;号切割  （索引count($tmpArr) -1 ，和大部分语言保持一致，便于理解和移植）\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    $queryParts \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eexplode\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;\u0026amp;\u0026#39;\u003c/span\u003e, $tmpArr[\u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e($tmpArr) \u003cspan style=\"color:#f92672\"\u003e-\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    $ret \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003earray\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eforeach\u003c/span\u003e ($queryParts \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e $param) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $item \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eexplode\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#39;=\u0026#39;\u003c/span\u003e, $param);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e(\u003cspan style=\"color:#a6e22e\"\u003ecount\u003c/span\u003e($item) \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $ret [$item[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e]] \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $item[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e $ret;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"代码片段：php解析url的query参数"},{"content":"\u0026lt;?php //大部分代码按照自己对算法导论的伪代码的理解编写 namespace zxszl; /* 红黑树的特性: （1）每个节点或者是黑色，或者是红色。 （2）根节点是黑色。 （3）每个叶节点（NIL）是黑色。 [注意：这里叶节点，是指为空(NIL或NULL)的子节点！] （4）如果一个节点是红色的，则它的子节点必须是黑色的。 （5）从一个节点到该节点的叶节点的所有路径上包含相同数目的黑节点。 */ //参考 https://blog.csdn.net/v_JULY_v/article/details/6105630 class RedBlackNode { public $parent;//父节点 public $left; //左子节点 public $right; //右子节点 public $isRed; //红色节点或者黑色节点 /** * 这里引入两个变量，是为了方便字典数据结构 * 其中，key作为红黑树的排序依据 */ public $key; //节点值 public $value; //节点值 public function __construct () { $this-\u0026gt;parent = null; $this-\u0026gt;left = null; $this-\u0026gt;right = null; $this-\u0026gt;isRed = true; $this-\u0026gt;key = null; $this-\u0026gt;value = null; } } /** * 红黑树 ，左边小节点，右边大节点 */ class RedBlackTree { /** * 深度（树高度） * @param RedBlackNode $node * @return int */ static public function depth($node) { if ($node === NULL) { return 0; } $left_d = RedBlackTree::depth($node-\u0026gt;left); $right_d = RedBlackTree::depth($node-\u0026gt;right); return ($left_d \u0026gt; $right_d ? $left_d : $right_d) + 1; } /** * 最小节点 * @return RedBlackNode 最小节点 */ static public function minNode($node) { $current = $node; if ($current !== null) { while ($current-\u0026gt;left !== null) { $current = $current-\u0026gt;left; } } return $current; } /** * 最大节点 * @return RedBlackNode 最大节点 */ static public function maxNode($node) { $current = $node; if ($current !== null) { while ($current-\u0026gt;right !== null) { $current = $current-\u0026gt;right; } } return $current; } /** * 查找指定节点 * @return RedBlackNode 节点 */ public function searchNode($key) { $current = $this-\u0026gt;rootNode; while ($current !== NULL) { if ($current-\u0026gt;key === $key) { return $current; } elseif ($current-\u0026gt;key \u0026gt; $key) { $current = $current-\u0026gt;left; } else { $current = $current-\u0026gt;right; } } return null; } /** * 插入节点，若$key已经存在，则替换对应节点的$value * @return RedBlackNode 插入的节点 */ public function insertNode($key,$value) { //查找节点插入时的父亲节点 $nodeParent = null; do { $tmp = $this-\u0026gt;rootNode; while ($tmp !== null) { $nodeParent = $tmp; if ($key === $tmp-\u0026gt;key ) {//已经存在key，不必再插入,只要替换value就可以 $tmp-\u0026gt;value = $value; return; } else if ( $key \u0026lt; $tmp-\u0026gt;key ) { $tmp = $tmp-\u0026gt;left; } else { $tmp = $tmp-\u0026gt;right; } } }while(0); //创建新节点,节点为红色 $node = new RedBlackNode(); // $node-\u0026gt;isRed = true; $node-\u0026gt;key = $key; $node-\u0026gt;value = $value; //插入节点 $node-\u0026gt;parent = $nodeParent; if ($nodeParent === null) { $this-\u0026gt;rootNode = $node; } else if ($node-\u0026gt;key \u0026lt; $nodeParent-\u0026gt;key) { $nodeParent-\u0026gt;left = $node; } else { $nodeParent-\u0026gt;right = $node; } //修正红黑树 $this-\u0026gt;p_insert_fixup($node); } /** * 删除节点 */ public function deleteNode ($key) { $z = $this-\u0026gt;searchNode($key); if ( $z !== null ) //找到$key对应的节点 { //$z //待删除节点 $y = null; $x = null; ///\u0026gt;\u0026gt;\u0026gt;START $z不为null，那么经过操作，$y一定不为null if ($z-\u0026gt;left === null || $z-\u0026gt;right === null) { $y = $z; } else { $y = RedBlackTree::minNode($z-\u0026gt;right); //$z的最小上限 } ///\u0026lt;\u0026lt;\u0026lt;END if ( $y-\u0026gt;left !== null ) { $x = $y-\u0026gt;left; } else { $x = $y-\u0026gt;right; } //删除节点$y if ($x !== null){ $x-\u0026gt;parent = $y-\u0026gt;parent; } if ($y-\u0026gt;parent === null ) { $this-\u0026gt;rootNode = $x; } else if ( $y === $y-\u0026gt;parent-\u0026gt;left ) { $y-\u0026gt;parent-\u0026gt;left = $x; } else { $y-\u0026gt;parent-\u0026gt;right = $x; } $xParent = $y-\u0026gt;parent; //如果$y不是$z，那么用$y的信息覆盖$z,这样达到删除$z的目的 if ($y !== $z) { $z-\u0026gt;key = $y-\u0026gt;key; $z-\u0026gt;value = $y-\u0026gt;value; } //如果删除的节点是黑色，则需要修正 if ($y-\u0026gt;isRed === false) {//$y可能是$z ,也可能是$z的最小上限 $this-\u0026gt;p_delete_fixup($x,$xParent); } } } /** * 修正红黑树 * @param RedBlackNode node 插入的节点 */ private function p_insert_fixup($node) { while ($node-\u0026gt;parent !== null \u0026amp;\u0026amp; $node-\u0026gt;parent-\u0026gt;isRed === true ) //如果node的父节点是红色 (node是红色) { $grandParent = $node-\u0026gt;parent-\u0026gt;parent; //祖父节点，一定存在 (根据红黑树性质，红色节点一定有父节点)) if ($node-\u0026gt;parent === $grandParent-\u0026gt;left ) { //node的父节点是左孩子 $uncle = $grandParent-\u0026gt;right; //case1：node的父节点是红色，且叔节点是红色 if ($uncle \u0026amp;\u0026amp; $uncle-\u0026gt;isRed === true ) { $uncle-\u0026gt;isRed = false; $node-\u0026gt;parent-\u0026gt;isRed = false; $grandParent-\u0026gt;isRed = true; $node = $grandParent; continue; //经过这一步之后，组父节点作为新节点存在（跳到case2） } //case2：node的父节点是红色,叔节点是黑色，node是其父节点的右孩子 else if ($node === $node-\u0026gt;parent-\u0026gt;right ) { $node = $node-\u0026gt;parent; $this-\u0026gt;p_left_rotate($node); } //case3：node的父节点是红色,叔节点是黑色，node是其父节点的左孩子 $node-\u0026gt;parent-\u0026gt;isRed = false; $grandParent-\u0026gt;isRed = true; $this-\u0026gt;p_right_rotate($grandParent); } else { //node的父节点是右孩子 $uncle = $grandParent-\u0026gt;left; //case1：node的父节点是红色，且叔节点是红色 if ($uncle \u0026amp;\u0026amp; $uncle-\u0026gt;isRed === true ) { $uncle-\u0026gt;isRed = false; $node-\u0026gt;parent-\u0026gt;isRed = false; $grandParent-\u0026gt;isRed = true; $node = $grandParent; continue; //经过这一步之后，组父节点作为新节点存在（跳到case2） } //case2：node的父节点是红色,叔节点是黑色，node是其父节点的左孩子 else if ($node === $node-\u0026gt;parent-\u0026gt;left ) { $node = $node-\u0026gt;parent; $this-\u0026gt;p_right_rotate($node); } //case3：node的父节点是红色,叔节点是黑色，node是其父节点的左孩子 $node-\u0026gt;parent-\u0026gt;isRed = false; $grandParent-\u0026gt;isRed = true; $this-\u0026gt;p_left_rotate($grandParent); } } $this-\u0026gt;rootNode-\u0026gt;isRed = false; } /** * 修正红黑树 * @param RedBlackNode $x * @param RedBlackNode $xParent */ private function p_delete_fixup($x,$xParent) { while ( $x !== $this-\u0026gt;rootNode \u0026amp;\u0026amp; ($x ===null || $x-\u0026gt;isRed === false ) ) { if ($x === $xParent-\u0026gt;left ) //$x不是根节点，那么$xParent一定存在 { $w = $xParent-\u0026gt;right; if ($w !== null ) //若为null，则$w黑色 { //case1：$x黑, 兄弟节点$w红，父节点黑 if ($w-\u0026gt;isRed === true ) { $w-\u0026gt;isRed = false; $xParent-\u0026gt;isRed = true; $this-\u0026gt;p_left_rotate($xParent); $w = $xParent-\u0026gt;right; //在左旋处理后，$xParent-\u0026gt;right指向的是原来兄弟结点$w的右孩子，黑色 } //case2：$x黑色， $w是黑色，且$w两个子节点都是黑色 if ( ($w-\u0026gt;left===null || $w-\u0026gt;left-\u0026gt;isRed === false) \u0026amp;\u0026amp; ($w-\u0026gt;right===null || $w-\u0026gt;right-\u0026gt;isRed === false) ) { $w-\u0026gt;isRed = true; $x = $xParent; $xParent = $x-\u0026gt;parent; } else { //case3：$x黑色，$w黑色，$w左子是红色，$w右子是黑色 if ( $w-\u0026gt;right===null || $w-\u0026gt;right-\u0026gt;isRed === false ) { $w-\u0026gt;left-\u0026gt;isRed = false; $w-\u0026gt;isRed = true; $this-\u0026gt;p_right_rotate($w); $w = $xParent-\u0026gt;right; } //case4：$x黑色，$w黑色，$w右子是红色，$w左子的颜色任意 $w-\u0026gt;isRed = $xParent-\u0026gt;isRed; $xParent-\u0026gt;isRed = false; if ($w-\u0026gt;right !== null ) { $w-\u0026gt;right-\u0026gt;isRed = false; } $this-\u0026gt;p_left_rotate($xParent); $x = $this-\u0026gt;rootNode; break;//加不加break都可以，因为下次循环条件不满足 } } } else //$x是右孩子 $x不是根节点，那么$xParent一定存在 { $w = $xParent-\u0026gt;left; if ($w !== null ) //若为null，则$w黑色 { //case1：$x黑, 兄弟节点$w红，父节点黑 if ($w-\u0026gt;isRed === true ) { $w-\u0026gt;isRed = false; $xParent-\u0026gt;isRed = true; $this-\u0026gt;p_right_rotate($xParent); $w = $xParent-\u0026gt;left; //在右旋处理后，$xParent-\u0026gt;left指向的是原来兄弟结点$w的左孩子，黑色 } //case2：$x黑色， $w是黑色，且$w两个子节点都是黑色 if ( ($w-\u0026gt;left===null || $w-\u0026gt;left-\u0026gt;isRed === false) \u0026amp;\u0026amp; ($w-\u0026gt;right===null || $w-\u0026gt;right-\u0026gt;isRed === false) ) { $w-\u0026gt;isRed = true; $x = $xParent; $xParent = $x-\u0026gt;parent; } else { //case3：$x黑色，$w黑色，$w左子是黑色，$w右子是红色 if ( $w-\u0026gt;left===null || $w-\u0026gt;left-\u0026gt;isRed === false ) { $w-\u0026gt;right-\u0026gt;isRed = false; $w-\u0026gt;isRed = true; $this-\u0026gt;p_left_rotate($w); $w = $xParent-\u0026gt;left; } //case4：$x黑色，$w黑色，$w左子是红色，$w右子的颜色任意 $w-\u0026gt;isRed = $xParent-\u0026gt;isRed; $xParent-\u0026gt;isRed = false; if ($w-\u0026gt;left !== null ) { $w-\u0026gt;left-\u0026gt;isRed = false; } $this-\u0026gt;p_right_rotate($xParent); $x = $this-\u0026gt;rootNode; break;//加不加break都可以，因为下次循环条件不满足 } } } } if ($x !== null ) { $x-\u0026gt;isRed = false; } } /** * 对指定节点进行左旋操作 * 左旋中的“左”，意味着“被旋转的节点将变成（自己右孩子的）一个左节点 * node right * / \\ / \\ * a right ======\u0026gt; node c * / \\ / \\ * b c a b * * @param RedBlackNode $node */ private function p_left_rotate($node) { $rightChild = $node-\u0026gt;right; //右孩子 if ($rightChild === null){ //右孩子为null，左旋结束 return; } $rightChild-\u0026gt;parent = $node-\u0026gt;parent; //将 “node的父亲” 设为 “rightChild的父亲” if ($rightChild-\u0026gt;parent === null) { //情况1：如果 “rightChild的父亲” 是空节点，则将rightChild设为根节点 $this-\u0026gt;rootNode = $rightChild; } else if ($node === $node-\u0026gt;parent-\u0026gt;left ) { //情况2：如果 node是它父节点的左孩子，则将rightChild设为“node的父节点的左孩子” $node-\u0026gt;parent-\u0026gt;left = $rightChild; } else { // 情况3：(node是它父节点的右孩子) 将rightChild设为“node的父节点的右孩子” $node-\u0026gt;parent-\u0026gt;right = $rightChild; } $node-\u0026gt;parent = $rightChild; //将 “node的父节点” 设为 “rightChild” $node-\u0026gt;right = $rightChild-\u0026gt;left; //将 “rightChild的左孩子” 设为 “node的右孩子” if ($rightChild-\u0026gt;left !== null) { $rightChild-\u0026gt;left-\u0026gt;parent = $node; //将 “node” 设为 “rightChild的左孩子的父亲” } $rightChild-\u0026gt;left = $node; //将 “node” 设为 “rightChild的左孩子” } /** * 对指定节点进行右旋操作 * 右旋中的“右”，意味着“被旋转的节点将变成（自己左孩子的）一个右节点” * left node * / \\ / \\ * a node \u0026lt;====== left c * / \\ / \\ * b c a b * * @param RedBlackNode $node */ private function p_right_rotate($node) { $leftChild = $node-\u0026gt;left; //左孩子 if ($leftChild === null) { //左孩子为null，右旋结束 return; } $leftChild-\u0026gt;parent = $node-\u0026gt;parent; //将 “node的父节点” 设为 “leftChild的父节点” if ($leftChild-\u0026gt;parent === null) { // 情况1：如果 “leftChild的父亲” 是空节点，则将leftChild设为根节点 $this-\u0026gt;rootNode = $leftChild; } else if ($node === $node-\u0026gt;parent-\u0026gt;left ) { // 情况2：如果 node 是它父节点的左孩子，则将leftChild设为“node的父节点的左孩子” $node-\u0026gt;parent-\u0026gt;left = $leftChild; } else { // 情况3：如果 node 是它父节点的右孩子，则将leftChild设为“node的父节点的右孩子” $node-\u0026gt;parent-\u0026gt;right = $leftChild; } $node-\u0026gt;parent = $leftChild; //将leftChild设为“node的父节点” $node-\u0026gt;left = $leftChild-\u0026gt;right; //将 “leftChild的右孩子” 设为\u0026#34;node的左孩子\u0026#34; if ( $leftChild-\u0026gt;right !== null ){ $leftChild-\u0026gt;right-\u0026gt;parent = $node; //将node 设为 “leftChild的右孩子的父节点” } $leftChild-\u0026gt;right = $node; //将 \u0026#34;node\u0026#34; 设为 “leftChild的右孩子” } private $rootNode; } $rbTree = new RedBlackTree(); $testN = 10000; function testInsert( $rbTree ) { global $testN; $tmpArray = array(); for ($i = 0 ; $i \u0026lt; $testN ; $i++) { array_push($tmpArray,$i); } shuffle($tmpArray); for ($i = 0 ; $i \u0026lt; $testN ; $i++) { $k = $tmpArray[$i]; $rbTree-\u0026gt;insertNode($k,$k); } for ($i = 0 ; $i \u0026lt; $testN ; $i++) { $node = $rbTree-\u0026gt;searchNode($i); if($node === null) { echo \u0026#34;not found $i\u0026#34;; } else if ($node-\u0026gt;value !== $i ) { $value = $node-\u0026gt;value; echo \u0026#34;found $i,but value is $value\u0026#34;; } } } function testDelete( $rbTree ) { global $testN; $tmpArray = array(); for ($i = 0 ; $i \u0026lt; $testN ; $i++) { array_push($tmpArray,$i); } shuffle($tmpArray); for ($i = 0 ; $i \u0026lt; $testN ; $i++) { $k = $tmpArray[$i]; $rbTree-\u0026gt;deleteNode($k); } for ($i = 0 ; $i \u0026lt; $testN ; $i++) { $node = $rbTree-\u0026gt;searchNode($i); if($node !== null) { echo \u0026#34;found $i\u0026#34;; } } } testInsert($rbTree); testDelete($rbTree); ","permalink":"https://blog.z6z8.cn/2019/09/17/%E7%BA%A2%E9%BB%91%E6%A0%91%E5%AE%9E%E7%8E%B0-php%E7%89%88%E6%9C%AC/","summary":"\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;?\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ephp\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//大部分代码按照自己对算法导论的伪代码的理解编写\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003enamespace\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ezxszl\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e/*\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e红黑树的特性:\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e（1）每个节点或者是黑色，或者是红色。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e（2）根节点是黑色。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e（3）每个叶节点（NIL）是黑色。 [注意：这里叶节点，是指为空(NIL或NULL)的子节点！]\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e（4）如果一个节点是红色的，则它的子节点必须是黑色的。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e（5）从一个节点到该节点的叶节点的所有路径上包含相同数目的黑节点。\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e*/\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//参考 https://blog.csdn.net/v_JULY_v/article/details/6105630\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eRedBlackNode\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e $parent;\u003cspan style=\"color:#75715e\"\u003e//父节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e $left; \u003cspan style=\"color:#75715e\"\u003e//左子节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e $right; \u003cspan style=\"color:#75715e\"\u003e//右子节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e $isRed; \u003cspan style=\"color:#75715e\"\u003e//红色节点或者黑色节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e/**\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * 这里引入两个变量，是为了方便字典数据结构\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * 其中，key作为红黑树的排序依据\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e $key; \u003cspan style=\"color:#75715e\"\u003e//节点值\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e $value; \u003cspan style=\"color:#75715e\"\u003e//节点值\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003e__construct\u003c/span\u003e ()\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e/**\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e * 红黑树 ，左边小节点，右边大节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003eclass\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eRedBlackTree\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e{\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#e6db74\"\u003e/**\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * 深度（树高度）\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * @param RedBlackNode $node\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * @return int\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edepth\u003c/span\u003e($node)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($node \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eNULL\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $left_d \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eRedBlackTree\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003edepth\u003c/span\u003e($node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $right_d \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eRedBlackTree\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003edepth\u003c/span\u003e($node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e ($left_d \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e $right_d \u003cspan style=\"color:#f92672\"\u003e?\u003c/span\u003e $left_d \u003cspan style=\"color:#f92672\"\u003e:\u003c/span\u003e $right_d) \u003cspan style=\"color:#f92672\"\u003e+\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e/**\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * 最小节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * @return RedBlackNode 最小节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eminNode\u003c/span\u003e($node)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $current \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($current \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e ($current\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $current \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $current\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e $current;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e/**\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * 最大节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * @return RedBlackNode 最大节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003estatic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003emaxNode\u003c/span\u003e($node)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $current \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($current \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e ($current\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $current \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $current\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e $current;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e/**\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * 查找指定节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * @return RedBlackNode 节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003esearchNode\u003c/span\u003e($key)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $current \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erootNode\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e ($current \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eNULL\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($current\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e $key) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e $current;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            } \u003cspan style=\"color:#66d9ef\"\u003eelseif\u003c/span\u003e ($current\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026gt;\u003c/span\u003e $key) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $current \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $current\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            } \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $current \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $current\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e/**\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * 插入节点，若$key已经存在，则替换对应节点的$value\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * @return RedBlackNode 插入的节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003einsertNode\u003c/span\u003e($key,$value)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e//查找节点插入时的父亲节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        $nodeParent \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003edo\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $tmp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erootNode\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e ($tmp \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $nodeParent \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $tmp;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($key \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e $tmp\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e ) {\u003cspan style=\"color:#75715e\"\u003e//已经存在key，不必再插入,只要替换value就可以\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    $tmp\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $value;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( $key \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e $tmp\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    $tmp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $tmp\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    $tmp \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $tmp\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e(\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e//创建新节点,节点为红色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        $node \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eRedBlackNode\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e// $node-\u0026gt;isRed = true;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $key;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $value;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e//插入节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $nodeParent;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($nodeParent \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erootNode\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e $nodeParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $nodeParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $nodeParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e//修正红黑树\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ep_insert_fixup\u003c/span\u003e($node);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e/**\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * 删除节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003epublic\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003edeleteNode\u003c/span\u003e ($key) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $z \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003esearchNode\u003c/span\u003e($key);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( $z \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e ) \u003cspan style=\"color:#75715e\"\u003e//找到$key对应的节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        {   \u003cspan style=\"color:#75715e\"\u003e//$z //待删除节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            $y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e///\u0026gt;\u0026gt;\u0026gt;START $z不为null，那么经过操作，$y一定不为null\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($z\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e $z\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $z;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            } \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $y \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eRedBlackTree\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e::\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eminNode\u003c/span\u003e($z\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e); \u003cspan style=\"color:#75715e\"\u003e//$z的最小上限\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e///\u0026lt;\u0026lt;\u0026lt;END\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( $y\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $y\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            } \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $y\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e//删除节点$y\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($x \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $x\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $y\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($y\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erootNode\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $x;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( $y \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e $y\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $y\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $x;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $y\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $x;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $xParent \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $y\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e//如果$y不是$z，那么用$y的信息覆盖$z,这样达到删除$z的目的\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($y \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e $z) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $z\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $y\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ekey\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $z\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $y\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e//如果删除的节点是黑色，则需要修正\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($y\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e) {\u003cspan style=\"color:#75715e\"\u003e//$y可能是$z ,也可能是$z的最小上限\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ep_delete_fixup\u003c/span\u003e($x,$xParent);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e/**\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * 修正红黑树\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * @param RedBlackNode node 插入的节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ep_insert_fixup\u003c/span\u003e($node)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e ($node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e ) \u003cspan style=\"color:#75715e\"\u003e//如果node的父节点是红色 (node是红色)\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $grandParent \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e//祖父节点，一定存在 (根据红黑树性质，红色节点一定有父节点))\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e $grandParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e ) { \u003cspan style=\"color:#75715e\"\u003e//node的父节点是左孩子\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                $uncle \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $grandParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e//case1：node的父节点是红色，且叔节点是红色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($uncle \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e $uncle\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    $uncle\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    $grandParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    $node \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $grandParent;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003econtinue\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e//经过这一步之后，组父节点作为新节点存在（跳到case2）\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e//case2：node的父节点是红色,叔节点是黑色，node是其父节点的右孩子\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($node \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    $node \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ep_left_rotate\u003c/span\u003e($node);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e//case3：node的父节点是红色,叔节点是黑色，node是其父节点的左孩子\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $grandParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ep_right_rotate\u003c/span\u003e($grandParent);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e { \u003cspan style=\"color:#75715e\"\u003e//node的父节点是右孩子\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                $uncle \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $grandParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e//case1：node的父节点是红色，且叔节点是红色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($uncle \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e $uncle\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    $uncle\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    $grandParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    $node \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $grandParent;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003econtinue\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e//经过这一步之后，组父节点作为新节点存在（跳到case2）\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e//case2：node的父节点是红色,叔节点是黑色，node是其父节点的左孩子\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($node \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    $node \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ep_right_rotate\u003c/span\u003e($node);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#75715e\"\u003e//case3：node的父节点是红色,叔节点是黑色，node是其父节点的左孩子\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $grandParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ep_left_rotate\u003c/span\u003e($grandParent);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erootNode\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e/**\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * 修正红黑树\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * @param RedBlackNode $x\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * @param RedBlackNode $xParent\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ep_delete_fixup\u003c/span\u003e($x,$xParent)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003ewhile\u003c/span\u003e ( $x \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erootNode\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e ($x \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e $x\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e ) )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($x \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e $xParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e ) \u003cspan style=\"color:#75715e\"\u003e//$x不是根节点，那么$xParent一定存在\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $w \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $xParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($w \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e ) \u003cspan style=\"color:#75715e\"\u003e//若为null，则$w黑色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#75715e\"\u003e//case1：$x黑, 兄弟节点$w红，父节点黑\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $xParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ep_left_rotate\u003c/span\u003e($xParent);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $w \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $xParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e//在左旋处理后，$xParent-\u0026gt;right指向的是原来兄弟结点$w的右孩子，黑色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#75715e\"\u003e//case2：$x黑色， $w是黑色，且$w两个子节点都是黑色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( ($w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e ($w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e) )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $xParent;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $xParent \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $x\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#75715e\"\u003e//case3：$x黑色，$w黑色，$w左子是红色，$w右子是黑色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ep_right_rotate\u003c/span\u003e($w);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            $w \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $xParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#75715e\"\u003e//case4：$x黑色，$w黑色，$w右子是红色，$w左子的颜色任意\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                        $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $xParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $xParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ep_left_rotate\u003c/span\u003e($xParent);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erootNode\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\u003cspan style=\"color:#75715e\"\u003e//加不加break都可以，因为下次循环条件不满足\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#75715e\"\u003e//$x是右孩子  $x不是根节点，那么$xParent一定存在\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                $w \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $xParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($w \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e ) \u003cspan style=\"color:#75715e\"\u003e//若为null，则$w黑色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#75715e\"\u003e//case1：$x黑, 兄弟节点$w红，父节点黑\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $xParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ep_right_rotate\u003c/span\u003e($xParent);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $w \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $xParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e//在右旋处理后，$xParent-\u0026gt;left指向的是原来兄弟结点$w的左孩子，黑色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#75715e\"\u003e//case2：$x黑色， $w是黑色，且$w两个子节点都是黑色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( ($w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            \u003cspan style=\"color:#f92672\"\u003e\u0026amp;\u0026amp;\u003c/span\u003e ($w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e) )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $xParent;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $xParent \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $x\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#75715e\"\u003e//case3：$x黑色，$w黑色，$w左子是黑色，$w右子是红色\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e||\u003c/span\u003e $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003etrue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ep_left_rotate\u003c/span\u003e($w);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            $w \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $xParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#75715e\"\u003e//case4：$x黑色，$w黑色，$w左子是红色，$w右子的颜色任意\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                        $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $xParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $xParent\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                            $w\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ep_right_rotate\u003c/span\u003e($xParent);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        $x \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erootNode\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                        \u003cspan style=\"color:#66d9ef\"\u003ebreak\u003c/span\u003e;\u003cspan style=\"color:#75715e\"\u003e//加不加break都可以，因为下次循环条件不满足\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e                    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e                }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($x \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $x\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eisRed\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efalse\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e/**\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * 对指定节点进行左旋操作\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * 左旋中的“左”，意味着“被旋转的节点将变成（自己右孩子的）一个左节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     *      node                  right\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     *      /  \\                  /  \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     *     a  right   ======\u0026gt;   node  c\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     *        /  \\              /  \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     *       b    c            a    b\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     *\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * @param RedBlackNode $node\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ep_left_rotate\u003c/span\u003e($node)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $rightChild \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e//右孩子\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($rightChild \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e//右孩子为null，左旋结束\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $rightChild\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e//将 “node的父亲” 设为 “rightChild的父亲”\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($rightChild\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e//情况1：如果 “rightChild的父亲” 是空节点，则将rightChild设为根节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erootNode\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $rightChild;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($node \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e//情况2：如果 node是它父节点的左孩子，则将rightChild设为“node的父节点的左孩子”\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $rightChild;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// 情况3：(node是它父节点的右孩子) 将rightChild设为“node的父节点的右孩子”\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $rightChild;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $rightChild; \u003cspan style=\"color:#75715e\"\u003e//将 “node的父节点” 设为 “rightChild”\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $rightChild\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e;    \u003cspan style=\"color:#75715e\"\u003e//将 “rightChild的左孩子” 设为 “node的右孩子”\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($rightChild\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $rightChild\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node;   \u003cspan style=\"color:#75715e\"\u003e//将 “node” 设为 “rightChild的左孩子的父亲”\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $rightChild\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node; \u003cspan style=\"color:#75715e\"\u003e//将 “node” 设为 “rightChild的左孩子”\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#e6db74\"\u003e/**\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * 对指定节点进行右旋操作\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * 右旋中的“右”，意味着“被旋转的节点将变成（自己左孩子的）一个右节点”\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     *      left                  node\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     *      /  \\                  /  \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     *     a  node   \u0026lt;======    left  c\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     *        /  \\              /  \\\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     *       b    c            a    b\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     *\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     * @param RedBlackNode $node\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#e6db74\"\u003e     */\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ep_right_rotate\u003c/span\u003e($node)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $leftChild \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e//左孩子\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($leftChild \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e//左孩子为null，右旋结束\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            \u003cspan style=\"color:#66d9ef\"\u003ereturn\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $leftChild\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e//将 “node的父节点” 设为 “leftChild的父节点”\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($leftChild\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// 情况1：如果 “leftChild的父亲” 是空节点，则将leftChild设为根节点\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            $this\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003erootNode\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $leftChild;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($node \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// 情况2：如果 node 是它父节点的左孩子，则将leftChild设为“node的父节点的左孩子”\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $leftChild;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            \u003cspan style=\"color:#75715e\"\u003e// 情况3：如果 node 是它父节点的右孩子，则将leftChild设为“node的父节点的右孩子”\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e            $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $leftChild;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $leftChild; \u003cspan style=\"color:#75715e\"\u003e//将leftChild设为“node的父节点”\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eleft\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $leftChild\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e; \u003cspan style=\"color:#75715e\"\u003e//将 “leftChild的右孩子” 设为\u0026#34;node的左孩子\u0026#34;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ( $leftChild\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e ){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e            $leftChild\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eparent\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node; \u003cspan style=\"color:#75715e\"\u003e//将node 设为 “leftChild的右孩子的父节点”\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e        }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $leftChild\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eright\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node;   \u003cspan style=\"color:#75715e\"\u003e//将 \u0026#34;node\u0026#34; 设为 “leftChild的右孩子”\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eprivate\u003c/span\u003e $rootNode;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e $rbTree \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eRedBlackTree\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e $testN \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e10000\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etestInsert\u003c/span\u003e( $rbTree )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003eglobal\u003c/span\u003e $testN;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     $tmpArray \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003earray\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e ($i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; $i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e $testN ; $i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         \u003cspan style=\"color:#a6e22e\"\u003earray_push\u003c/span\u003e($tmpArray,$i);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#a6e22e\"\u003eshuffle\u003c/span\u003e($tmpArray);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e ($i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; $i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e $testN ; $i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         $k \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $tmpArray[$i];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         $rbTree\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003einsertNode\u003c/span\u003e($k,$k);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e ($i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; $i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e $testN ; $i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         $node \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $rbTree\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003esearchNode\u003c/span\u003e($i);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e($node \u003cspan style=\"color:#f92672\"\u003e===\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e             \u003cspan style=\"color:#66d9ef\"\u003eecho\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;not found \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e$i\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e $i ) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e             $value \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $node\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003evalue\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e             \u003cspan style=\"color:#66d9ef\"\u003eecho\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;found \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e$i\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e,but value is \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e$value\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003etestDelete\u003c/span\u003e( $rbTree )\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003eglobal\u003c/span\u003e $testN;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     $tmpArray \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003earray\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e ($i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; $i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e $testN ; $i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         \u003cspan style=\"color:#a6e22e\"\u003earray_push\u003c/span\u003e($tmpArray,$i);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#a6e22e\"\u003eshuffle\u003c/span\u003e($tmpArray);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e ($i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; $i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e $testN ; $i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         $k \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $tmpArray[$i];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         $rbTree\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003edeleteNode\u003c/span\u003e($k);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     \u003cspan style=\"color:#66d9ef\"\u003efor\u003c/span\u003e ($i \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e ; $i \u003cspan style=\"color:#f92672\"\u003e\u0026lt;\u003c/span\u003e $testN ; $i\u003cspan style=\"color:#f92672\"\u003e++\u003c/span\u003e)\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         $node \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e $rbTree\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003esearchNode\u003c/span\u003e($i);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e($node \u003cspan style=\"color:#f92672\"\u003e!==\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enull\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e             \u003cspan style=\"color:#66d9ef\"\u003eecho\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;found \u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e$i\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e         }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e     }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#a6e22e\"\u003etestInsert\u003c/span\u003e($rbTree);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e \u003cspan style=\"color:#a6e22e\"\u003etestDelete\u003c/span\u003e($rbTree);\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"红黑树实现 --php版本"},{"content":"用PHP PDO打开数据库，出现错误\ncould not find driver 一个原因是没安装对应的PDO\n解决方法\n#查看php版本 $ php -v #安装PDO sudo apt-get install php7.3-mysql sudo apt-get install php7.3-pgsql sudo apt-get install php7.3-sqlite ","permalink":"https://blog.z6z8.cn/2019/09/13/ubuntu18-04-php-pdo-could-not-find-driver/","summary":"\u003cp\u003e用PHP PDO打开数据库，出现错误\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecould not find driver\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e一个原因是没安装对应的PDO\u003c/p\u003e\n\u003cp\u003e解决方法\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#查看php版本\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ php -v\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#安装PDO\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get install php7.3-mysql\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get install php7.3-pgsql\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get install php7.3-sqlite\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"ubuntu18.04 php pdo : could not find driver"},{"content":"创建工程 需要先安装 Phalcon DevTools\n创建Test工程\nphalcon project Test 然后，只保留四个文件 Test\\.htaccess (访问权限控制) Test\\.htrouter.php(访问路由) Test\\public\\.htaccess(访问权限控制) Test\\public\\index.php(应用入口)\n一个简单微应用的示例 将 Test\\public\\index.php 的内容修改成:\n\u0026lt;?php //导入Micro use Phalcon\\Mvc\\Micro; //创建对象 $app = new Micro(); //注册路由 //GET方法，路径为 /xxxx , 响应输出 hello xxxx $app-\u0026gt;get(\u0026#34;/{name}\u0026#34;, //响应方法 function ($name){ echo \u0026#34;hello \u0026#34; . $name; }); $app-\u0026gt;handle(); 进入 Test 目录，开启服务\nphalcon serve 默认情况下开启的是8000端口，用浏览器访问 http://127.0.0.1:8000/world 应能看到输出\nhello world 进一步，自定义微应用的路由 微应用使用起来很简单，我们可以在这基础上抽象出自定义的路由（这里，仅仅是演示示意，不代表一定这么做），即把 $app-\u0026gt;getxxxx 这段拆开，定义一个路由表\n\u0026lt;?php use Phalcon\\Mvc\\Micro; function func_test($name){ echo \u0026#34;hello \u0026#34; . $name; } //定义路由 $route_list = [ //GET方发 路径/xxxx 响应函数func_test [\u0026#34;GET\u0026#34;, \u0026#34;/{name}\u0026#34;, \u0026#34;func_test\u0026#34;], ]; $app = new Micro(); //注册路由 foreach ($route_list as $item) { if ($item[0] == \u0026#34;GET\u0026#34;) { $app-\u0026gt;get($item[1],$item[2]); } else { //错误处理; } } $app-\u0026gt;handle(); 再次用浏览器访问 http://127.0.0.1:8000/world，看看效果\n","permalink":"https://blog.z6z8.cn/2019/09/12/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9Aphalcon-%E5%BE%AE%E5%BA%94%E7%94%A8%E7%A4%BA%E4%BE%8B/","summary":"\u003ch1 id=\"创建工程\"\u003e创建工程\u003c/h1\u003e\n\u003cp\u003e需要先安装 \u003ccode\u003ePhalcon DevTools\u003c/code\u003e\u003c/p\u003e\n\u003cp\u003e创建Test工程\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ephalcon project Test\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e然后，只保留四个文件\n\u003ccode\u003eTest\\.htaccess\u003c/code\u003e (访问权限控制)\n\u003ccode\u003eTest\\.htrouter.php\u003c/code\u003e(访问路由)\n\u003ccode\u003eTest\\public\\.htaccess\u003c/code\u003e(访问权限控制)\n\u003ccode\u003eTest\\public\\index.php\u003c/code\u003e(应用入口)\u003c/p\u003e\n\u003ch1 id=\"一个简单微应用的示例\"\u003e一个简单微应用的示例\u003c/h1\u003e\n\u003cp\u003e将 \u003ccode\u003eTest\\public\\index.php\u003c/code\u003e 的内容修改成:\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;?\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ephp\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//导入Micro\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003euse\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePhalcon\\Mvc\\Micro\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//创建对象\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e$app \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMicro\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//注册路由\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//GET方法，路径为 /xxxx , 响应输出 hello  xxxx\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e$app\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eget\u003c/span\u003e(\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/{name}\u0026#34;\u003c/span\u003e,\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e  \u003cspan style=\"color:#75715e\"\u003e//响应方法\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    \u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e ($name){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#66d9ef\"\u003eecho\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hello  \u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e $name;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    });\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$app\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ehandle\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e进入 \u003ccode\u003eTest\u003c/code\u003e 目录，开启服务\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ephalcon serve\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e默认情况下开启的是8000端口，用浏览器访问 \u003ccode\u003ehttp://127.0.0.1:8000/world\u003c/code\u003e\n应能看到输出\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-text\" data-lang=\"text\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ehello world\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"进一步自定义微应用的路由\"\u003e进一步，自定义微应用的路由\u003c/h1\u003e\n\u003cp\u003e微应用使用起来很简单，我们可以在这基础上抽象出自定义的路由（这里，仅仅是演示示意，不代表一定这么做），即把 \u003ccode\u003e$app-\u0026gt;getxxxx\u003c/code\u003e 这段拆开，定义一个路由表\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-php\" data-lang=\"php\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#f92672\"\u003e\u0026lt;?\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ephp\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003euse\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003ePhalcon\\Mvc\\Micro\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#66d9ef\"\u003efunction\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003efunc_test\u003c/span\u003e($name){\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eecho\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;hello  \u0026#34;\u003c/span\u003e \u003cspan style=\"color:#f92672\"\u003e.\u003c/span\u003e $name;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//定义路由\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e$route_list \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e [\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#75715e\"\u003e//GET方发  路径/xxxx  响应函数func_test\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    [\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;GET\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;/{name}\u0026#34;\u003c/span\u003e, \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;func_test\u0026#34;\u003c/span\u003e],\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e];\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$app \u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e \u003cspan style=\"color:#66d9ef\"\u003enew\u003c/span\u003e \u003cspan style=\"color:#a6e22e\"\u003eMicro\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e//注册路由\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003eforeach\u003c/span\u003e ($route_list \u003cspan style=\"color:#66d9ef\"\u003eas\u003c/span\u003e $item) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eif\u003c/span\u003e ($item[\u003cspan style=\"color:#ae81ff\"\u003e0\u003c/span\u003e] \u003cspan style=\"color:#f92672\"\u003e==\u003c/span\u003e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;GET\u0026#34;\u003c/span\u003e) {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        $app\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003eget\u003c/span\u003e($item[\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e],$item[\u003cspan style=\"color:#ae81ff\"\u003e2\u003c/span\u003e]);\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    \u003cspan style=\"color:#66d9ef\"\u003eelse\u003c/span\u003e {\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e        \u003cspan style=\"color:#75715e\"\u003e//错误处理;\n\u003c/span\u003e\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e\u003c/span\u003e    }\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e}\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$app\u003cspan style=\"color:#f92672\"\u003e-\u0026gt;\u003c/span\u003e\u003cspan style=\"color:#a6e22e\"\u003ehandle\u003c/span\u003e();\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e再次用浏览器访问 \u003ccode\u003ehttp://127.0.0.1:8000/world\u003c/code\u003e，看看效果\u003c/p\u003e","title":"学习笔记：Phalcon 微应用示例"},{"content":"官方没有找到很好的支持（Phalcon只有一个对PhpStorm的支持），想到一个折中方案 下载https://github.com/phalcon/ide-stubs.git 把src目录下面的Phalcon目录整体复制到Phalcon的工程目录中\n然后在VS Code中安装扩展插件 PHP Intelephense\n","permalink":"https://blog.z6z8.cn/2019/09/11/vs-code-%E5%AF%B9-phalcon%E7%9A%84%E8%AF%AD%E6%B3%95%E8%87%AA%E5%8A%A8%E8%A1%A5%E5%85%A8/","summary":"\u003cp\u003e官方没有找到很好的支持（Phalcon只有一个对PhpStorm的支持），想到一个折中方案\n下载https://github.com/phalcon/ide-stubs.git\n把src目录下面的Phalcon目录整体复制到Phalcon的工程目录中\u003c/p\u003e\n\u003cp\u003e\u003cimg loading=\"lazy\" src=\"/wp-content/uploads/2019/09/%E5%B1%8F%E5%B9%95%E5%BF%AB%E7%85%A7-2019-09-11-%E4%B8%8B%E5%8D%881.54.44.png%22\"\u003e\u003c/p\u003e\n\u003cp\u003e然后在VS Code中安装扩展插件 PHP Intelephense\u003c/p\u003e","title":"VS Code 对 Phalcon的语法自动补全"},{"content":"安装homebrew方法（若已经安装，忽略）\n/usr/bin/ruby -e \u0026#34;$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)\u0026#34; 通过homebrew安装\nbrew install php@7.3 刷新php连接\nbrew link php@7.3 重启shell，查看php版本\nphp -v ","permalink":"https://blog.z6z8.cn/2019/09/10/mac-os-%E5%AE%89%E8%A3%85php7-3/","summary":"\u003cp\u003e安装homebrew方法（若已经安装，忽略）\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e/usr/bin/ruby -e \u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003ecurl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install\u003cspan style=\"color:#66d9ef\"\u003e)\u003c/span\u003e\u003cspan style=\"color:#e6db74\"\u003e\u0026#34;\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e通过homebrew安装\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebrew install php@7.3\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e刷新php连接\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ebrew link php@7.3\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e重启shell，查看php版本\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ephp -v\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"mac OS 安装php7.3"},{"content":"默认情况下，ssh会默认读取 ~/.ssh/id_rsa 验证信息（私钥文件），如何指定特定的验证信息呢？\nssh shell 指定验证信息文件 此方法适用于支持ssh shell访问的服务\nssh -i 私钥文件路径 git@xxxxx.com 启用config文件 参考 https://linux.die.net/man/5/ssh_config\n此方法可以为不同的域名指定不同的验证信息；在git服务支持的情况下，还可以为不同的git仓库指定不同的验证信息\n1、创建config文件\nvim ~/.ssh/config 内容如下\n#仓库A的验证信息（也可以是指定域名的验证信息） Host 名字A HostName 域名或者ip地址 User 用户名 IdentityFile 私钥文件路径 # Host 名字B HostName 域名或者ip地址 User 用户名 Port 22 IdentityFile 私钥文件路径 2、ssh 访问git仓库\n以clone为例，访问名字A对应的仓库\ngit clone git@名字A:xxx/xxx/repo.git ssh会根据 名字A 找到config文件中对应的验证信息进行验证\n","permalink":"https://blog.z6z8.cn/2019/09/10/gitssh%EF%BC%9A%E4%B8%BA%E4%BB%93%E5%BA%93%E6%88%96%E5%9F%9F%E5%90%8D%E6%8C%87%E5%AE%9Assh%E9%AA%8C%E8%AF%81%E4%BF%A1%E6%81%AF/","summary":"\u003cp\u003e默认情况下，ssh会默认读取 \u003ccode\u003e~/.ssh/id_rsa\u003c/code\u003e 验证信息（私钥文件），如何指定特定的验证信息呢？\u003c/p\u003e\n\u003ch1 id=\"ssh-shell-指定验证信息文件\"\u003essh shell 指定验证信息文件\u003c/h1\u003e\n\u003cp\u003e此方法适用于支持ssh shell访问的服务\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003essh -i 私钥文件路径  git@xxxxx.com\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"启用config文件\"\u003e启用config文件\u003c/h1\u003e\n\u003cp\u003e参考 \u003ca href=\"https://linux.die.net/man/5/ssh_config\"\u003ehttps://linux.die.net/man/5/ssh_config\u003c/a\u003e\u003c/p\u003e\n\u003cp\u003e此方法可以为不同的域名指定不同的验证信息；在git服务支持的情况下，还可以为不同的git仓库指定不同的验证信息\u003c/p\u003e\n\u003cp\u003e1、创建config文件\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003evim ~/.ssh/config\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e内容如下\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#仓库A的验证信息（也可以是指定域名的验证信息）\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eHost 名字A\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    HostName 域名或者ip地址\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    User 用户名\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    IdentityFile 私钥文件路径\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003eHost 名字B\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    HostName 域名或者ip地址\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    User 用户名\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    Port 22\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e    IdentityFile 私钥文件路径\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e2、ssh 访问git仓库\u003c/p\u003e\n\u003cp\u003e以clone为例，访问名字A对应的仓库\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone git@名字A:xxx/xxx/repo.git\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003essh会根据 \u003ccode\u003e名字A\u003c/code\u003e 找到config文件中对应的验证信息进行验证\u003c/p\u003e","title":"git+ssh：为仓库或域名指定ssh验证信息"},{"content":"参考连接 1、 https://docs.phalcon.io/3.4/en/installation 2、 http://phalcondoc.p2hp.com/zh/3.4 3、 https://github.com/phalcon/phalcon-devtools\n最终环境 ubuntu 18.04.1 nginx 1.14.0 (Ubuntu) php7.3 和 php7.3-fpm phalcon3.4.4-1 安装nginx 如果已经安装，请忽略\nsudo apt-get install nginx 安装php和php-fpm 如果已经安装，请忽略\n添加php源\nsudo apt-add-repository ppa:ondrej/php sudo apt-get update 安装\n#安装php7.3 sudo apt-get install php7.3 #安装php-fpm sudo apt-get install php-fpm 安装phalcon sudo apt-get install php7.3-phalcon 重启php-fpm 这个步骤是要把phalcon模块注册到php-fpm\nsudo systemctl reload php7.3-fpm.service 安装phalcon-devtools（脚手架） 从git安装\n#下载 git clone --depth=1 https://github.com/phalcon/phalcon-devtools.git #进入目录 cd phalcon-devtools/ #创建软连接 sudo ln -s $(pwd)/phalcon /usr/bin/phalcon #修改权限 sudo chmod ugo+x /usr/bin/phalcon #执行命令，查看是否安装成功 phalcon commands help 如果提示 \u0026quot;phalcon: command not found\u0026quot; 尝试命令\nsudo alias phalcon=git仓库下载目录/phalcon-devtools/phalcon 用phalcon-devtools创建一个phalcon项目 phalcon create-project test 配置虚拟主机（web服务） 进入 /etc/nginx/sites-available ,创建一个nginx虚拟主机服务test.conf\nsudo vim /etc/nginx/sites-available/test.conf 内容如下\nserver { #端口 listen 8080; #域名或IP地址均可 server_name default; # 注意路径为使用phalcon-devtools创建后的路径，包括public目录 root phalcon工程目录/test/public; index index.php index.html index.htm; charset utf-8; client_max_body_size 1M; fastcgi_read_timeout 1800; # Represents the root of the domain # http://localhost:8000/[index.php] location / { # Matches URLS `$_GET[\u0026#39;_url\u0026#39;]` try_files $uri $uri/ /index.php?_url=$uri\u0026amp;$args; } # When the HTTP request does not match the above # and the file ends in .php location ~ [^/]\\.php(/|$) { # try_files $uri =404; #unix socket 路径参见 /etc/php/7.3/fpm/pool.d/www.conf fastcgi_pass unix:/run/php/php7.3-fpm.sock; fastcgi_index /index.php; include fastcgi_params; fastcgi_split_path_info ^(.+?\\.php)(/.*)$; if (!-f $document_root$fastcgi_script_name) { return 404; } fastcgi_param PATH_INFO $fastcgi_path_info; # fastcgi_param PATH_TRANSLATED $document_root$fastcgi_path_info; # and set php.ini cgi.fix_pathinfo=0 fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; } location ~ /\\.ht { deny all; } location ~* \\.(js|css|png|jpg|jpeg|gif|ico)$ { expires max; log_not_found off; access_log off; } } 好了，用浏览器打开http://servername:8080 看看\n","permalink":"https://blog.z6z8.cn/2019/09/09/%E9%83%A8%E7%BD%B2ubuntu-nginx-php-fpm-phalcon/","summary":"\u003cp\u003e参考连接\n1、 \u003ca href=\"https://docs.phalcon.io/3.4/en/installation\"\u003ehttps://docs.phalcon.io/3.4/en/installation\u003c/a\u003e\n2、 \u003ca href=\"http://phalcondoc.p2hp.com/zh/3.4\"\u003ehttp://phalcondoc.p2hp.com/zh/3.4\u003c/a\u003e\n3、 \u003ca href=\"https://github.com/phalcon/phalcon-devtools\"\u003ehttps://github.com/phalcon/phalcon-devtools\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"最终环境\"\u003e最终环境\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003eubuntu 18.04.1\u003c/li\u003e\n\u003cli\u003enginx 1.14.0 (Ubuntu)\u003c/li\u003e\n\u003cli\u003ephp7.3 和 php7.3-fpm\u003c/li\u003e\n\u003cli\u003ephalcon3.4.4-1\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"安装nginx\"\u003e安装nginx\u003c/h1\u003e\n\u003cp\u003e如果已经安装，请忽略\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get install nginx\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"安装php和php-fpm\"\u003e安装php和php-fpm\u003c/h1\u003e\n\u003cp\u003e如果已经安装，请忽略\u003c/p\u003e\n\u003cp\u003e添加php源\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-add-repository ppa:ondrej/php\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get update\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e安装\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#安装php7.3\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get install php7.3\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#安装php-fpm\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get install php-fpm\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"安装phalcon\"\u003e安装phalcon\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get install php7.3-phalcon\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"重启php-fpm\"\u003e重启php-fpm\u003c/h1\u003e\n\u003cp\u003e这个步骤是要把phalcon模块注册到php-fpm\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo systemctl reload  php7.3-fpm.service\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"安装phalcon-devtools脚手架\"\u003e安装phalcon-devtools（脚手架）\u003c/h1\u003e\n\u003cp\u003e从git安装\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#下载\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003egit clone --depth\u003cspan style=\"color:#f92672\"\u003e=\u003c/span\u003e\u003cspan style=\"color:#ae81ff\"\u003e1\u003c/span\u003e https://github.com/phalcon/phalcon-devtools.git\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#进入目录\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ecd phalcon-devtools/\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#创建软连接\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo ln -s \u003cspan style=\"color:#66d9ef\"\u003e$(\u003c/span\u003epwd\u003cspan style=\"color:#66d9ef\"\u003e)\u003c/span\u003e/phalcon /usr/bin/phalcon\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#修改权限\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo chmod ugo+x /usr/bin/phalcon\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#执行命令，查看是否安装成功\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003ephalcon commands help\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e如果提示 \u003ccode\u003e\u0026quot;phalcon: command not found\u0026quot;\u003c/code\u003e\n尝试命令\u003c/p\u003e","title":"部署ubuntu + nginx + php-fpm + phalcon"},{"content":"记录下过程\n安装Python3.6 正常情况下，Python3.6是自带的\n$ sudo apt-get install python3.6 创建Python3虚拟环境 ubuntu自带Python2和Python3，默认情况下Python2的优先级高 需要虚拟一个Python3的环境\n# 安装virtualenv $ sudo apt-get install virtualenv # 创建python3.6虚拟环境 -p指定python3.6解释器路径 $ virtualenv -p /usr/bin/python3.6 envPython3.6 # 激活Python3.6环境 $ cd envPython3.6 $ source bin/activate #查看当前版本 $ python -V 注：\n如果不使用虚拟环境，也可提升Python3.6的优先级 如果有多个Python3.x，调整Python3的优先级，使得3.6优先级较高 $ sudo update-alternatives \u0026ndash;install /usr/bin/python3 python3 /usr/bin/python3.5 1 $ sudo update-alternatives \u0026ndash;install /usr/bin/python3 python3 /usr/bin/python3.6 2\n更改默认值，python默认为Python2，现在修改为Python3 $ sudo update-alternatives \u0026ndash;install /usr/bin/python python /usr/bin/python2 100 $ sudo update-alternatives \u0026ndash;install /usr/bin/python python /usr/bin/python3 150\n查看当前版本 $ python -V\nsudo apt-get install libapache2-mod-wsgi-py3\n创建一个Django应用 安装Django # 在激活的Python3.6虚拟环境中 $ pip install Django 创建一个项目 $ django-admin startproject DjangoProj DjangoProj为项目名，项目名需要为合法的 Python 包名，如不能为 1a 或 a-b等。\n创建成功后，会有一个DjangoProj文件夹，里面包含 manage.py 文件\n创建一个应用 # 在激活的Python3.6虚拟环境中 $ cd DjangoProj $ python manage.py startapp firstApp 安装Apache2 和 mod_wsgi $ sudo apt-get install apache2 $ sudo apt-get install libapache2-mod-wsgi-py3 配置文件 在 /etc/apahce2/sites-available 文件夹下创建配置文件，如 firstApp.conf\n# firstApp.conf \u0026lt;VirtualHost *:80\u0026gt; #如果有域名，可以配置域名；没有域名，可以配置ip地址 ServerName hello.com ServerAlias abcName #管理员联系方式 ServerAdmin helloAdmin@hello.com #指定项目路径 WSGIDaemonProcess abcName python-home=/home/ubuntu/envPython3.6/ WSGIProcessGroup abcName # 配置wsgi.py脚本路径 在使用Django创建的项目目录下面 WSGIScriptAlias /firstApp /home/ubuntu/envPython3.6/DjangoProj/DjangoProj/wsgi.py \u0026lt;Directory /home/ubuntu/envPython3.6/DjangoProj/\u0026gt; \u0026lt;Files wsgi.py\u0026gt; Require all granted \u0026lt;/Files\u0026gt; \u0026lt;/Directory\u0026gt; \u0026lt;/VirtualHost\u0026gt; 使用VS Code Remote SSH打开文件时，可能会遇到权限问题，可以用如下命令修改相应文件夹的权限\n变更所有者 $ sudo chown -R 当前用户名 /etc/apache2/sites-available/\n修改wsgi.py 添加如下代码\nimport sys PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0,PROJECT_DIR) 完整代码\nimport os import sys PROJECT_DIR = os.path.dirname(os.path.dirname(os.path.abspath(__file__))) sys.path.insert(0,PROJECT_DIR) from django.core.wsgi import get_wsgi_application os.environ.setdefault(\u0026#39;DJANGO_SETTINGS_MODULE\u0026#39;, \u0026#39;DjangoProj.settings\u0026#39;) application = get_wsgi_application() 激活配置文件 $ sudo a2ensite firstApp.conf $ sudo systemctl reload apache2 ","permalink":"https://blog.z6z8.cn/2019/09/09/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0-ubuntu-18-%E9%83%A8%E7%BD%B2-apache2-python-3-6-django/","summary":"\u003cp\u003e记录下过程\u003c/p\u003e\n\u003ch1 id=\"安装python36\"\u003e安装Python3.6\u003c/h1\u003e\n\u003cp\u003e正常情况下，Python3.6是自带的\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ sudo apt-get install python3.6\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch1 id=\"创建python3虚拟环境\"\u003e创建Python3虚拟环境\u003c/h1\u003e\n\u003cp\u003eubuntu自带Python2和Python3，默认情况下Python2的优先级高\n需要虚拟一个Python3的环境\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-fallback\" data-lang=\"fallback\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 安装virtualenv\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ sudo apt-get install virtualenv\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 创建python3.6虚拟环境 -p指定python3.6解释器路径\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ virtualenv -p /usr/bin/python3.6  envPython3.6\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e# 激活Python3.6环境\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ cd envPython3.6\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ source bin/activate\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e#查看当前版本\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e$ python -V\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e注：\u003c/p\u003e\n\u003cblockquote\u003e\n\u003cp\u003e如果不使用虚拟环境，也可提升Python3.6的优先级\n如果有多个Python3.x，调整Python3的优先级，使得3.6优先级较高\n$ sudo update-alternatives \u0026ndash;install /usr/bin/python3 python3 /usr/bin/python3.5 1\n$ sudo update-alternatives \u0026ndash;install /usr/bin/python3 python3 /usr/bin/python3.6 2\u003c/p\u003e\n\u003cp\u003e更改默认值，python默认为Python2，现在修改为Python3\n$ sudo update-alternatives \u0026ndash;install /usr/bin/python python /usr/bin/python2 100\n$ sudo update-alternatives \u0026ndash;install /usr/bin/python python /usr/bin/python3 150\u003c/p\u003e","title":"学习笔记: Ubuntu 18 部署 Apache2 + Python 3.6 + Django"},{"content":"参考连接 https://docs.phalcon.io/4.0/en/installation\nsudo apt-get update sudo apt-get install php7.2-phalcon ","permalink":"https://blog.z6z8.cn/2019/09/09/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9Aubuntu18-%E5%AE%89%E8%A3%85-phalcon7/","summary":"\u003cp\u003e参考连接\n\u003ca href=\"https://docs.phalcon.io/4.0/en/installation\"\u003ehttps://docs.phalcon.io/4.0/en/installation\u003c/a\u003e\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get update\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get install php7.2-phalcon\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e","title":"学习笔记：Ubuntu18 安装 phalcon7"},{"content":"参考连接 1、 https://www.linuxidc.com/Linux/2015-01/112587.htm 2、 https://www.centos.bz/2018/07/%E4%B8%80%E6%AC%A1ubuntunginx%E6%90%AD%E5%BB%BAwordpress%E7%9A%84%E7%BB%8F%E5%8E%86/ 3、 https://www.cnblogs.com/ldj3/p/9298734.html 4、 https://wordpress.org/support/article/how-to-install-wordpress/\n最终环境 ubuntu 18.04.1 nginx 1.14.0 (Ubuntu) mysql server 5.7.27-0ubuntu0.18.04.1 (Ubuntu) php7.3 和 php7.3-fpm 和php7.3-mysql wordpress 5.2.3(安装时为最新版本) 安装nginx sudo apt-get install nginx 可以用浏览器打开 http://127.0.0.1 来测试nginx是否安装成功\n安装mysql 安装server sudo apt-get install mysql-server 安全配置 sudo mysql_secure_installation 按照提示操作，配置密码、测试库、匿名用户、远程访问等\n修改mysql数据库路径（数据迁移，可选） 1、查看当前数据库路径 #root用户登陆 sudo mysql -u root -p #查看路径 \u0026gt; show variables like \u0026#39;%dir%\u0026#39;; #退出 \u0026gt; exit; 输出类似结果\n+-----------------------------------------+----------------------------+ | Variable_name | Value | +-----------------------------------------+----------------------------+ | basedir | /usr/ | | binlog_direct_non_transactional_updates | OFF | | character_sets_dir | /usr/share/mysql/charsets/ | | datadir | /var/lib/mysql/ | ...... +-----------------------------------------+----------------------------+ 其中 datadir是需要修改的部分\n2、停止mysql服务 sudo /etc/init.d/mysql stop 或者 sudo systemctl stop mysql 3、移动数据库到新目录 使用mv命令好处是不会修改原数据库文件的权限，以及用户和用户组归属：\nsudo mv /var/lib/mysql 新目录/ 4、修改mysql配置文件\n4-1 修改 my.cnf文件\nmysql数据库会按顺序优先级从/etc/my.cnf、/etc/mysql/my.cnf、/usr/etc/my.cnf、~/.my.cnf四个位置找my.cnf配置文件，一旦找到就不再继续往下找。\n我的文件路径是 /etc/mysql/mysql.conf.d/mysqld.cnf 用sudo vim打开\nsudo vim /etc/mysql/mysql.conf.d/mysqld.cnf 修改datadir的值\n[mysqld] # * Basic Settings ...... basedir = /usr #修改datadir的值 datadir = 新目录/mysql ...... 4-2 修改 usr.bin.mysqld文件 Ubuntu使用了apparmor安全模块，就是类似于沙盒运行的一种机制，它可以限制软件在运行时的一些行为，比如对哪些目录和文件可以读写加锁等等。 /etc/apparmor.d/usr.sbin.mysqld，用sudo vim打开\nsudo vim /etc/apparmor.d/usr.sbin.mysqld 找到其中的数据库路径(参考上面的 查看当前数据库路径)\n/var/lib/mysql/ r, /var/lib/mysql/** rwk, 修改为：\n新目录/mysql/ r, 新目录/mysql/** rwk, 4-3 修改 abstractions/mysql文件 由于usr.bin.mysqld文件中引用了abstractions/mysql文件，也就是会将abstractions/mysql文件中的权限声明导入进来。\nsudo vim /etc/apparmor.d/abstractions/mysql 新数据库文件路径中的socket文件权限添加进去，同时可以删除或者注释掉全路径中申请的权限\n# /var/lib/mysql{,d}/mysql{,d}.sock rw, #修改为新目录 /新目录/mysql{,d}/mysql{,d}.sock rw, /{var/,}run/mysql{,d}/mysql{,d}.sock rw, /usr/share/{mysql,mysql-community-server,mariadb}/charsets/ r, /usr/share/{mysql,mysql-community-server,mariadb}/charsets/*.xml r, 4-4 重启服务 #重新载入apparmor配置文件 sudo /etc/init.d/apparmor restart #重启mysql sudo /etc/init.d/mysql start 安装php和php-fpm和php-mysql 添加php源 sudo apt-add-repository ppa:ondrej/php sudo apt-get update 安装 #安装php7.3 sudo apt-get install php7.3 #安装php-fpm sudo apt-get install php-fpm #安装php-mysql sudo apt-get install php-mysql 安装wordpress 创建一个空文件夹给wordpress，然后下载解压wordpress压缩包\n#下载最新版本 wget https://wordpress.org/latest.tar.gz #解压缩 tar -xzvf latest.tar.gz 配置web服务 进入 /etc/nginx/sites-available ,创建一个nginx虚拟主机服务给wordpress，\nsudo vim /etc/nginx/sites-available/wordpress.conf 内容如下\nserver { #监听端口(ipv4和ipv6) listen 8000; listen [::]:8000; #wordpress的主机域名（也可以填写ip地址）,多个用空格分开 server_name hellowrold.com www.hellowrold.com; #wordpress根目录（就是wordpress压缩包解压后存放目录） root /xxxxx/wordpress; # index index.php index.html index.htm; client_max_body_size 5M; location / { try_files $uri $uri/ /index.php?$args; } location ~ \\.php$ { include snippets/fastcgi-php.conf; #unix socket 路径参见 /etc/php/7.3/fpm/pool.d/www.conf fastcgi_pass unix:/run/php/php7.3-fpm.sock; fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name; include fastcgi_params; } } 开启wordpress的web服务\n#创建软连接 sudo ln -s /etc/nginx/sites-available/wordpress.conf /etc/nginx/sites-enabled/ #重新加载nginx sudo systemctl reload nginx 给wordpress创建数据库 #以root用户进入mysql环境 sudo mysql -u root -p #创建数据库 需要记录下数据库名称 \u0026gt; CREATE DATABASE wordpressDbName; Query OK, 1 row affected (0.00 sec) # 创建用户 需要记录下用户名和密码 \u0026gt; GRANT ALL PRIVILEGES ON wordpressDbName.* TO \u0026#34;wordpressUserName\u0026#34;@\u0026#34;localhost\u0026#34; (输入到这，按回车键) -\u0026gt; IDENTIFIED BY \u0026#34;密码\u0026#34;; Query OK, 0 rows affected (0.00 sec) #提交 mysql\u0026gt; FLUSH PRIVILEGES; Query OK, 0 rows affected (0.01 sec) #退出 mysql\u0026gt; EXIT Bye 初始化wordpress 进入 http://你分配的nginx虚拟主机/wp-admin/install.php 本文所示案例为 http://hellowrold.com/wp-admin/install.php\n安装提示操作完成初始化,这里会用的 给wordpress创建数据库 里面的信息\n如果遇到\n抱歉，我不能写入wp-config.php文件。 您可以手工创建wp-config.php文件，并将以下文字粘贴于其中。 可以在wordpress的根目录（就是wordpress压缩包解压后存放目录）,创建 wp-config.php 文件，内容见提示\n","permalink":"https://blog.z6z8.cn/2019/09/05/%E5%AD%A6%E4%B9%A0%E7%AC%94%E8%AE%B0%EF%BC%9Aubuntu18-%E5%AE%89%E8%A3%85nginx-mysql-wordpress/","summary":"\u003cp\u003e参考连接\n1、 \u003ca href=\"https://www.linuxidc.com/Linux/2015-01/112587.htm\"\u003ehttps://www.linuxidc.com/Linux/2015-01/112587.htm\u003c/a\u003e\n2、 \u003ca href=\"https://www.centos.bz/2018/07/%E4%B8%80%E6%AC%A1ubuntunginx%E6%90%AD%E5%BB%BAwordpress%E7%9A%84%E7%BB%8F%E5%8E%86/\"\u003ehttps://www.centos.bz/2018/07/%E4%B8%80%E6%AC%A1ubuntunginx%E6%90%AD%E5%BB%BAwordpress%E7%9A%84%E7%BB%8F%E5%8E%86/\u003c/a\u003e\n3、 \u003ca href=\"https://www.cnblogs.com/ldj3/p/9298734.html\"\u003ehttps://www.cnblogs.com/ldj3/p/9298734.html\u003c/a\u003e\n4、 \u003ca href=\"https://wordpress.org/support/article/how-to-install-wordpress/\"\u003ehttps://wordpress.org/support/article/how-to-install-wordpress/\u003c/a\u003e\u003c/p\u003e\n\u003ch1 id=\"最终环境\"\u003e最终环境\u003c/h1\u003e\n\u003cul\u003e\n\u003cli\u003eubuntu 18.04.1\u003c/li\u003e\n\u003cli\u003enginx 1.14.0 (Ubuntu)\u003c/li\u003e\n\u003cli\u003emysql server 5.7.27-0ubuntu0.18.04.1 (Ubuntu)\u003c/li\u003e\n\u003cli\u003ephp7.3 和 php7.3-fpm 和php7.3-mysql\u003c/li\u003e\n\u003cli\u003ewordpress 5.2.3(安装时为最新版本)\u003c/li\u003e\n\u003c/ul\u003e\n\u003ch1 id=\"安装nginx\"\u003e安装nginx\u003c/h1\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get install nginx\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e可以用浏览器打开 \u003ca href=\"http://127.0.0.1\"\u003ehttp://127.0.0.1\u003c/a\u003e 来测试nginx是否安装成功\u003c/p\u003e\n\u003ch1 id=\"安装mysql\"\u003e安装mysql\u003c/h1\u003e\n\u003ch2 id=\"安装server\"\u003e安装server\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo apt-get install mysql-server\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003ch2 id=\"安全配置\"\u003e安全配置\u003c/h2\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo mysql_secure_installation\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e按照提示操作，配置密码、测试库、匿名用户、远程访问等\u003c/p\u003e\n\u003ch2 id=\"修改mysql数据库路径数据迁移可选\"\u003e修改mysql数据库路径（数据迁移，可选）\u003c/h2\u003e\n\u003cul\u003e\n\u003cli\u003e1、查看当前数据库路径\u003c/li\u003e\n\u003c/ul\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#root用户登陆\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003esudo mysql -u root -p\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#查看路径\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026gt; show variables like \u003cspan style=\"color:#e6db74\"\u003e\u0026#39;%dir%\u0026#39;\u003c/span\u003e;\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u003cspan style=\"color:#75715e\"\u003e#退出\u003c/span\u003e\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e\u0026gt; exit;\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e输出类似结果\u003c/p\u003e\n\u003cdiv class=\"highlight\"\u003e\u003cpre tabindex=\"0\" style=\"color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;\"\u003e\u003ccode class=\"language-shell\" data-lang=\"shell\"\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e+-----------------------------------------+----------------------------+\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e| Variable_name                           | Value                      |\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e+-----------------------------------------+----------------------------+\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e| basedir                                 | /usr/                      |\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e| binlog_direct_non_transactional_updates | OFF                        |\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e| character_sets_dir                      | /usr/share/mysql/charsets/ |\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e| datadir                                 | /var/lib/mysql/ |\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e......\n\u003c/span\u003e\u003c/span\u003e\u003cspan style=\"display:flex;\"\u003e\u003cspan\u003e+-----------------------------------------+----------------------------+\n\u003c/span\u003e\u003c/span\u003e\u003c/code\u003e\u003c/pre\u003e\u003c/div\u003e\u003cp\u003e其中 datadir是需要修改的部分\u003c/p\u003e","title":"学习笔记：ubuntu18 安装nginx + mysql + wordpress"}]