├── .DS_Store
├── .gitignore
├── Android
└── Android001.md
├── BlogArchive
├── AppLovin-MAX-SDK-Android-master.zip
├── Audio Queue 录制 播放原理.md
├── Flutter main和 future mirotask 的执行顺序.md
├── Flutter 一些常用库.md
├── Flutter学习路线.md
├── Image.File 加载图像时文件内容变化显示不变解决.md
├── MLImageOptimizer.md
├── Runloop分析.md
├── Swift 中文和日文分词.md
├── TenonVPN.ipa
├── Xcode兼容ios.md
├── [Flutter] 一些面试可能会问基础知识.md
├── code-obfuscation-master.zip
├── dart1.0 语言基础 .md
├── geph-macos.dmg
├── iOS 内存管理分析.md
├── iOS底层原理探索—OC对象的本质.md
├── iOS消息转发机制、响应者链、App启动前后.md
├── simpread-Flutter 布局 - Baseline、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth 详解 - Flutter 开发社区.md
├── simpread-Flutter 布局 - FittedBox、AspectRatio、ConstrainedBox 详解 - Flutter 开发社区.md
├── simpread-Flutter 布局 - LimitedBox、Offstage、OverflowBox、SizedBox 详解 - Flutter 开发社区.md
├── simpread-Flutter 布局 - Padding、Align、Center 详解 - Flutter 开发社区.md
├── video.mp4
├── 三棵重要的树 (渲染过程、布局约束、应用视图的构建等) .md
├── 使用 libclang 实现 iOS 代码中的明文加密.md
├── 动画全解析(动画四要素、动画组件、隐式动画组件原理等).md
├── 在 IOS 工程中使用 OC 调用 C 语言国密算法 SM4(来替换 DES 算法)__小呵呵的博客 - CSDN 博客_ios sm4 算法.md
├── 堆、栈、全局区、常量区、代码区.md
├── 禁止macOS自动更新.md
├── 聊聊 Flutter Platform SDK.md
├── 让你的 Swift 代码更 Swift.md
└── 震动效果调研-番茄巧克力-CSDN.md
├── CCFileUtils
├── CCFileUtils.cpp
└── CCFileUtils.h
├── Files
├── 3DTouch.md
├── AI.md
├── AVFoundation.md
├── Algorithm.md
├── AlwaysInline.md
├── BatteryLevel.md
├── BuildConfiguration.md
├── CallKit.md
├── Carthage.md
├── Cartoon_GAN.md
├── Chrome.md
├── CocoaPods.md
├── DeleteSystemABC.md
├── DevelopEnglish.md
├── Exit.md
├── FFMpeg.md
├── Flutter.md
├── Framework.md
├── Git.md
├── Hackintosh.md
├── Handoff.md
├── Homebrew.md
├── IJKPlayer.md
├── IM.md
├── IPATransportation.md
├── IpaProcessingFailed.md
├── LineBreakMode.md
├── Mac.md
├── NSInvocation.md
├── NSPredicate.md
├── NSTimer.md
├── Network.md
├── Nil_nil_Null_NSNull.md
├── OverTheAirInstallation.md
├── Project.md
├── ProjectNotice.md
├── RAM.md
├── Reverse.md
├── SIP.md
├── SKAdNetwork.md
├── SafeMainAsync.md
├── Singleton.md
├── SiriKit.md
├── Sox.md
├── Thread.md
├── Tip001.md
├── Tip002.md
├── Tip003.md
├── Tip004.md
├── Tip005.md
├── TypeChange.md
├── Use_frameworks.md
├── Wifi.md
├── Xcode.md
├── aml.md
└── iOS13.md
├── MindNode
└── FlutterWidget.mindnode
│ ├── QuickLook
│ └── Preview.jpg
│ ├── contents.xml
│ ├── style.mindnodestyle
│ ├── contents.xml
│ └── metadata.plist
│ └── viewState.plist
├── README.md
├── iOS底层原理探究
└── OC对象.md
├── video
├── Android.webm
├── iOS.mov
├── iOS.mp4
├── iOS的副本.mp4
├── puppets_with_alpha_hevc-1.mov
└── puppets_with_alpha_hevc.mov
└── 积累知识
├── 影视_歌曲_明星_现代.md
├── 电影_动画_文章_网址.md
└── 诗词_歌赋_典故_古代.md
/.DS_Store:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/.DS_Store
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 |
2 | .DS_Store
3 | .DS_Store
4 |
--------------------------------------------------------------------------------
/Android/Android001.md:
--------------------------------------------------------------------------------
1 | ## 知识概要
2 |
3 | > #### 术语
4 |
5 | * Dalvik:Android特有的虚拟机,比JVM更适合移动端使用
6 | * AVD:Android Virtual Device,安卓虚拟设备,模拟器
7 | * ADT:Android Development Tools,安卓开发工具
8 | * SDK:Software Development Kit,软件开发工具包
9 | * DDMS:Dalvik Debug Monitor Sevice,安卓调试监控工具
10 | * adb:安卓调试桥,在platform-tools目录
11 | * DX工具:将.class转.dex的工具
12 | * AAPT:Android Asset Packing Tool,安卓资源打包工具
13 | * R.java文件:由aapt工具根据App中的资源文件自动生成,可以理解为资源字典
14 | * AndroidManifest.xml:app包名+组件声明+程序兼容的最低版本+所需权限等程序的配置文件
15 |
16 | > #### adb命令
17 |
18 | * windows上需要配置环境变量
19 |
20 | 1. 新建 ``` ANDROID_HOME ```环境变量,添加SDK地址(如 D:\Android\android_sdks)
21 | 2. 更新Path环境变量,添加 ``` % ANDROID_HOME%\tools ```
22 |
23 | * 一些命令
24 |
25 | 1. 安装软件: adb install [-r] xx.apk -r:重装
26 | 2. 卸载软件: adb uninstall [-k] <包名> -k:保留数据和缓存目录
27 | 3. 取出手机文件: adb pull xxx.xxx
28 | 4. 发送文件到手机: adb push xxx.xxx
29 | 5. 进入手机终端: adb shell
30 | 6. 列出所有连接的设备: adb devices
31 | 7. 重启adb: adb:reset adb
32 | 8. 杀死adb: adb kill-server
33 | 9. 启动adb: adb start-server
34 | 10. 查看端口号占用的进程: netstat -ano
35 |
36 | > #### 工程说明
37 |
38 | * java目录
39 |
40 | 写业务功能的java代码
41 |
42 | * res目录
43 |
44 | 存放各种资源文件的地方,如图片、字符串、动画、音频、视频及各种XML等
45 |
46 | * 自建assets目录
47 |
48 | 自己创建的存放资源的地方。res下所有的资源文件在R.java文件下生成对应资源id,通过资源id访问对应资源;自建assets不会在R.java生成id,通过AssetManager以二进制流形式读取。(R文件可理解成资源字典,res下每个资源在这里生成唯一id)
49 |
50 | * drawable
51 |
52 | 存放各种位图文件,包括png、jpg、.9png、gif及一些其他drawable类型的XML文件等
53 |
54 | * mipmap-hdpi
55 |
56 | 高分辨率,一般图片放这里
57 |
58 | * mipmap-mdpi
59 |
60 | 中等分辨率,兼容旧型号手机,很少用了
61 |
62 | * mipmap-xhdpi
63 |
64 | 超高分辨率
65 |
66 | * mipmap-xxhdpi
67 |
68 | 超超高分辨率
69 |
70 | * layout
71 |
72 | 布局文件资源所在目录。另外在一些特定机型上,我们做屏幕适配,如480*320手机,创建另外一套布局layout-480x320文件夹
73 |
74 | * menu
75 |
76 | 有物理按键menu的手机用,菜单相关资源xml放这里
77 |
78 | * values
79 |
80 | * demens.xml: 定义尺寸资源
81 | * string.xml: 定义字符串资源
82 | * style.xml: 定义样式资源
83 | * colors.xml: 定义颜色资源
84 | * arrays.xml: 定义数组资源
85 | * attri.xml: 自定义控件时用到,自定义控件的属性
86 | * theme主题文件,和style类似,但是会对整个应用的Activity或指定Activity起作用,一般改变窗口外观。可在Java代码中通过setTheme使用,或在Androidmanifest.xml中为添加theme的属性。有时候可能看到这样的values目录:values-w820dp,values-v11等,前者w代表平板设备,820dp代表屏幕宽度,后者v11代表在API(11)后才能用到。
87 |
88 | * raw目录
89 |
90 | 存放各种原生资源,包括音频、视频、一些XML文件等,可通过openRawResource(int id)获得资源的二进制流,和Assets类似,不过这里的资源会在R文件生成资源id
91 |
92 | * 动画目录
93 |
94 | * animator:存放属性动画的XML文件
95 | * anim: 存放补间动画的XML文件
96 |
97 | > #### 获取资源
98 |
99 | 对于R.java中生成唯一资源id的资源,可通过id完成资源访问,可在java代码或XML中使用
100 |
101 | * java代码中使用
102 |
103 | ```
104 | // java文本
105 | texName.setText(getResources().getText(R.string.name));
106 |
107 | // 图片
108 | imgIcon.setBackgroundDrawableResource(R.drawable.icon);
109 |
110 | // 颜色
111 | textName.setTextColor(getResources().getColor(R.color.red));
112 |
113 | // 布局
114 | setContentView(R.layout.main);
115 |
116 | // 控件
117 | textName = (TextView)findViewById(R.id.text_name);
118 | ```
119 |
120 | * XML代码中使用
121 |
122 | ```
123 | 通过@xxx即可得到,比如获取文本和图片
124 |
129 | ```
130 |
131 | > #### 深入了解三个文件
132 |
133 | * MainAcrivity.java
134 |
135 | ```
136 | package jay.com.example.firstapp
137 |
138 | import android.support.v7.app.AppCompatActivity;
139 | import android.os.Bundle;
140 |
141 | // 1.定义一个MainActivity 继承自AppCompatActivity 要实现抽象方法onCreate()
142 | public class MainActivity extends AppCompatActivity {
143 | @Override
144 | protected void onCreate(Bundle savedInstanceState) {
145 | // 2.调用父类方法
146 | super.onCreate(saveInstanceState);
147 | // 3.加载R.layout.activity_main的布局文件
148 | setContentView(R.layout.activity_main);
149 | }
150 | }
151 | // 4.在AndroidManifest.xml中进行声明,否则报错
152 | ```
153 |
154 | * 布局文件 activity_main.xml
155 |
156 | ```
157 |
163 |
164 |
168 |
169 |
170 | ```
171 |
172 | 我们定义一个LinearLayout线性布局,在xml命名空间中定义我们所需要使用的架构,来自于
173 |
174 | ```
175 | 1.有了xmlns:android 和 xmlns:tools 就可以按alt+/作为提示(语法文件且无需联网)
176 | 2.android:id = "@+id/linearLayout1" 为这个布局设置一个id标记为LinearLayout1,并添加到R文件的id内部类中
177 | 3. android:layout_width和android:layout_height 控制组件的宽高,有三个属性可以选wrap_content/fill_content/match_content
178 | 4. android:orientation = "vertical" 为线性布局指定方式(水平horizontal 竖直vertical)
179 | 5. tools:context = ".MyActivity" 这句不会打包进Apk,只是ADT的的Layout Editor在当前的Layout文件里设置对应的渲染上下文,说明当前Layout所在的渲染上下文是activiry name对应的那个activity,如果这个activity在manifest文件中设置了Theme,那么ADT的Layout Editor会根据这个Theme来渲染当前的Layout。
180 | 6. android:text = "@string/hello_world" 为这个textview设置文本,引用string资源里hello_world字符串文本
181 | ```
182 |
183 | * AndroidManifest.xml配置文件
184 |
185 | ```
186 |
187 |
189 |
190 |
195 |
196 |
199 |
200 |
201 |
202 |
203 |
204 |
205 |
206 |
207 |
208 |
209 |
210 | ```
211 |
212 | 代码详细分析
213 |
214 | ```
215 | // manifest
216 | 定义了使用的xml的版本和编码方式
217 | xmlns:android = "http://schemas.android.com/apk/res/android" 定义架构来源
218 | package = "jay.com.example.firstapp"> 程序所在Java包(包名是应用唯一标识)
219 |
220 | // users-sdk
221 | android:versionCode = "1" android:versionName = "1.0" 定义程序的版本号和版本名称
222 | 使用该app的最低sdk版本为2.2 开发的系统版本为4.2,后面的编号代表每个版本的sdk
223 |
224 | // Application
225 | android:allowBackup = "true" 是否允许备份文件(这里允许)
226 | android:icon = "@drawable/ic_launcher" 定义应用的图标,引用drawable中的ic_launcher
227 | android:label = "@string/app_name" 定义应用名称,应用string中的app_name
228 | Android:theme = "@style/AppTheme" 定义应用使用的主题(app风格)
229 |
230 | // Activity
231 | android:name = "com.example.helloworld.MainActivity" 声明一个activity,包括activity所在的包和app名称,前面部分可用 . 表示来缩写
232 | android:label = "@string/app_name" Activity名称,显示给用户看的
233 |
234 | Intent-filter(意图过滤器)
235 |
236 |
237 | 这两行代码决定了程序的入口,且app会被显示在Home的应用程序列表中
238 |
239 | 除上述内容外:
240 | 1.如果app中包含其他组件的话,都要使用类型说明语法在该文件中进行声明Server元素 BroadcastReceiver元素ContentProvoder元素 IntentFilter元素
241 | 2.权限的声明:在该文件中显式地声明程序需要的权限,防止app错误地使用服务或不恰当地访问资源,最终提高健壮性
242 | ```
243 |
244 | > #### 签名
245 |
246 | * 签名好处[详见](https://blog.csdn.net/fyh2003/article/details/6911967)
247 |
248 | 1. 应用程序升级:如果你希望用户无缝升级到新的版本,那么你必须用同一个证书进行签名。这是由于只有以同一个证书签名,系统才会允许安装升级的应用程序。如果你采用了不同的证书,那么系统会要求你的应用程序采用不同的包名称,在这种情况下相当于安装了一个全新的应用程序。如果想升级应用程序,签名证书要相同,包名称要相同!
249 | 2. 应用程序模块化:Android系统可以允许同一个证书签名的多个应用程序在一个进程里运行,系统实际把他们作为一个单个的应用程序,此时就可以把我们的应用程序以模块的方式进行部署,而用户可以独立的升级其中的一个模块
250 | 3. 代码或者数据共享:Android提供了基于签名的权限机制,那么一个应用程序就可以为另一个以相同证书签名的应用程序公开自己的功能。以同一个证书对多个应用程序进行签名,利用基于签名的权限检查,你就可以在应用程序间以安全的方式共享代码和数据了。
251 |
252 | 不同的应用程序之间,想共享数据,或者共享代码,那么要让他们运行在同一个进程中,而且要让他们用相同的证书签名。
253 |
254 | * 命令行签名方式(keytool在jdk/jre/bin目录,jarsigner在jdk/bin目录)
255 |
256 | 1. 通过以下命令可以获取证书和私钥:keytool -genkey -v -keystore doudou.keystore -alias doudou -keyalg RSA -validity 10000
257 | 2. 通过以下命令可以对apk签名:jarsigner -verbose -keystore doudou.keystore doudou.apk doudou.keystore
258 | 3. 验证是否签名 jarsigner -verbose -certs -vertify doudou.apk
259 |
260 | ```
261 | 可以更改顺序如:
262 | keytool -genkey -alias demo.keystore -keyalg RSA -validity 40000 -keystore demo.keystore
263 | -genkey 产生密钥
264 | -alias demo.keystore 别名demo.keystore
265 | -validity 40000 有效期40000天
266 |
267 | jarsigner -verbose -keystore demo.keystore -signedjar demo_signed.apk demo.apk demo.keystore
268 | -verbose 输出签名的详细信息
269 | -keystore demo.keystore 密钥库位置
270 | -signedjar demor_signed.apk demo.apk demo.keystore 正式签名,三个参数中依次为签名后产生的文件demo_signed,要签名的文件demo.apk和密钥库demo.keystore
271 | ```
272 |
273 | 打包Android APK的方法还有很多,命令行,或者Gradle,ANT,MAVEN等等
274 |
275 |
276 | [传送门](https://www.runoob.com/w3cnote/android-tutorial-sign-package.html)
277 |
278 | [adb常用命令小结](https://zhuanlan.zhihu.com/p/68571291)
279 |
280 | [菜鸟教程](https://www.runoob.com/)
281 |
282 | [Android学习总结](https://www.jianshu.com/p/5a2419132c4c)
283 |
284 | [Android 2011](https://www.cnblogs.com/qianxudetianxia/default.html?page=4)
--------------------------------------------------------------------------------
/BlogArchive/AppLovin-MAX-SDK-Android-master.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/BlogArchive/AppLovin-MAX-SDK-Android-master.zip
--------------------------------------------------------------------------------
/BlogArchive/Flutter main和 future mirotask 的执行顺序.md:
--------------------------------------------------------------------------------
1 | > 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 https://www.cnblogs.com/yangyxd/p/10411114.html
2 |
3 | 下面这段代码的输出是什么?
4 | -------------
5 |
6 | [](javascript:void(0); "复制代码")
7 |
8 | ```
9 | import 'dart:async';
10 | main() {
11 | print('main #1 of 2');
12 | scheduleMicrotask(() => print('microtask #1 of 2'));
13 |
14 | new Future.delayed(new Duration(seconds:1),
15 | () => print('future #1 (delayed)'));
16 | new Future(() => print('future #2 of 3'));
17 | new Future(() => print('future #3 of 3'));
18 |
19 | scheduleMicrotask(() => print('microtask #2 of 2'));
20 |
21 | print('main #2 of 2');
22 | }
23 |
24 | ```
25 |
26 | [](javascript:void(0); "复制代码")
27 |
28 | 答案在下面:
29 |
30 | [](javascript:void(0); "复制代码")
31 |
32 | ```
33 | 1 main #1 of 2
34 | 2 main #2 of 2
35 | 3 microtask #1 of 2
36 | 4 microtask #2 of 2
37 | 5 future #2 of 3
38 | 6 future #3 of 3
39 | 7 future #1 (delayed)
40 |
41 | ```
42 |
43 | [](javascript:void(0); "复制代码")
44 |
45 | main 方法中的普通代码都是同步执行的,所以肯定是 main 打印先全部打印出来,等 main 方法结束后会开始检查 microtask 中是否有任务,若有则执行,执行完继续检查 microtask,直到 microtask 列队为空。所以接着打印的应该是 microtask 的打印。最后会去执行 event 队列(future)。由于有一个使用的 delay 方法,所以它的打印应该是在最后的。
46 | 原文:https://blog.csdn.net/meiyulong518/article/details/81773365
--------------------------------------------------------------------------------
/BlogArchive/Flutter学习路线.md:
--------------------------------------------------------------------------------
1 | > 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 https://www.jianshu.com/p/6a7bbae6aa19
2 |
3 | 0.4252019.03.09 11:53:10 字数 620 阅读 83
4 |
5 | 一、学习路线
6 | ------
7 |
8 | > 10 步,每一个学习步骤都以自己亲身实现写出了 Demo 为准,光看资料不算完成
9 |
10 | 1. 参考 [https://flutterchina.club/setup-macos/](https://flutterchina.club/setup-macos/),搭建 Flutter 开发环境,安装默认项目到设备
11 | 2. 通读 Dart 语法一遍:[https://juejin.im/post/5c52a386f265da2de25b5c36](https://juejin.im/post/5c52a386f265da2de25b5c36),要求上面所有代码,必须自己敲一遍
12 | 3. 实现一个简单的 HelloWorld 页面,目的是熟悉 Flutter 的项目结构和 StatelessWidget 组件,通读 Flutter 的所有 UI 组件一遍:[https://juejin.im/post/5c18d181f265da611f07a128](https://juejin.im/post/5c18d181f265da611f07a128),要求记住 flutter 的常用 UI 组件的继承关系
13 | 4. 实现页面跳转、传参、接收返回值,目的是熟悉 Navigator 组件
14 | 5. 实现一个 ezbuy-Mine 页面,暂不要求交互,但是页面的样式要大致实现,主要目的是熟悉基本 UI 组件,尤其是布局、文本、图片,
15 | 6. 实现一个 ezbuy-Home 页面,要求包含交互:下拉刷新和上拉加载更多,主要目的是熟悉复杂列表视图、滚动嵌套、手势
16 | 7. 实现一个简单登录页面的 Http 请求,服务端自己写,主要目的是熟悉 Flutter 的输入框、Dart 的异步编程 (async/await/Future)、网络请求、json 解析、响应式编程 (StatefulWidget/setState)
17 | 8. 实现一个简单登录页面的 grpc 请求,protobuf 文件和服务端也自己写,主要目的是熟悉 grpc 插件的用法
18 | 9. 实现读写本地缓存(Android:SharedPreferences,ios:NSUserDefaults)的简单页面,不准用第三方插件,自己用 MethodChannel 实现 Flutter 调用原生的功能
19 | 10. 实现 Flutter 项目接入宿主 Android 容器,主要目的是熟悉 Flutter 静态路由和 Android 原生传参给 FlutterView
20 |
21 | 二、下一步的调研计划
22 | ----------
23 |
24 | > 调研必须有产出,实践性的要有代码产出,理论性的要有 wiki 产出,没有产出的调研,就是耍流氓
25 |
26 | * 写一个国际化的 demo,实现多语言切换
27 | * 写一个自定义 View 的 Demo,熟悉绘图三剑客:canvas、path、paint
28 | * 写一个网络图片缓存的 demo,并了解其实现原理和内存占用
29 | * 阅读源码,了解 Flutter 的渲染机制,如何从 Widget->Element->RenderObject
30 | * 了解 Dart 的异步机制,深入理解 async/await/Future 的原理
31 |
32 | [](https://www.jianshu.com/u/5b37e90e81f7)
33 |
34 | ### 被以下专题收入,发现更多相似内容
35 |
36 | ### 推荐阅读[更多精彩内容](https://www.jianshu.com/)
37 |
38 | * 先看效果: 实现: 这边主要是用到了 NotificationListener 这个 widget,借助这个 widget...
39 |
40 | * 学习 Flutter 也有一阵子了。闲着没事,用了公司一个已经凉凉的 App 设计图来练手。当然了接口不可能用的了,所以都...
41 |
42 | * 一、路由跳转 1、直接跳转 2、先声明注册路由 后跳转 二、路由参数传递方法:使用 arguments 接收方法:在新...
43 |
44 | * 在开发过程中, 屏幕适配是很重要的一件事. 再 RN 中我们可以获取屏幕的像素, 按照特定机型来适配屏幕大小. 还要自己手写类...
45 |
46 | * 写在前面 Flutter 是 Google 推出并开源的移动应用开发框架,主打跨平台、高保真、高性能。开发者可以通过...
--------------------------------------------------------------------------------
/BlogArchive/Image.File 加载图像时文件内容变化显示不变解决.md:
--------------------------------------------------------------------------------
1 | > 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 https://www.cnblogs.com/yangyxd/p/10044094.html
2 |
3 | 在 Flutter 中,我们可以用下面的代码从文件中加载图像:
4 |
5 | ```
6 | Image.file(File(_fileName));
7 |
8 | ```
9 |
10 | 这个时候,当_fileName 这个文件名称和路径不变,文件内容变化时,Flutter 并不会更新显示。问题产生的原因是 Flutter 自动使用了缓存。
11 |
12 | 那么怎么办呢?
13 |
14 | 我查看到,Image.file 实际上会将 image 设置为 FileImage 这个 ImageProvider。FileImage 的代码中,在进行 operator 时,只判断了文件路径和缩放比例。正是因为如此,我们文件路径不变,缩放比例不变时,Flutter 会认为我们还是用的原图,并不会重新进行加载。
15 |
16 | 于是,我想到了办法是扩展一个 FileImage,将这个 operator 的方式改一下。
17 |
18 | [](javascript:void(0); "复制代码")
19 |
20 | ```
21 | class FileImageEx extends FileImage {
22 | int fileSize;
23 | FileImageEx(File file, { double scale = 1.0 })
24 | : assert(file != null),
25 | assert(scale != null),
26 | super(file, scale: scale) {
27 | fileSize = file.lengthSync();
28 | }
29 |
30 | @override
31 | bool operator ==(dynamic other) {
32 | if (other.runtimeType != runtimeType)
33 | return false;
34 | final FileImageEx typedOther = other;
35 | return file?.path == typedOther.file?.path
36 | && scale == typedOther.scale && fileSize == typedOther.fileSize;
37 | }
38 |
39 | }
40 |
41 | ```
42 |
43 | [](javascript:void(0); "复制代码")
44 |
45 | 接下来,直接使用下面的代码来加载图像:
46 |
47 | ```
48 | Image(image: FileImageEx(File(_fileName)));
49 |
50 | ```
51 |
52 | 经测试,问题得到解决。
53 |
54 | 如果您有更好的方式,欢迎留言。
--------------------------------------------------------------------------------
/BlogArchive/MLImageOptimizer.md:
--------------------------------------------------------------------------------
1 | # MLImageOptimizer
2 |
3 | **使用 [`pngquant`](https://github.com/kornelski/pngquant)、[`jpegoptim`](https://github.com/tjko/jpegoptim)
4 | 、[`gifsicle`](https://github.com/kohler/gifsicle) 快速批量递归压缩 png、jpg、gif 图片 ( 支持无损压缩和有损压缩 )**
5 |
6 | ## 自动递归压缩图片(默认开启无损压缩)
7 |
8 | 两种脚本:
9 | `optimizer.sh` 压缩完毕的图片会存储到原图 `` 同级目录下的文件夹 `` 内;
10 | `replace.sh` 脚本压缩图片并直接替换原图
11 |
12 | 打开终端,cd 到当前目录,然后执行 shell 脚本:
13 | ```
14 | $ sh optimizer.sh
15 | or
16 | $ ./optimizer.sh
17 |
18 | $ sh replace.sh
19 | or
20 | $ ./replace.sh
21 | ```
22 | 当然也支持在其他路径下执行,无需cd到当前目录:
23 | ```
24 | // 使用replace.sh脚本压缩图片并直接替换原图
25 | $ sh /Users/mountainx/Documents/MLImageOptimizer/replace.sh /Users/mountainx/Documents/Images
26 |
27 | // 使用optimizer.sh脚本压缩图片,保留原图,并将压缩后的图片保存在原图同级目录下的文件夹 `` 内
28 | $ sh /Users/mountainx/Documents/MLImageOptimizer/optimizer.sh /Users/mountainx/Documents/Images
29 | ```
30 |
31 | ## 备注
32 |
33 | **有损压缩比例 or 无损压缩可以在 `optimizer.sh` 和 `replace.sh` 中进行修改,参照下面的 `pngquant` 、 `jpegoptim` 、 `gifsicle` 的命令选项**
34 |
35 | `if use '$ ./optimizer.sh ', command line tool print error: 'Permission denied', please modify privilege using '$ chmod 777 optimizer.sh'`
36 |
37 | ## pngquant 命令选项
38 | ```
39 | $ pngquant -h
40 | pngquant, 2.12.3 (January 2019), by Kornel Lesinski, Greg Roelofs.
41 | Color profiles are supported via Little CMS. Using libpng 1.6.26.
42 |
43 | usage: pngquant [options] [ncolors] -- pngfile [pngfile ...]
44 | pngquant [options] [ncolors] - >stdout
73 |
74 | -d, --dest=
75 | specify alternative destination directory for
76 | optimized files (default is to overwrite originals)
77 | -f, --force force optimization
78 | -h, --help display this help and exit
79 | -m, --max=
80 | set maximum image quality factor (disables lossless
81 | optimization mode, which is by default on)
82 | Valid quality values: 0 - 100
83 | -n, --noaction don't really optimize files, just print results
84 | -S, --size=
85 | Try to optimize file to given size (disables lossless
86 | optimization mode). Target size is specified either in
87 | kilo bytes (1 - n) or as percentage (1% - 99%)
88 | -T, --threshold=
89 | keep old file if the gain is below a threshold (%)
90 | -b, --csv print progress info in CSV format
91 | -o, --overwrite overwrite target file even if it exists (meaningful
92 | only when used with -d, --dest option)
93 | -p, --preserve preserve file timestamps
94 | -P, --preserve-perms
95 | preserve original file permissions by overwriting it
96 | -q, --quiet quiet mode
97 | -t, --totals print totals after processing all files
98 | -v, --verbose enable verbose mode (positively chatty)
99 | -V, --version print program version
100 |
101 | -s, --strip-all strip all markers from output file
102 | --strip-none do not strip any markers
103 | --strip-com strip Comment markers from output file
104 | --strip-exif strip Exif markers from output file
105 | --strip-iptc strip IPTC/Photoshop (APP13) markers from output file
106 | --strip-icc strip ICC profile markers from output file
107 | --strip-xmp strip XMP markers markers from output file
108 |
109 | --all-normal force all output files to be non-progressive
110 | --all-progressive force all output files to be progressive
111 | --stdout send output to standard output (instead of a file)
112 | --stdin read input from standard input (instead of a file)
113 | ```
114 |
115 | ## gifsicle 命令选项
116 | ```
117 | $ gifsicle -h
118 | 'Gifsicle' manipulates GIF images. Its most common uses include combining
119 | single images into animations, adding transparency, optimizing animations for
120 | space, and printing information about GIFs.
121 |
122 | Usage: gifsicle [OPTION | FILE | FRAME]...
123 |
124 | Mode options: at most one, before any filenames.
125 | -m, --merge Merge mode: combine inputs, write stdout.
126 | -b, --batch Batch mode: modify inputs, write back to
127 | same filenames.
128 | -e, --explode Explode mode: write N files for each input,
129 | one per frame, to 'input.frame-number'.
130 | -E, --explode-by-name Explode mode, but write 'input.name'.
131 |
132 | General options: Also --no-OPTION for info and verbose.
133 | -I, --info Print info about input GIFs. Two -I's means
134 | normal output is not suppressed.
135 | --color-info, --cinfo --info plus colormap details.
136 | --extension-info, --xinfo --info plus extension details.
137 | --size-info, --sinfo --info plus compression information.
138 | -V, --verbose Prints progress information.
139 | -h, --help Print this message and exit.
140 | --version Print version number and exit.
141 | -o, --output FILE Write output to FILE.
142 | -w, --no-warnings Don't report warnings.
143 | --no-ignore-errors Quit on very erroneous input GIFs.
144 | --conserve-memory Conserve memory at the expense of speed.
145 | --multifile Support concatenated GIF files.
146 |
147 | Frame selections: #num, #num1-num2, #num1-, #name
148 |
149 | Frame change options:
150 | --delete FRAMES Delete FRAMES from input.
151 | --insert-before FRAME GIFS Insert GIFS before FRAMES in input.
152 | --append GIFS Append GIFS to input.
153 | --replace FRAMES GIFS Replace FRAMES with GIFS in input.
154 | --done Done with frame changes.
155 |
156 | Image options: Also --no-OPTION and --same-OPTION.
157 | -B, --background COL Make COL the background color.
158 | --crop X,Y+WxH, --crop X,Y-X2,Y2
159 | Crop the image.
160 | --crop-transparency Crop transparent borders off the image.
161 | --flip-horizontal, --flip-vertical
162 | Flip the image.
163 | -i, --interlace Turn on interlacing.
164 | -S, --logical-screen WxH Set logical screen to WxH.
165 | -p, --position X,Y Set frame position to (X,Y).
166 | --rotate-90, --rotate-180, --rotate-270, --no-rotate
167 | Rotate the image.
168 | -t, --transparent COL Make COL transparent.
169 |
170 | Extension options:
171 | --app-extension N D Add an app extension named N with data D.
172 | -c, --comment TEXT Add a comment before the next frame.
173 | --extension N D Add an extension number N with data D.
174 | -n, --name TEXT Set next frame's name.
175 | --no-comments, --no-names, --no-extensions
176 | Remove comments (names, extensions) from input.
177 | Animation options: Also --no-OPTION and --same-OPTION.
178 | -d, --delay TIME Set frame delay to TIME (in 1/100sec).
179 | -D, --disposal METHOD Set frame disposal to METHOD.
180 | -l, --loopcount[=N] Set loop extension to N (default forever).
181 | -O, --optimize[=LEVEL] Optimize output GIFs.
182 | -U, --unoptimize Unoptimize input GIFs.
183 | -j, --threads[=THREADS] Use multiple threads to improve speed.
184 |
185 | Whole-GIF options: Also --no-OPTION.
186 | --careful Write larger GIFs that avoid bugs in other
187 | programs.
188 | --change-color COL1 COL2 Change COL1 to COL2 throughout.
189 | -k, --colors N Reduce the number of colors to N.
190 | --color-method METHOD Set method for choosing reduced colors.
191 | -f, --dither Dither image after changing colormap.
192 | --gamma G Set gamma for color reduction [2.2].
193 | --lossy[=LOSSINESS] Alter image colors to shrink output file size
194 | at the cost of artifacts and noise.
195 | --resize WxH Resize the output GIF to WxH.
196 | --resize-width W Resize to width W and proportional height.
197 | --resize-height H Resize to height H and proportional width.
198 | --resize-fit WxH Resize if necessary to fit within WxH.
199 | --scale XFACTOR[xYFACTOR] Scale the output GIF by XFACTORxYFACTOR.
200 | --resize-method METHOD Set resizing method.
201 | --resize-colors N Resize can add new colors up to N.
202 | --transform-colormap CMD Transform each output colormap by shell CMD.
203 | --use-colormap CMAP Set output GIF's colormap to CMAP, which can
204 | be 'web', 'gray', 'bw', or a GIF file.
205 |
206 | Report bugs to .
207 | Too much information? Try 'gifsicle --help | more'.
208 | ```
209 |
--------------------------------------------------------------------------------
/BlogArchive/Swift 中文和日文分词.md:
--------------------------------------------------------------------------------
1 | Swift 内置的 CFStringTokenizer 和 NaturalLanguage 都可以实现各种常见的自然语言分词,包括不是用空格分割单词的日语和中文。
2 |
3 | CFStringTokenizer 实现分词
4 |
5 | ```
6 | func tokenize(text: String) -> [String] {
7 | let tokenize = CFStringTokenizerCreate(kCFAllocatorDefault, text as CFString?, CFRangeMake(0, text.count), kCFStringTokenizerUnitWord, CFLocaleCopyCurrent())
8 | CFStringTokenizerAdvanceToNextToken(tokenize)
9 | var range = CFStringTokenizerGetCurrentTokenRange(tokenize)
10 | var keyWords : [String] = []
11 | while range.length > 0 {
12 | let wRange = text.index(text.startIndex, offsetBy: range.location).. [String] {
34 | // 设置分割粒度,.word分词,.paragraph分段落,.sentence分句,document
35 | let tokenizer = NLTokenizer(unit: .word)
36 | tokenizer.string = text
37 | var keyWords : [String] = []
38 | tokenizer.enumerateTokens(in: text.startIndex.. 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 https://www.cnblogs.com/yangyxd/p/10449614.html
2 |
3 | 1. Flutter 是什么?
4 | ===============
5 |
6 | Flutter 是谷歌的移动 UI 框架,可以快速在 iOS 和 Android 上构建高质量的原生用户界面。 Flutter 可以与现有的代码一起工作。在全世界,Flutter 正在被越来越多的开发者和组织使用,并且 Flutter 是完全免费、开源的。
7 |
8 | 2. Flutter 特性有哪些?
9 | =================
10 |
11 | 快速开发(毫秒级热重载)
12 |
13 | * 绚丽 UI(内建漂亮的质感设计 Material Design 和 Cupertino Widget 和丰富平滑的动画效果和平台感知)
14 | * 响应式 (Reactive,用强大而灵活的 API 解决 2D、动画、手势、效果等难题)
15 | * 原生访问功能
16 | * 堪比原生性能
17 |
18 | 3. Flutter 和 Dart 的关系是什么?
19 | ==========================
20 |
21 | Flutter 是一个使用 Dart 语言开发的跨平台移动 UI 框架,通过自建绘制引擎,能高性能、高保真地进行移动开发。Dart 囊括了多数编程语言的优点,它更符合 Flutter 构建界面的方式。
22 |
23 | 4. Dart 语言的特性?
24 | ==============
25 |
26 | * Productive(生产力高,Dart 的语法清晰明了,工具简单但功能强大)
27 | * Fast(执行速度快,Dart 提供提前优化编译,以在移动设备和 Web 上获得可预测的高性能和快速启动。)
28 | * Portable(易于移植,Dart 可编译成 ARM 和 X86 代码,这样 Dart 移动应用程序可以在 iOS、Android 和其他地方运行)
29 | * Approachable(容易上手,充分吸收了高级语言特性,如果你已经知道 C++,C 语言,或者 Java,你可以在短短几天内用 Dart 来开发)
30 | * Reactive(响应式编程)
31 |
32 | 5. Dart 的一些重要概念?
33 | ================
34 |
35 | * 在 Dart 中,一切都是对象,所有的对象都是继承自 Object
36 | * Dart 是强类型语言,但可以用 var 或 dynamic 来声明一个变量,Dart 会自动推断其数据类型, dynamic 类似 c#
37 | * 没有赋初值的变量都会有默认值 null
38 | * Dart 支持顶层方法,如 main 方法,可以在方法内部创建方法
39 | * Dart 支持顶层变量,也支持类变量或对象变量
40 | * Dart 没有 public protected private 等关键字,如果某个变量以下划线(_)开头,代表这个变量在库中是私有的
41 |
42 | 6. dart 是值传递还是引用传递?
43 | ===================
44 |
45 | dart 是引用传递的。
46 |
47 | 7. Widget 和 element 和 RenderObject 之间的关系?
48 | =========================================
49 |
50 | * Widget 是用户界面的一部分, 并且是不可变的。
51 | * Element 是在树中特定位置 Widget 的实例。
52 | * RenderObject 是渲染树中的一个对象,它的层次结构是渲染库的核心。
53 |
54 | Widget 会被 inflate(填充)到 Element,并由 Element 管理底层渲染树。Widget 并不会直接管理状态及渲染, 而是通过 State 这个对象来管理状态。Flutter 创建 Element 的可见树,相对于 Widget 来说,是可变的,通常界面开发中,我们不用直接操作 Element, 而是由框架层实现内部逻辑。就如一个 UI 视图树中,可能包含有多个 TextWidget(Widget 被使用多次),但是放在内部视图树的视角,这些 TextWidget 都是填充到一个个独立的 Element 中。Element 会持有 renderObject 和 widget 的实例。记住,Widget 只是一个配置,RenderObject 负责管理布局、绘制等操作。
55 |
56 | 在第一次创建 Widget 的时候,会对应创建一个 Element, 然后将该元素插入树中。如果之后 Widget 发生了变化,则将其与旧的 Widget 进行比较,并且相应地更新 Element。重要的是,Element 不会被重建,只是更新而已。
57 |
58 | 8. mixin extends implement 之间的关系?
59 | =================================
60 |
61 | 继承(关键字 extends)、混入 mixins (关键字 with)、接口实现(关键字 implements)。这三者可以同时存在,前后顺序是 extends -> mixins -> implements。
62 |
63 | Flutter 中的继承是单继承,子类重写超类的方法要用 @Override,子类调用超类的方法要用 super。
64 |
65 | 在 Flutter 中,Mixins 是一种在多个类层次结构中复用类代码的方法。mixins 的对象是类,mixins 绝不是继承,也不是接口,而是一种全新的特性,可以 mixins 多个类,mixins 的使用需要满足一定条件。
66 |
67 | 9. 使用 mixins 的条件是什么?
68 | ====================
69 |
70 | 因为 mixins 使用的条件,随着 Dart 版本一直在变,这里讲的是 Dart2.1 中使用 mixins 的条件:
71 |
72 | mixins 类只能继承自 object
73 | mixins 类不能有构造函数
74 | 一个类可以 mixins 多个 mixins 类
75 | 可以 mixins 多个类,不破坏 Flutter 的单继承
76 |
77 | 10. mixin 怎么指定异常类型?
78 | ===================
79 |
80 | on 关键字可用于指定异常类型。 on 只能用于被 mixins 标记的类,例如 mixins X on A,意思是要 mixins X 的话,得先接口实现或者继承 A。这里 A 可以是类,也可以是接口,但是在 mixins 的时候用法有区别.
81 |
82 | on 一个类:
83 |
84 | [](javascript:void(0); "复制代码")
85 |
86 | ```
87 | class A {
88 | void a(){
89 | print("a");
90 | }
91 | }
92 |
93 |
94 | mixin X on A{
95 | void x(){
96 | print("x");
97 | }
98 | }
99 |
100 |
101 | class mixinsX extends A with X{
102 | }
103 |
104 | ```
105 |
106 | [](javascript:void(0); "复制代码")
107 |
108 | on 的是一个接口: 得首先实现这个接口,然后再用 mix
109 |
110 | [](javascript:void(0); "复制代码")
111 |
112 | ```
113 | class A {
114 | void a(){
115 | print("a");
116 | }
117 | }
118 |
119 | mixin X on A{
120 | void x(){
121 | print("x");
122 | }
123 | }
124 |
125 | class implA implements A{
126 | @override
127 | void a() {}
128 | }
129 |
130 | class mixinsX2 extends implA with X{
131 | }
132 |
133 | ```
134 |
135 | [](javascript:void(0); "复制代码")
136 |
137 | 11. Flutter main future mirotask 的执行顺序?
138 | ========================================
139 |
140 | 普通代码都是同步执行的,结束后会开始检查 microtask 中是否有任务,若有则执行,执行完继续检查 microtask,直到 microtask 列队为空。最后会去执行 event 队列(future)。
141 |
142 | 12. Future 和 Isolate 有什么区别?
143 | ===========================
144 |
145 | future 是异步编程,调用本身立即返回,并在稍后的某个时候执行完成时再获得返回结果。在普通代码中可以使用 await 等待一个异步调用结束。
146 |
147 | isolate 是并发编程,Dartm 有并发时的共享状态,所有 Dart 代码都在 isolate 中运行,包括最初的 main()。每个 isolate 都有它自己的堆内存,意味着其中所有内存数据,包括全局数据,都仅对该 isolate 可见,它们之间的通信只能通过传递消息的机制完成,消息则通过端口 (port) 收发。isolate 只是一个概念,具体取决于如何实现,比如在 Dart VM 中一个 isolate 可能会是一个线程,在 Web 中可能会是一个 Web Worker。
148 |
149 | 13. Stream 与 Future 是什么关系?
150 | ==========================
151 |
152 | Stream 和 Future 是 Dart 异步处理的核心 API。Future 表示稍后获得的一个数据,所有异步的操作的返回值都用 Future 来表示。但是 Future 只能表示一次异步获得的数据。而 Stream 表示多次异步获得的数据。比如界面上的按钮可能会被用户点击多次,所以按钮上的点击事件(onClick)就是一个 Stream 。简单地说,Future 将返回一个值,而 Stream 将返回多次值。Dart 中统一使用 Stream 处理异步事件流。Stream 和一般的集合类似,都是一组数据,只不过一个是异步推送,一个是同步拉取。
153 |
154 | 14. Stream 两种订阅模式?
155 | ==================
156 |
157 | Stream 有两种订阅模式:**单订阅 (single) **和 **多订阅(broadcast)**。单订阅就是只能有一个订阅者,而广播是可以有多个订阅者。这就有点类似于消息服务(Message Service)的处理模式。单订阅类似于点对点,在订阅者出现之前会持有数据,在订阅者出现之后就才转交给它。而广播类似于发布订阅模式,可以同时有多个订阅者,当有数据时就会传递给所有的订阅者,而不管当前是否已有订阅者存在。
158 | Stream 默认处于单订阅模式,所以同一个 stream 上的 listen 和其它大多数方法只能调用一次,调用第二次就会报错。但 Stream 可以通过 transform() 方法(返回另一个 Stream)进行连续调用。通过 Stream.asBroadcastStream() 可以将一个单订阅模式的 Stream 转换成一个多订阅模式的 Stream,isBroadcast 属性可以判断当前 Stream 所处的模式。
159 |
160 | 15. await for 如何使用?
161 | ===================
162 |
163 | await for 是不断获取 stream 流中的数据,然后执行循环体中的操作。它一般用在直到 stream 什么时候完成,并且必须等待传递完成之后才能使用,不然就会一直阻塞。
164 |
165 | [](javascript:void(0); "复制代码")
166 |
167 | ```
168 | Stream stream = new Stream.fromIterable(['不开心', '面试', '没', '过']);
169 | main() async{
170 | print('上午被开水烫了脚');
171 | await for(String s in stream){
172 | print(s);
173 | }
174 | print('晚上还没吃饭');
175 | }
176 |
177 | ```
178 |
179 | [](javascript:void(0); "复制代码")
180 |
181 | 16. Flutter 中的 Widget、State、Context 的核心概念?是为了解决什么问题?
182 | ====================================================
183 |
184 | **Widget**: 在 Flutter 中,几乎所有东西都是 Widget。将一个 Widget 想象为一个可视化的组件(或与应用可视化方面交互的组件),当你需要构建与布局直接或间接相关的任何内容时,你正在使用 Widget。
185 |
186 | **Widget 树**: Widget 以树结构进行组织。包含其他 Widget 的 widget 被称为父 Widget(或 widget 容器)。包含在父 widget 中的 widget 被称为子 Widget。
187 |
188 | **Context**: 仅仅是已创建的所有 Widget 树结构中的某个 Widget 的位置引用。简而言之,将 context 作为 widget 树的一部分,其中 context 所对应的 widget 被添加到此树中。一个 context 只从属于一个 widget,它和 widget 一样是链接在一起的,并且会形成一个 context 树。
189 |
190 | **State**: 定义了 StatefulWidget 实例的行为,它包含了用于” **交互 / 干预** “Widget 信息的行为和布局。应用于 State 的任何更改都会强制重建 Widget。
191 |
192 | 这些状态的引入,主要是为了解决多个部件之间的交互和部件自身状态的维护。
193 |
194 | 17. Widget 的两种类型是什么?
195 | ====================
196 |
197 | **StatelessWidget**: 一旦创建就不关心任何变化,在下次构建之前都不会改变。它们除了依赖于自身的配置信息(在父节点构建时提供)外不再依赖于任何其他信息。比如典型的 Text、Row、Column、Container 等,都是 StatelessWidget。它的生命周期相当简单:初始化、通过 build() 渲染。
198 |
199 | **StatefulWidget**: 在生命周期内,该类 Widget 所持有的数据可能会发生变化,这样的数据被称为 **State**,这些拥有动态内部数据的 Widget 被称为 StatefulWidget。比如复选框、Button 等。State 会与 Context 相关联,并且此关联是永久性的,State 对象将永远不会改变其 Context,即使可以在树结构周围移动,也仍将与该 context 相关联。当 **state 与 context 关联时**,state 被视为**已挂载**。StatefulWidget 由两部分组成,在初始化时必须要在 createState() 时初始化一个与之相关的 State 对象。
200 |
201 | 18. State 对象的初始化流程?
202 | ===================
203 |
204 | **initState**() : 一旦 State 对象被创建,initState 方法是第一个(构造函数之后)被调用的方法。可通过重写来执行额外的初始化,如初始化动画、控制器等。重写该方法时,应该首先调用 super.initState()。在 initState 中,无法真正使用 context,因为框架还没有完全将其与 state 关联。initState 在该 State 对象的生命周期内将不会再次调用。
205 |
206 | **didChangeDependencies**(): 这是第二个被调用的方法。在这一阶段,context 已经可用。如果你的 Widget 链接到了一个 InheritedWidget 并且 / 或者你需要初始化一些 listeners(基于 context),通常会重写该方法。
207 |
208 | **build(BuildContext context)**: 此方法在 didChangeDependencies()、didUpdateWidget() 之后被调用。每次 State 对象更新(或当 InheritedWidget 有新的通知时)都会调用该方法!我们一般都在 build 中来编写真正的功能代码。为了强制重建,可以在需要的时候调用 setState((){...}) 方法。
209 |
210 | **dispose()**: 此方法在 Widget 被废弃时调用。可重写该方法来执行一些清理操作(如解除 listeners),并在此之后立即调用 super.dispose()。
211 |
212 | 19. Widget 唯一标识 Key 有那几种?
213 | =========================
214 |
215 | 在 flutter 中,每个 widget 都是被唯一标识的。这个唯一标识在 build 或 rendering 阶段由框架定义。该标识对应于可选的 Key 参数,如果省略,Flutter 将会自动生成一个。
216 |
217 | 在 flutter 中,主要有 4 种类型的 Key:GlobalKey(确保生成的 Key 在整个应用中唯一,是很昂贵的,允许 element 在树周围移动或变更父节点而不会丢失状态)、LocalKey、UniqueKey、ObjectKey。
218 |
219 | 20. 什么是 Navigator? MaterialApp 做了什么?
220 | ====================================
221 |
222 | Navigator 是在 Flutter 中负责管理维护页面堆栈的导航器。MaterialApp 在需要的时候,会自动为我们创建 Navigator。Navigator.of(context),会使用 context 来向上遍历 Element 树,找到 MaterialApp 提供的_NavigatorState 再调用其 push/pop 方法完成导航操作。
--------------------------------------------------------------------------------
/BlogArchive/code-obfuscation-master.zip:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/BlogArchive/code-obfuscation-master.zip
--------------------------------------------------------------------------------
/BlogArchive/geph-macos.dmg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/BlogArchive/geph-macos.dmg
--------------------------------------------------------------------------------
/BlogArchive/iOS底层原理探索—OC对象的本质.md:
--------------------------------------------------------------------------------
1 | > 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 https://www.jianshu.com/p/ffd742041946
2 |
3 | 在探索 OC 对象的本质之前,我们要明白 Objective-C 的代码,底层的实现都是 C/C++ 代码。
4 |
5 | 
6 |
7 | OC 代码转化过程. png
8 |
9 | 而 OC 中的对象、类则是基于 C/C++ 的结构体来实现的。
10 |
11 | 我们可以通过将创建好的 OC 文件,转化成 C++ 文件来看一下 OC 对象的底层结构。
12 |
13 | OC 代码转换成 C++
14 | ------------
15 |
16 | 通过命令行将 OC 的 main.m 文件转换成 C++,生成 main.cpp。
17 |
18 | ```
19 | clang -rewrite-objc main.m -o main.cpp
20 |
21 |
22 |
23 | ```
24 |
25 | 需要注意这种方式没有指定运行平台和架构模式,我们可以通过命令行设置参数,来指定运行平台和架构模式
26 |
27 | ```
28 | xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc main.m -o main-arm64.cpp
29 |
30 |
31 |
32 | ```
33 |
34 | 生成的 main-arm64.cpp 文件就是 main.m 转换 c++ 后的文件,直接拖拽到工程中,就可以查看底层实现了。我们在 main-arm64.cpp 文件中搜索 NSObjcet,可以找到 NSObjcet_IMPL(IMPL 即 implementation 的缩写,代表实现)。
35 |
36 | ```
37 | struct NSObject_IMPL {
38 | Class isa;
39 | };
40 |
41 |
42 | ```
43 |
44 | 可以看到,NObject 的底层实现就是一个结构体。我们进一步查看 Class
45 |
46 | ```
47 | typedef struct objc_class *Class;
48 |
49 |
50 | ```
51 |
52 | 我们发现 Class 其实就是一个指针,指向了 objc_class 类型的结构体。
53 |
54 | > 通过以上探索我们可以得出总结,OC 中对象的底层实现都是通过 C\C++ 的结构体实现的。那么一个 OC 对象占据了多少内存空间呢?下面让我们用代码实际验证一下。
55 |
56 | 
57 |
58 | NSObject 对象占多少内存空间. png
59 |
60 | 通过代码我们创建了一个 NSObject 对象,分别调用了
61 |
62 | `class_getInstanceSize`
63 |
64 | 和
65 |
66 | `malloc_size`
67 |
68 | 方法来查看占据的内存空间。我们看到打印输出了 8 和 16,这是怎么回事呢?
69 |
70 | 我们通过查看 OC 源码可知,
71 |
72 | `class_getInstanceSize`
73 |
74 | 是
75 |
76 | **返回类的成员变量占据内存的大小**
77 |
78 | 。而
79 |
80 | `malloc_size`
81 |
82 | 是
83 |
84 | **获取 obj 指针指向内存的大小**
85 |
86 | 我们上文创建的 NSObject 对象 obj 的结构体只有一个成员:isa 指针,而指针在 64 位架构中占 8 个字节,所以第一次打印输出了 8。但是系统为 obj 对象分配了 16 个字节的内存,第二次打印输出 16。
87 |
88 | 
89 |
90 | NSObject 对象占据内存空间示意图. jpeg
91 |
92 | 上图中黄色区域系统为 obj 对象分配的 16 个字节的内存,但是 obj 对象结构体中只有一个 isa 指针,所以只占据了绿色区域的 8 个字节。这一点可以通过查看
93 |
94 | `alloc`
95 |
96 | 底层源码也可以证实:
97 |
98 | 
99 |
100 | alloc 源码. jpeg
101 |
102 | 通过
103 |
104 | `alloc`
105 |
106 | 底层源码可以看到,如果一个对象占据的内存小于 16 时,则会直接返回 16,也就是说,系统在为对象分配内存空间时,最小为 16 个字节。
107 |
108 | 至此我们知道了系统在创建一个对象的时候会为其分配最少 16 字节的内存空间,其中对象的`isa`指针占据 8 个字节。我们通过下面一道面试题继续深入了解 OC 对象的底层本质。
109 |
110 | > 在 64 位环境下,下面的代码会输出什么?
111 |
112 | ```
113 | @interface Person : NSObject
114 | {
115 | int _age;
116 | }
117 | @end
118 |
119 | @implementation Person
120 | @end
121 |
122 |
123 | @interface Student : Person
124 | {
125 | int _no;
126 | }
127 | @end
128 |
129 | @implementation Student
130 | @end
131 |
132 | int main(int argc, const char * argv[]) {
133 | @autoreleasepool {
134 |
135 | NSLog(@"%zd %zd",
136 | class_getInstanceSize([Person class]),
137 | class_getInstanceSize([Student class])
138 | );
139 | }
140 | return 0;
141 | }
142 |
143 |
144 | ```
145 |
146 | > 经过代码分析,这道面试题想问的其实就是一个 Person 对象和一个 Student 对象分别占据多少内存空间。但是需要注意的是 Person 对象和 Student 对象分别有一个实例变量、Student 继承自 Person 对象。
147 |
148 | 经过综合上文简单分析,我们可以简单画出 Person 对象和 Student 对象的内存结构示意图:
149 |
150 | 
151 |
152 | Person 对象和 Student 对象内存结构示意图. png
153 |
154 | 我们可以看到,在 Person 对象结构体中,有一个父类类型的结构体指针和一个
155 |
156 | `int`
157 |
158 | 类型成员变量
159 |
160 | `_age`
161 |
162 | ,分别占据内存空间为 8 字节和 4 字节。根据底层源码对象分配的最小内存空间为 16 可得,Person 对象占据的内存空间为 16。此处值得注意的是,根据
163 |
164 | **内存对齐**
165 |
166 | ,也可得出 Person 对象占据 16 个字节。
167 |
168 | 
169 |
170 | Person 对象内存示意图. jpeg
171 |
172 | 那么根据这个分析逻辑,Student 对象占据的内存空间是不是 20 或者 24 呢?答案当然是不对,虽然 Student 结构体中有 Person 类型的指针(16 个字节)和`int`类型成员变量`_no`(4 个字节),但是要注意的是上面 Person 对象占据的 16 个字节是没有完全占据完的,还留有 4 个字节的空白地址,系统会自动的把`int`类型成员变量`_no`放在这 4 个字节的空白地址中,所以 Student 对象也占据 16 个字节的内存空间。
173 |
174 | 
175 |
176 | Student 内存示意图. jpeg
177 |
178 | > 内存对齐:
179 | >
180 | > 1. 前面的地址必须是后面的地址整数倍, 不是就补齐。
181 | > 2. 整个结构体的地址必须是最大字节的整数倍。
182 |
183 | > OC 对象分为三种:
184 | > **实例对象(instance 对象)**
185 | > **类对象(class 对象)**
186 | > **元类对象(meta-class 对象)**
187 |
188 | 1、实例对象(instance 对象)
189 | -------------------
190 |
191 | **实例对象(instance 对象)**就是通过类的`alloc`出来的对象,每次调用`alloc`都会产生新的实例对象。例如:
192 |
193 | ```
194 | NSObjcet *obj1 = [[NSObjcet alloc] init];
195 | NSObjcet *obj2 = [[NSObjcet alloc] init];
196 |
197 |
198 | ```
199 |
200 | obj1 和 obj2 都是 NSObject 的实例对象,但是它们是不同的两个实例对象,分别占用两块不同的内存地址。
201 | 实例对象在内存中存储的信息包括:
202 | 1、`isa`指针
203 | 2、其他`成员变量`
204 |
205 | 
206 |
207 | 实例对象在内存中存储信息示意图. png
208 |
209 | 2、类对象(class 对象)
210 | ---------------
211 |
212 | **类对象(class 对象)就是**通过`class`方法或者 runtime 的`object_getClass`方法得到的 class 对象
213 |
214 | ```
215 | Class objClass1 = [obj1 class];
216 | Class objClass2 = [obj2 class];
217 | Class objClass3 = [NSObject class];
218 |
219 |
220 | Class objClass4 = object_getClass(obj1);
221 | Class objClass5 = object_getClass(obj2);
222 |
223 |
224 | ```
225 |
226 | objClass1-objClass5 都是 NSObject 的类对象(class 对象),且它们是同一个对象。
227 |
228 | > 每个类在内存中有且只有一个 class 对象
229 |
230 | 类对象在内存中存储的信息包括:
231 | 1、`isa`指针
232 | 2、`superClass`指针
233 | 3、类的`属性`信息(`@property`),类的成员变量信息(`ivar`)
234 | 4、类的`对象方法`信息(`instance method`),类的`协议`信息(`protocol`)
235 |
236 | 
237 |
238 | 类对象在内存中存储信息示意图. png
239 |
240 | 3、元类对象(meta-class 对象)
241 | ---------------------
242 |
243 | **元类对象(meta-class 对象)**就是通过 RunTime 的`object_getClass`方法得到的对象
244 |
245 | ```
246 | Class objectMetaClass = object_getClass([NSObject class]);
247 |
248 |
249 | ```
250 |
251 | objectMetaClass 就是 NSObject 的元类对象
252 |
253 | > 每个类在内存中有且只有一个元类对象
254 |
255 | 元类对象和类对象的内存结构是一样的,但是用途不一样,元类对象在内存中存储的信息包括:
256 | 1、`isa`指针
257 | 2、`superClass`指针
258 | 3、类的`类方法`信息(`class method`)
259 |
260 | 
261 |
262 | 元类对象在内存中存储信息示意图. png
263 |
264 | 以上我们了解了实例对象、类对象和元类对象的含义以及包含的内容,那么它们当中的`isa`指针和`superClass`指针分别指向哪里呢?
265 |
266 | isa 指针的指向
267 | ---------
268 |
269 | isa 指针指向用一张示意图来简单概括一下:
270 |
271 | 
272 |
273 | isa 指针指向示意图. jpeg
274 |
275 | 实例对象(instance 对象)的`isa`指针指向`class`。当调用对象方法时,通过实例对象的`isa`找到`class`,最后找到对象方法的实现进行调用
276 | 类对象(class 对象)的`isa`指针指向 meta-class。当调用类方法时,通过类对象的`isa`找到 meta-class,最后找到类方法的实现进行调用。
277 |
278 | class 的 superClass 指针的指向
279 | ------------------------
280 |
281 | class 的 superClass 指针指向用一张示意图来简单概括一下:
282 |
283 | 
284 |
285 | superClass 指针指向示意图. jpeg
286 |
287 | 图中举例 Student 继承自 Person,Person 继承自 NSObject。
288 |
289 | 当 Student 的实例对象要调用父类 Person 的对象方法时,会先通过
290 |
291 | `isa`
292 |
293 | 找到 Student 的
294 |
295 | `class`
296 |
297 | ,然后通过
298 |
299 | `class`
300 |
301 | 中的 superClass 找到父类 Person 的
302 |
303 | `class`
304 |
305 | ,最后找到对象方法的实现进行调用。
306 |
307 | meta-class 对象的 superClass 指针指向
308 | ------------------------------
309 |
310 | 
311 |
312 | meat-class 的 superClass 指针指向示意图. jpeg
313 |
314 | 同上,当 Student 的 class 要调用 Person 的类方法时,会先通过 isa 找到 Student 的 meta-class,然后通过 superClass 找到 Person 的 meta-class,最后找到类方法的实现进行调用。
315 |
316 | 这里当然要提一下非常经典的 isa 指向图,做进一步的总结:
317 |
318 | 
319 |
320 | 超神图. jpeg
321 |
322 | > 1、instance 的 isa 指向 clas
323 | > 2、class 的 isa 指向 meta-class
324 | > 3、meta-class 的 isa 指向基类的 meta-class,基类的 isa 指向自己
325 | > 4、class 的 superClass 指向父类的 class,如果没有父类,则 superClass 指针为 nil
326 | > 5、meta-class 的 superClass 指向父类的 meta-class,基类的 meta-class 的 superClass 指向基类的 class
327 | > 6、instance 调用对象方法的轨迹:通过 isa 找到 class,方法不存在,就通过 supercla 逐层父类里找,有就实现,如果找到基类仍没有找到,就会抛出`unrecognized selector sent to instance`异常
328 | > 7、class 调用类方法的轨迹:通过 isa 找到 meta-class,方法不存在,就通过 superClass 逐层父类里找。
329 |
330 | **补充:**
331 | 相信很多人在查看源码或者看一些底层博客的时候,经常会看到下面一段代码,来讲述 class 的内部结构:
332 |
333 | ```
334 | typedef struct objc_class *Class;
335 |
336 | struct objc_class {
337 | Class _Nonnull isa OBJC_ISA_AVAILABILITY;
338 |
339 | #if !__OBJC2__
340 | Class _Nullable super_class OBJC2_UNAVAILABLE;
341 | const char * _Nonnull name OBJC2_UNAVAILABLE;
342 | long version OBJC2_UNAVAILABLE;
343 | long info OBJC2_UNAVAILABLE;
344 | long instance_size OBJC2_UNAVAILABLE;
345 | struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE;
346 | struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE;
347 | struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE;
348 | struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE;
349 | #endif
350 |
351 | } OBJC2_UNAVAILABLE;
352 |
353 |
354 | ```
355 |
356 | 这段源码其实讲述的也是 class 内部结构,包含成员变量列表、方法列表、方法缓存以及协议列表。细心的人可能会发现,这段代码里面是有`if`判断条件的:
357 |
358 | 判断条件是非 OC2.0 版本,也就是说在 OC2.0 之前的版本中,class 底层的结构体中包含上面代码所讲述的,但我们现在所用的最新版肯定是 OC2.0 版本了,所以这段代码就不再使用了。
359 |
360 | 新的 class 底层的 objc_class 结构体:
361 |
362 | 
363 |
364 | objc_class 结构体. jpeg
365 |
366 | 可以看到结构体中只包含`isa`、`superclass`、`cache`和`bits`。而`bits`经过`& FAST_DATA_MASK`之后,会得到`struct class_rw_t`这样一个结构体:
367 |
368 | 
369 |
370 | class_rw_t.jpeg
371 |
372 | > rw 代表 readwrite,可读可写
373 | > t 代表 table,列表
374 |
375 | `struct class_rw_t`结构体中就包含了方法列表、属性列表以及协议列表,这些都是可读可写的。其中还包含一个`struct class_ro_t`的结构体:
376 |
377 | 
378 |
379 | class_ro_t.jpeg
380 |
381 | > ro 代表 readonly,只读
382 |
383 | `struct class_ro_t`的结构体中包含了 instance 对象占用的内存空间、类名以及成员变量列表,当然这些都是只读的。
384 |
385 | **一个 NSObject 对象占用多少内存?**
386 | 答:系统会为一个 NSObject 对象分配最少 16 个字节的内存空间。一个指针变量所占用的大小(64bit 占 8 个字节,32bit 占 4 个字节)
387 | **对象的 isa 指针指向哪里?**
388 | 答:instance 对象的`isa`指针指向 class 对象,class 对象的`isa`指针指向 meta-class 对象,meta-class 对象的`isa`指针指向基类的 meta-class 对象,基类自己的`isa`指针指向自己。
389 | **OC 的类信息存放在哪里?**
390 | 答:成员变量的具体值存放在实例对象(instance 对象);对象方法,协议,属性,成员变量信息存放在类对象(class 对象);类方法信息存放在元类对象(meta-class 对象)。
391 |
392 | > 本文如果对你有所帮助,点亮喜欢支持一下
393 | > 更多底层知识,扫码关注公众号
394 | > iOS 进阶
395 | >
396 | > 
397 | >
398 | > 我的二维码. jpg
--------------------------------------------------------------------------------
/BlogArchive/simpread-Flutter 布局 - Baseline、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth 详解 - Flutter 开发社区.md:
--------------------------------------------------------------------------------
1 | > 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 https://www.flutter123.net/Article/Detail/37
2 |
3 | 本文主要介绍 Flutter 布局中的 Baseline、FractionallySizedBox、IntrinsicHeight、IntrinsicWidth 四种控件,详细介绍了其布局行为以及使用场景,并对源码进行了分析。
4 |
5 | 1. Baseline
6 | A widget that positions its child according to the child's baseline.
7 |
8 | 1.1 简介
9 | Baseline 这个控件,做过移动端开发的都会了解过,一般文字排版的时候,可能会用到它。它的作用很简单,根据 child 的 baseline,来调整 child 的位置。例如两个字号不一样的文字,希望底部在一条水平线上,就可以使用这个控件,是一个非常基础的控件。
10 |
11 | 关于字符的 Baseline,可以看下下面这张图,这具体就涉及到了字体排版,感兴趣的同学可以自行了解。
12 |
13 | Baseline
14 |
15 | 1.2 布局行为
16 | Baseline 控件布局行为分为两种情况:
17 |
18 | 如果 child 有 baseline,则根据 child 的 baseline 属性,调整 child 的位置;
19 | 如果 child 没有 baseline,则根据 child 的 bottom,来调整 child 的位置。
20 | 1.3 继承关系
21 | Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > Baseline
22 | 1.4 示例代码
23 | new Row(
24 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
25 | children: [
26 | new Baseline(
27 | baseline: 50.0,
28 | baselineType: TextBaseline.alphabetic,
29 | child: new Text(
30 | 'TjTjTj',
31 | style: new TextStyle(
32 | fontSize: 20.0,
33 | textBaseline: TextBaseline.alphabetic,
34 | ),
35 | ),
36 | ),
37 | new Baseline(
38 | baseline: 50.0,
39 | baselineType: TextBaseline.alphabetic,
40 | child: new Container(
41 | width: 30.0,
42 | height: 30.0,
43 | color: Colors.red,
44 | ),
45 | ),
46 | new Baseline(
47 | baseline: 50.0,
48 | baselineType: TextBaseline.alphabetic,
49 | child: new Text(
50 | 'RyRyRy',
51 | style: new TextStyle(
52 | fontSize: 35.0,
53 | textBaseline: TextBaseline.alphabetic,
54 | ),
55 | ),
56 | ),
57 | ],
58 | )
59 | 上述运行结果是左右两个文本跟中间的 Container 底部在一个水平线上,这也印证了 Baseline 的布局行为。
60 |
61 | Baseline 样例
62 |
63 | 1.5 源码解析
64 | const Baseline({
65 | Key key,
66 | @required this.baseline,
67 | @required this.baselineType,
68 | Widget child
69 | })
70 | 1.5.1 属性解析
71 | baseline:baseline 数值,必须要有,从顶部算。
72 |
73 | baselineType:bseline 类型,也是必须要有的,目前有两种类型:
74 |
75 | alphabetic:对齐字符底部的水平线;
76 | ideographic:对齐表意字符的水平线。
77 | 1.5.2 源码
78 | 我们来看看源码中具体计算尺寸的这段代码
79 |
80 | child.layout(constraints.loosen(), parentUsesSize: true);
81 | final double childBaseline = child.getDistanceToBaseline(baselineType);
82 | final double actualBaseline = baseline;
83 | final double top = actualBaseline - childBaseline;
84 | final BoxParentData childParentData = child.parentData;
85 | childParentData.offset = new Offset(0.0, top);
86 | final Size childSize = child.size;
87 | size = constraints.constrain(new Size(childSize.width, top + childSize.height));
88 | getDistanceToBaseline 这个函数是获取 baseline 数值的,存在的话,就取这个值,不存在的话,则取其高度。
89 |
90 | 整体的计算过程:
91 |
92 | 获取 child 的 baseline 值;
93 | 计算出 top 值,其为 baseline - childBaseline,这个值有可能为负数;
94 | 计算出 Baseline 控件尺寸,宽度为 child 的,高度则为 top + childSize.height。
95 | 1.6 使用场景
96 | 跟字符对齐相关的会用到,其他场景暂时没有想到。
97 |
98 | 2. FractionallySizedBox
99 | A widget that sizes its child to a fraction of the total available space
100 |
101 | 2.1 简介
102 | FractionallySizedBox 控件会根据现有空间,来调整 child 的尺寸,所以说 child 就算设置了具体的尺寸数值,也不起作用。
103 |
104 | 2.2 布局行为
105 | FractionallySizedBox 的布局行为主要跟它的宽高因子两个参数有关,当参数为 null 或者有具体数值的时候,布局表现不一样。当然,还有一个辅助参数 alignment,作为对齐方式进行布局。
106 |
107 | 当设置了具体的宽高因子,具体的宽高则根据现有空间宽高 * 因子,有可能会超出父控件的范围,当宽高因子大于 1 的时候;
108 | 当没有设置宽高因子,则填满可用区域;
109 | 2.3 继承关系
110 | Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > FractionallySizedBox
111 | 2.4 示例代码
112 | new Container(
113 | color: Colors.blue,
114 | height: 150.0,
115 | width: 150.0,
116 | padding: const EdgeInsets.all(10.0),
117 | child: new FractionallySizedBox(
118 | alignment: Alignment.topLeft,
119 | widthFactor: 1.5,
120 | heightFactor: 0.5,
121 | child: new Container(
122 | color: Colors.red,
123 | ),
124 | ),
125 | )
126 | 运行效果如下所示
127 |
128 | FractionallySizedBox 例子
129 |
130 | 2.5 源码解析
131 | const FractionallySizedBox({
132 | Key key,
133 | this.alignment = Alignment.center,
134 | this.widthFactor,
135 | this.heightFactor,
136 | Widget child,
137 | })
138 | 2.5.1 属性解析
139 | alignment:对齐方式,不能为 null。
140 |
141 | widthFactor:宽度因子,跟之前介绍的控件类似,宽度乘以这个值,就是最后的宽度。
142 |
143 | heightFactor:高度因子,用作计算最后实际高度的。
144 |
145 | 其中 widthFactor 和 heightFactor 都有一个规则
146 |
147 | 如果不为 null,那么实际的最大宽高度则为 child 的宽高乘以这个因子;
148 | 如果为 null,那么 child 的宽高则会尽量充满整个区域。
149 | 2.5.2 源码
150 | FractionallySizedBox 内部具体渲染是由 RenderFractionallySizedOverflowBox 来实现的,通过命名就可以看出,这个控件可能会 Overflow。
151 |
152 | 我们直接看实际计算尺寸的代码
153 |
154 | double minWidth = constraints.minWidth;
155 | double maxWidth = constraints.maxWidth;
156 | if (_widthFactor != null) {
157 | final double width = maxWidth * _widthFactor;
158 | minWidth = width;
159 | maxWidth = width;
160 | }
161 | double minHeight = constraints.minHeight;
162 | double maxHeight = constraints.maxHeight;
163 | if (_heightFactor != null) {
164 | final double height = maxHeight * _heightFactor;
165 | minHeight = height;
166 | maxHeight = height;
167 | }
168 | 源代码中,根据宽高因子是否存在,来进行相对应的尺寸计算。这个过程非常简单,不再赘述。
169 |
170 | 2.6 使用场景
171 | 当需要在一个区域里面取百分比尺寸的时候,可以使用这个,比方说,高度 40% 宽度 70% 的区域。当然,AspectRatio 也可以达到近似的效果。
172 |
173 | 3. IntrinsicHeight
174 | A widget that sizes its child to the child's intrinsic height.
175 |
176 | 3.1 简介
177 | IntrinsicHeight 的作用是调整 child 到固定的高度。这个控件笔者也是看了很久,不知道它的作用是什么,官方说这个很有用,但是应该尽量少用,因为其效率问题。
178 |
179 | 3.2 布局行为
180 | 这个控件的作用,是将可能高度不受限制的 child,调整到一个合适并且合理的尺寸。
181 |
182 | 3.3 继承关系
183 | Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > IntrinsicHeight
184 | 3.4 示例代码
185 | new IntrinsicHeight(
186 | child: new Row(
187 | mainAxisAlignment: MainAxisAlignment.spaceBetween,
188 | children: [
189 | new Container(color: Colors.blue, width: 100.0),
190 | new Container(color: Colors.red, width: 50.0,height: 50.0,),
191 | new Container(color: Colors.yellow, width: 150.0),
192 | ],
193 | ),
194 | );
195 | IntrinsicHeight 例子
196 |
197 | 当没有 IntrinsicHeight 包裹着,可以看到,第一三个 Container 高度是不受限制的,当外层套一个 IntrinsicHeight,第一三个 Container 高度就调整到第二个一样的高度。
198 |
199 | 3.5 源码解析
200 | 构造函数如下:
201 |
202 | const IntrinsicHeight({Key key, Widget child})
203 | 3.5.1 属性解析
204 | 除了 child,没有提供额外的属性。
205 |
206 | 3.5.2 源码
207 | 当 child 不为 null 的时候,具体的布局代码如下:
208 |
209 | BoxConstraints childConstraints = constraints;
210 | if (!childConstraints.hasTightHeight) {
211 | final double height = child.getMaxIntrinsicHeight(childConstraints.maxWidth);
212 | assert(height.isFinite);
213 | childConstraints = childConstraints.tighten(height: height);
214 | }
215 | child.layout(childConstraints, parentUsesSize: true);
216 | size = child.size;
217 | 首先会检测是否只有一个高度值满足约束条件,如果不是的话,则返回一个最小的高度。然后调整尺寸。
218 |
219 | 3.6 使用场景
220 | 说老实话,不知道在什么场景使用,可以替代的控件也有的。谷歌说很有用,效率会有问题,建议一般的就别用了。
221 |
222 | 4. IntrinsicWidth
223 | A widget that sizes its child to the child's intrinsic width.
224 |
225 | 4.1 简介
226 | IntrinsicWidth 从描述看,跟 IntrinsicHeight 类似,一个是调整高度,一个是调整宽度。同样是会存在效率问题,能别使用就尽量别使用。
227 |
228 | 4.2 布局行为
229 | IntrinsicWidth 不同于 IntrinsicHeight,它包含了额外的两个参数,stepHeight 以及 stepWidth。而 IntrinsicWidth 的布局行为跟这两个参数相关。
230 |
231 | 当 stepWidth 不是 null 的时候,child 的宽度将会是 stepWidth 的倍数,当 stepWidth 值比 child 最小宽度小的时候,这个值不起作用;
232 | 当 stepWidth 为 null 的时候,child 的宽度是 child 的最小宽度;
233 | 当 stepHeight 不为 null 的时候,效果跟 stepWidth 相同;
234 | 当 stepHeight 为 null 的时候,高度取最大高度。
235 | 4.3 继承关系
236 | Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > IntrinsicWidth
237 | 4.4 示例代码
238 | new Container(
239 | color: Colors.green,
240 | padding: const EdgeInsets.all(5.0),
241 | child: new IntrinsicWidth(
242 | stepHeight: 450.0,
243 | stepWidth: 300.0,
244 | child: new Column(
245 | children: [
246 | new Container(color: Colors.blue, height: 100.0),
247 | new Container(color: Colors.red, width: 150.0, height: 100.0),
248 | new Container(color: Colors.yellow, height: 150.0,),
249 | ],
250 | ),
251 | ),
252 | )
253 | IntrinsicWidth 例子
254 |
255 | 分别对 stepWidth 以及 stepHeight 设置不同的值,可以看到不同的效果,当 step 值比最小宽高小的时候,这个值其实是不起作用的。感兴趣的同学可以自己试试。
256 |
257 | 4.5 源码解析
258 | 构造函数
259 |
260 | const IntrinsicWidth({Key key, this.stepWidth, this.stepHeight, Widget child})
261 | 4.5.1 属性解析
262 | stepWidth:可以为 null,效果参看上面所说的布局行为。
263 |
264 | stepHeight:可以为 null,效果参看上面所说的布局行为。
265 |
266 | 4.5.2 源码
267 | 我们先来看看布局代码中_applyStep 函数
268 |
269 | static double _applyStep(double input, double step) {
270 | assert(input.isFinite);
271 | if (step == null)
272 | return input;
273 | return (input / step).ceil() * step;
274 | }
275 | 如果存在 step 数值的话,则会是 step 的倍数,如果 step 为 null,则返回原始的尺寸。
276 |
277 | 接下来我们看看 child 不为 null 时候的布局代码
278 |
279 | BoxConstraints childConstraints = constraints;
280 | if (!childConstraints.hasTightWidth) {
281 | final double width = child.getMaxIntrinsicWidth(childConstraints.maxHeight);
282 | assert(width.isFinite);
283 | childConstraints = childConstraints.tighten(width: _applyStep(width, _stepWidth));
284 | }
285 | if (_stepHeight != null) {
286 | final double height = child.getMaxIntrinsicHeight(childConstraints.maxWidth);
287 | assert(height.isFinite);
288 | childConstraints = childConstraints.tighten(height: _applyStep(height, _stepHeight));
289 | }
290 | child.layout(childConstraints, parentUsesSize: true);
291 | size = child.size;
292 | 宽度方面的布局跟 IntrinsicHeight 高度部分相似,只是多了一个 step 的额外数值。总体的布局表现跟上面分析的布局行为一致,根据 step 值是否是 null 来进行判断,但是注意其对待高度与宽度的表现略有差异。
293 |
294 | 4.6 使用场景
295 | 这个控件,说老实话,笔者还是不知道该在什么场景下使用,可能会有些特殊的场景。但是从 IntrinsicWidth 与 IntrinsicHeight 布局差异看,Flutter 基础控件封的确实很随性,一些可有可无甚至是重复的控件,我觉得精简精简挺好的,哈哈。
296 |
297 | 5. 后话
298 | 笔者建了一个 Flutter 学习相关的项目,Github 地址,里面包含了笔者写的关于 Flutter 学习相关的一些文章,会定期更新,也会上传一些学习 Demo,欢迎大家关注。
299 |
300 | 6. 参考
301 | Baseline class
302 | 基线
303 | FractionallySizedBox class
304 | IntrinsicHeight class
305 | IntrinsicWidth class
--------------------------------------------------------------------------------
/BlogArchive/simpread-Flutter 布局 - FittedBox、AspectRatio、ConstrainedBox 详解 - Flutter 开发社区.md:
--------------------------------------------------------------------------------
1 | > 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 https://www.flutter123.net/Article/Detail/36
2 |
3 | 本文主要介绍 Flutter 布局中的 FittedBox、AspectRatio、ConstrainedBox,详细介绍了其布局行为以及使用场景,并对源码进行了分析。
4 |
5 | 1. FittedBox
6 | Scales and positions its child within itself according to fit.
7 |
8 | 1.1 简介
9 | 按照其官方的介绍,它主要做了两件事情,缩放(Scale)以及位置调整(Position)。
10 |
11 | FittedBox 会在自己的尺寸范围内缩放并且调整 child 位置,使得 child 适合其尺寸。做过移动端的,可能会联想到 ImageView 控件,它是将图片在其范围内,按照规则,进行缩放位置调整。FittedBox 跟 ImageView 是有些类似的,可以猜测出,它肯定有一个类似于 ScaleType 的属性。
12 |
13 | 1.2 布局行为
14 | FittedBox 的布局行为还算简单,官方没有给出说明,我在这里简单说一下。由于 FittedBox 是一个容器,需要让其 child 在其范围内缩放,因此其布局行为分两种情况:
15 |
16 | 如果外部有约束的话,按照外部约束调整自身尺寸,然后缩放调整 child,按照指定的条件进行布局;
17 | 如果没有外部约束条件,则跟 child 尺寸一致,指定的缩放以及位置属性将不起作用。
18 | 1.3 继承关系
19 | Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > FittedBox
20 | 从继承关系可以看出,FittedBox 控件是一个基础控件。
21 |
22 | 1.4 示例代码
23 | new Container(
24 | color: Colors.amberAccent,
25 | width: 300.0,
26 | height: 300.0,
27 | child: new FittedBox(
28 | fit: BoxFit.contain,
29 | alignment: Alignment.topLeft,
30 | child: new Container(
31 | color: Colors.red,
32 | child: new Text("FittedBox"),
33 | ),
34 | ),
35 | )
36 | 写了一个很简单的例子,加入 Container 是为了加颜色显示两个区域,读者可以试着修改 fit 以及 alignment 查看其不同的效果。
37 |
38 | 1.5 源码解析
39 | const FittedBox({
40 | Key key,
41 | this.fit: BoxFit.contain,
42 | this.alignment: Alignment.center,
43 | Widget child,
44 | })
45 | 1.5.1 属性解析
46 | fit:缩放的方式,默认的属性是 BoxFit.contain,child 在 FittedBox 范围内,尽可能的大,但是不超出其尺寸。这里注意一点,contain 是保持着 child 宽高比的大前提下,尽可能的填满,一般情况下,宽度或者高度达到最大值时,就会停止缩放。
47 |
48 | BoxFit 布局表现
49 |
50 | alignment:对齐方式,默认的属性是 Alignment.center,居中显示 child。
51 |
52 | 1.5.2 源码
53 | 构造函数如下:
54 |
55 | @override
56 | RenderFittedBox createRenderObject(BuildContext context) {
57 | return new RenderFittedBox(
58 | fit: fit,
59 | alignment: alignment,
60 | textDirection: Directionality.of(context),
61 | );
62 | }
63 | FittedBox 具体实现是由 RenderFittedBox 进行的。不知道读者有没有发现,目前的一些基础控件,继承自 RenderObjectWidget 的,widget 本身都只是存储了一些配置信息,真正的绘制渲染,则是由内部的 createRenderObject 所调用的 RenderObject 去实现的。
64 |
65 | RenderFittedBox 具体的布局代码如下:
66 |
67 | if (child != null) {
68 | child.layout(const BoxConstraints(), parentUsesSize: true);
69 | // 如果 child 不为 null,则按照 child 的尺寸比率缩放 child 的尺寸
70 | size = constraints.constrainSizeAndAttemptToPreserveAspectRatio(child.size);
71 | _clearPaintData();
72 | } else {
73 | // 如果 child 为 null,则按照最小尺寸进行布局
74 | size = constraints.smallest;
75 | }
76 | 1.6 使用场景
77 | FittedBox 在目前的项目中还未用到过。对于需要缩放调整位置处理的,一般都是图片。笔者一般都是使用 Container 中的 decoration 属性去实现相应的效果。对于其他控件需要缩放以及调整位置的,目前还没有遇到使用场景,大家只需要知道有这么一个控件,可以实现这个功能即可。
78 |
79 | 2. AspectRatio
80 | A widget that attempts to size the child to a specific aspect ratio.
81 |
82 | 2.1 简介
83 | AspectRatio 的作用是调整 child 到设置的宽高比,这种控件在其他移动端平台上一般都不会提供,Flutter 之所以提供,我想最大的原因,可能就是自定义起来特别麻烦吧。
84 |
85 | 2.2 布局行为
86 | AspectRatio 的布局行为分为两种情况:
87 |
88 | AspectRatio 首先会在布局限制条件允许的范围内尽可能的扩展,widget 的高度是由宽度和比率决定的,类似于 BoxFit 中的 contain,按照固定比率去尽量占满区域。
89 | 如果在满足所有限制条件过后无法找到一个可行的尺寸,AspectRatio 最终将会去优先适应布局限制条件,而忽略所设置的比率。
90 | 2.3 继承关系
91 | Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > AspectRatio
92 | 从继承关系看,AspectRatio 是基础的布局控件。
93 |
94 | 2.4 示例代码
95 | new Container(
96 | height: 200.0,
97 | child: new AspectRatio(
98 | aspectRatio: 1.5,
99 | child: new Container(
100 | color: Colors.red,
101 | ),
102 | ),
103 | );
104 | 示例代码是定义了一个高度为 200 的区域,内部 AspectRatio 比率设置为 1.5,最终 AspectRatio 的是宽 300 高 200 的一个区域。
105 |
106 | 2.5 源码解析
107 | 构造函数如下:
108 |
109 | const AspectRatio({
110 | Key key,
111 | @required this.aspectRatio,
112 | Widget child
113 | })
114 | 构造函数只包含了一个 aspectRatio 属性,其中 aspectRatio 不能为 null。
115 |
116 | 2.5.1 属性解析
117 | aspectRatio:aspectRatio 是宽高比,最终可能不会根据这个值去布局,具体则要看综合因素,外层是否允许按照这种比率进行布局,只是一个参考值。
118 |
119 | 2.5.2 源码
120 | @override
121 | RenderAspectRatio createRenderObject(BuildContext context) => new RenderAspectRatio(aspectRatio: aspectRatio);
122 | 经过前面一些控件的解析,我想大家对这种构造应该不会再陌生了,绘制都是交由 RenderObject 去完成的,这里则是由 RenderAspectRatio 去完成具体的绘制工作。
123 |
124 | RenderAspectRatio 的构造函数中会对 aspectRatio 做一些检测(assert)
125 |
126 | aspectRatio 不能为 null;
127 | aspectRatio 必须大于 0;
128 | aspectRatio 必须是有限的。
129 | 接下来我们来看一下 RenderAspectRatio 的具体尺寸计算函数:
130 |
131 | 如果限制条件为 isTight,则返回最小的尺寸(constraints.smallest);
132 | if (constraints.isTight)
133 | return constraints.smallest;
134 | 如果宽度为有限的值,则将高度设置为 width / _aspectRatio。 如果宽度为无限,则将高度设为最大高度,宽度设为 height * _aspectRatio;
135 | if (width.isFinite) {
136 | height = width / _aspectRatio;
137 | } else {
138 | height = constraints.maxHeight;
139 | width = height * _aspectRatio;
140 | }
141 | 接下来则是在限制范围内调整宽高,总体思想则是宽度优先,大于最大值则设为最大值,小于最小值,则设为最小值。
142 | 如果宽度大于最大宽度,则将其设为最大宽度,高度设为 width / _aspectRatio;
143 |
144 | if (width> constraints.maxWidth) {
145 | width = constraints.maxWidth;
146 | height = width / _aspectRatio;
147 | }
148 | 如果高度大于最大高度,则将其设为最大高度,宽度设为 height * _aspectRatio;
149 |
150 | if (height> constraints.maxHeight) {
151 | height = constraints.maxHeight;
152 | width = height * _aspectRatio;
153 | }
154 | 如果宽度小于最小宽度,则将其设为最小宽度,高度设为 width / _aspectRatio;
155 |
156 | if (width < constraints.minWidth) {
157 | width = constraints.minWidth;
158 | height = width / _aspectRatio;
159 | }
160 | 如果高度小于最小高度,则将其设为最小高度,宽度设为 height * _aspectRatio。
161 |
162 | if (height < constraints.minHeight) {
163 | height = constraints.minHeight;
164 | width = height * _aspectRatio;
165 | }
166 | 2.6 使用场景
167 | AspectRatio 适用于需要固定宽高比的情景下。笔者最近使用这个控件的场景是相机,相机的预览尺寸都是固定的几个值,因此不能随意去设置相机的显示区域,必须按照比率进行显示,否则会出现拉伸的情况。除此之外,倒是用的不多。
168 |
169 | 3. ConstrainedBox
170 | A widget that imposes additional constraints on its child.
171 |
172 | 3.1 简介
173 | 这个控件的作用是添加额外的限制条件(constraints)到 child 上,本身挺简单的,可以被一些控件替换使用。Flutter 的布局控件体系,梳理着发现确实有点乱,感觉总体思想是缺啥就造啥,哈哈。
174 |
175 | 3.2 布局行为
176 | ConstrainedBox 的布局行为非常简单,取决于设置的限制条件,而关于父子节点的限制因素生效优先级,可以查看之前的文章,在这里就不做具体叙述了。
177 |
178 | 3.3 继承关系
179 | Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > ConstrainedBox
180 | ConstrainedBox 也是一个基础的布局控件。
181 |
182 | 3.4 示例代码
183 | new ConstrainedBox(
184 | constraints: const BoxConstraints(
185 | minWidth: 100.0,
186 | minHeight: 100.0,
187 | maxWidth: 150.0,
188 | maxHeight: 150.0,
189 | ),
190 | child: new Container(
191 | width: 200.0,
192 | height: 200.0,
193 | color: Colors.red,
194 | ),
195 | );
196 | 例子也挺简单的,在一个宽高 200.0 的 Container 上添加一个约束最大最小宽高的 ConstrainedBox,实际的显示中,则是一个宽高为 150.0 的区域。
197 |
198 | 3.5 源码解析
199 | 构造函数如下:
200 |
201 | ConstrainedBox({
202 | Key key,
203 | @required this.constraints,
204 | Widget child
205 | })
206 | 包含了一个 constraints 属性,且不能为 null。
207 |
208 | 3.5.1 属性解析
209 | constraints:添加到 child 上的额外限制条件,其类型为 BoxConstraints。BoxConstraints 的作用是干啥的呢?其实很简单,就是限制各种最大最小宽高。说到这里插一句,double.infinity 在 widget 布局的时候是合法的,也就说,例如想最大的扩展宽度,可以将宽度值设为 double.infinity。
210 |
211 | 3.5.2 源码
212 | @override
213 | RenderConstrainedBox createRenderObject(BuildContext context) {
214 | return new RenderConstrainedBox(additionalConstraints: constraints);
215 | }
216 | RenderConstrainedBox 实现其绘制。其具体的布局表现分两种情况:
217 |
218 | 如果 child 不为 null,则将限制条件加在 child 上;
219 | 如果 child 为 null,则会尽可能的缩小尺寸。
220 | 具体代码如下:
221 |
222 | @override
223 | void performLayout() {
224 | if (child != null) {
225 | child.layout(_additionalConstraints.enforce(constraints), parentUsesSize: true);
226 | size = child.size;
227 | } else {
228 | size = _additionalConstraints.enforce(constraints).constrain(Size.zero);
229 | }
230 | }
231 | 3.6 使用场景
232 | 需要添加额外的约束条件可以使用此控件,例如设置最小宽高,尽可能的占用区域等等。笔者在实际开发中使用的倒不是很多,倒不是说这个控件不好使用,而是好多约束因素是综合的,例如需要额外的设置 margin、padding 属性能,因此单独再套个这个就显得很繁琐了。
233 |
234 | 3.7 关于 UnconstrainedBox
235 | 这个控件不做详细介绍了,它跟 ConstrainedBox 相反,是不添加任何约束条件到 child 上,让 child 按照其原始的尺寸渲染。
236 |
237 | 很神奇是吧,我也觉得,其实它的作用就是给 child 一个尽可能大的空间,不加约束的让其显示。用处我暂时木有想到。只能说 Flutter 生产 Widget 很随性。
238 |
239 | 4. 后话
240 | 笔者建的一个 Flutter 学习相关的项目,Github 地址,里面包含了笔者写的关于 Flutter 学习相关的一些文章,会定期更新,也会上传一些学习 demo,欢迎大家关注。
241 |
242 | 5. 参考
243 | FittedBox class
244 | BoxFit enum
245 | AspectRatio class
246 | ConstrainedBox class
247 | BoxConstraints class
248 | UnconstrainedBox class
--------------------------------------------------------------------------------
/BlogArchive/simpread-Flutter 布局 - LimitedBox、Offstage、OverflowBox、SizedBox 详解 - Flutter 开发社区.md:
--------------------------------------------------------------------------------
1 | > 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 https://www.flutter123.net/Article/Detail/38
2 |
3 | 本文主要介绍 Flutter 布局中的 LimitedBox、Offstage、OverflowBox、SizedBox 四种控件,详细介绍了其布局行为以及使用场景,并对源码进行了分析。
4 |
5 | 1. LimitedBox
6 | A box that limits its size only when it's unconstrained.
7 |
8 | 1.1 简介
9 | LimitedBox,通过字面意思,也可以猜测出这个控件的作用,是限制类型的控件。这种类型的控件前面也介绍了不少了,这个是对最大宽高进行限制的控件。
10 |
11 | 1.2 布局行为
12 | LimitedBox 是将 child 限制在其设定的最大宽高中的,但是这个限定是有条件的。当 LimitedBox 最大宽度不受限制时,child 的宽度就会受到这个最大宽度的限制,同理高度。
13 |
14 | 1.3 继承关系
15 | Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > LimitedBox
16 | 1.4 示例代码
17 | Row(
18 | children: [
19 | Container(
20 | color: Colors.red,
21 | width: 100.0,
22 | ),
23 | LimitedBox(
24 | maxWidth: 150.0,
25 | child: Container(
26 | color: Colors.blue,
27 | width: 250.0,
28 | ),
29 | ),
30 | ],
31 | )
32 | 1.5 源码解析
33 | const LimitedBox({
34 | Key key,
35 | this.maxWidth = double.infinity,
36 | this.maxHeight = double.infinity,
37 | Widget child,
38 | })
39 | 1.5.1 属性解析
40 | maxWidth:限定的最大宽度,默认值是 double.infinity,不能为负数。
41 |
42 | maxHeight:同上。
43 |
44 | 1.5.2 源码
45 | 先不说其源码,单纯从其作用,前面介绍的 SizedBox、ConstrainedBox 都类似,都是通过强加到 child 的 constraint,来达到相应的效果。
46 |
47 | 我们直接看其计算 constraint 的代码
48 |
49 | minWidth: constraints.minWidth,
50 | maxWidth: constraints.hasBoundedWidth ? constraints.maxWidth : constraints.constrainWidth(maxWidth),
51 | minHeight: constraints.minHeight,
52 | maxHeight: constraints.hasBoundedHeight ? constraints.maxHeight : constraints.constrainHeight(maxHeight)
53 | LimitedBox 只是改变最大宽高的限定。具体的布局代码如下:
54 |
55 | if (child != null) {
56 | child.layout(_limitConstraints(constraints), parentUsesSize: true);
57 | size = constraints.constrain(child.size);
58 | } else {
59 | size = _limitConstraints(constraints).constrain(Size.zero);
60 | }
61 | 根据最大尺寸,限制 child 的布局,然后将自身调节到 child 的尺寸。
62 |
63 | 1.6 使用场景
64 | 使用场景是不可能清楚了,光是找例子,就花了不少时间。Flutter 的一些冷门控件,真的是除了官方的文档,啥材料都木有。谷歌说这个很有用,还是一脸懵逼。这种控件,也有其他的替代解决方案,LimitedBox 可以达到的效果,ConstrainedBox 都可以实现。
65 |
66 | 2. Offstage
67 | A widget that lays the child out as if it was in the tree, but without painting anything, without making the child available for hit testing, and without taking any room in the parent.
68 |
69 | 2.1 简介
70 | Offstage 的作用很简单,通过一个参数,来控制 child 是否显示,日常使用中也算是比较常用的控件。
71 |
72 | 2.2 布局行为
73 | Offstage 的布局行为完全取决于其 offstage 参数
74 |
75 | 当 offstage 为 true,当前控件不会被绘制在屏幕上,不会响应点击事件,也不会占用空间;
76 | 当 offstage 为 false,当前控件则跟平常用的控件一样渲染绘制;
77 | 另外,当 Offstage 不可见的时候,如果 child 有动画,应该手动停掉,Offstage 并不会停掉动画。
78 |
79 | 2.3 继承关系
80 | Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > Offstage
81 | 2.4 示例代码
82 | Column(
83 | children: [
84 | new Offstage(
85 | offstage: offstage,
86 | child: Container(color: Colors.blue, height: 100.0),
87 | ),
88 | new CupertinoButton(
89 | child: Text("点击切换显示"),
90 | onPressed: () {
91 | setState(() {
92 | offstage = !offstage;
93 | });
94 | },
95 | ),
96 | ],
97 | )
98 | 当点击切换按钮的时候,可以看到 Offstage 显示消失。
99 |
100 | 2.5 源码解析
101 | const Offstage({Key key, this.offstage = true, Widget child})
102 | 2.5.1 属性解析
103 | offstage:默认为 true,也就是不显示,当为 flase 的时候,会显示该控件。
104 |
105 | 2.5.2 源码
106 | 我们先来看下 Offstage 的 computeIntrinsicSize 相关的方法:
107 |
108 | @override
109 | double computeMinIntrinsicWidth(double height) {
110 | if (offstage)
111 | return 0.0;
112 | return super.computeMinIntrinsicWidth(height);
113 | }
114 | 可以看到,当 offstage 为 true 的时候,自身的最小以及最大宽高都会被置为 0.0。
115 |
116 | 接下来我们来看下其 hitTest 方法:
117 |
118 | @override
119 | bool hitTest(HitTestResult result, { Offset position}) {
120 | return !offstage && super.hitTest(result, position: position);
121 | }
122 | 当 offstage 为 true 的时候,也不会去执行。
123 |
124 | 最后我们来看下其 paint 方法:
125 |
126 | @override
127 | void paint(PaintingContext context, Offset offset) {
128 | if (offstage)
129 | return;
130 | super.paint(context, offset);
131 | }
132 | 当 offstage 为 true 的时候直接返回,不绘制了。
133 |
134 | 到此,跟上面所说的布局行为对应上了。我们一定要清楚一件事情,Offstage 并不是通过插入或者删除自己在 widget tree 中的节点,来达到显示以及隐藏的效果,而是通过设置自身尺寸、不响应 hitTest 以及不绘制,来达到展示与隐藏的效果。
135 |
136 | 2.6 使用场景
137 | 当我们需要控制一个区域显示或者隐藏的时候,可以使用这个场景。其实也有其他代替的方法,但是成本会高很多,例如直接在 tree 上插入删除,但是不建议这么做。
138 |
139 | 3. OverflowBox
140 | A widget that imposes different constraints on its child than it gets from its parent, possibly allowing the child to overflow the parent.
141 |
142 | 3.1 简介
143 | OverflowBox 这个控件,允许 child 超出 parent 的范围显示,当然不用这个控件,也有很多种方式实现类似的效果。
144 |
145 | 3.2 布局行为
146 | 当 OverflowBox 的最大尺寸大于 child 的时候,child 可以完整显示,当其小于 child 的时候,则以最大尺寸为基准,当然,这个尺寸都是可以突破父节点的。最后加上对齐方式,完成布局。
147 |
148 | 3.3 继承关系
149 | Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > OverflowBox
150 | 3.4 示例代码
151 | Container(
152 | color: Colors.green,
153 | width: 200.0,
154 | height: 200.0,
155 | padding: const EdgeInsets.all(5.0),
156 | child: OverflowBox(
157 | alignment: Alignment.topLeft,
158 | maxWidth: 300.0,
159 | maxHeight: 500.0,
160 | child: Container(
161 | color: Color(0x33FF00FF),
162 | width: 400.0,
163 | height: 400.0,
164 | ),
165 | ),
166 | )
167 | OverflowBox 例子
168 |
169 | 当 maxHeight 大于 height 的时候,可以完全显示下来,当 maxHeight 小于 height 的时候,则不会会被隐藏掉
170 |
171 | 3.5 源码解析
172 | 构造函数如下:
173 |
174 | const OverflowBox({
175 | Key key,
176 | this.alignment = Alignment.center,
177 | this.minWidth,
178 | this.maxWidth,
179 | this.minHeight,
180 | this.maxHeight,
181 | Widget child,
182 | })
183 | 3.5.1 属性解析
184 | alignment:对齐方式。
185 |
186 | minWidth:允许 child 的最小宽度。如果 child 宽度小于这个值,则按照最小宽度进行显示。
187 |
188 | maxWidth:允许 child 的最大宽度。如果 child 宽度大于这个值,则按照最大宽度进行展示。
189 |
190 | minHeight:允许 child 的最小高度。如果 child 高度小于这个值,则按照最小高度进行显示。
191 |
192 | maxHeight:允许 child 的最大高度。如果 child 高度大于这个值,则按照最大高度进行展示。
193 |
194 | 其中,最小以及最大宽高度,如果为 null 的时候,就取父节点的 constraint 代替。
195 |
196 | 3.5.2 源码
197 | OverflowBox 的源码很简单,我们先来看一下布局代码:
198 |
199 | if (child != null) {
200 | child.layout(_getInnerConstraints(constraints), parentUsesSize: true);
201 | alignChild();
202 | }
203 | 如果 child 不为 null,child 则会按照计算出的 constraints 进行尺寸的调整,然后对齐。
204 |
205 | 至于 constraints 的计算,则还是上面的逻辑,如果设置的有的话,就取这个值,如果没有的话,就拿父节点的。
206 |
207 | 3.6 使用场景
208 | 有时候设计图上出现的角标,会超出整个模块,可以使用 OverflowBox 控件。但我们应该知道,不使用这种控件,也可以完成布局,在最外面包一层,也能达到一样的效果。具体实施起来哪个比较方便,同学们自行取舍。
209 |
210 | 4. SizedBox
211 | A box with a specified size.
212 |
213 | 4.1 简介
214 | 比较常用的一个控件,设置具体尺寸。
215 |
216 | 4.2 布局行为
217 | SizedBox 布局行为相对较简单:
218 |
219 | child 不为 null 时,如果设置了宽高,则会强制把 child 尺寸调到此宽高;如果没有设置宽高,则会根据 child 尺寸进行调整;
220 | child 为 null 时,如果设置了宽高,则自身尺寸调整到此宽高值,如果没设置,则尺寸为 0;
221 | 4.3 继承关系
222 | Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > SizedBox
223 | 4.4 示例代码
224 | Container(
225 | color: Colors.green,
226 | padding: const EdgeInsets.all(5.0),
227 | child: SizedBox(
228 | width: 200.0,
229 | height: 200.0,
230 | child: Container(
231 | color: Colors.red,
232 | width: 100.0,
233 | height: 300.0,
234 | ),
235 | ),
236 | )
237 | 4.5 源码解析
238 | 构造函数
239 |
240 | const SizedBox({Key key, this.width, this.height, Widget child})
241 | 4.5.1 属性解析
242 | width:宽度值,如果具体设置了,则强制 child 宽度为此值,如果没设置,则根据 child 宽度调整自身宽度。
243 |
244 | height:同上。
245 |
246 | 4.5.2 源码
247 | SizedBox 内部是通过 RenderConstrainedBox 来实现的。具体的源码就不解析了,总体思路是,根据宽高值算好一个 constraints,然后强制应用到 child 上。
248 |
249 | 4.6 使用场景
250 | 这个控件,很多场景可以使用。但是,可以替代它的控件也有不少,例如 Container、ConstrainedBox 等。而且 SizedBox 就是 ConstrainedBox 的一个特例。还是那句话,精简啊,多提供一些常用的,不要提供一大堆重复的,场景很少的控件。
251 |
252 | 5. 后话
253 | 笔者建了一个 Flutter 学习相关的项目,Github 地址,里面包含了笔者写的关于 Flutter 学习相关的一些文章,会定期更新,文章中的代码也在这个项目中,欢迎大家关注。
254 |
255 | 6. 参考
256 | LimitedBox class
257 | Offstage class
258 | OverflowBox class
259 | SizedBox class
--------------------------------------------------------------------------------
/BlogArchive/simpread-Flutter 布局 - Padding、Align、Center 详解 - Flutter 开发社区.md:
--------------------------------------------------------------------------------
1 | > 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 https://www.flutter123.net/Article/Detail/35
2 |
3 | 本文主要介绍 Flutter 布局中的 Padding、Align 以及 Center 控件,详细介绍了其布局行为以及使用场景,并对源码进行了分析。
4 |
5 | 1. Padding
6 | A widget that insets its child by the given padding.
7 |
8 | 1.1 简介
9 | Padding 在 Flutter 中用的也挺多的,作为一个基础的控件,功能非常单一,给子节点设置 padding 属性。写过其他端的都了解这个属性,就是设置内边距属性,内边距的空白区域,也是 widget 的一部分。
10 |
11 | Flutter 中并没有单独的 Margin 控件,在 Container 中有 margin 属性,看源码关于 margin 的实现。
12 |
13 | if (margin != null)
14 | current = new Padding(padding: margin, child: current);
15 | 不难看出,Flutter 中淡化了 margin 以及 padding 的区别,margin 实质上也是由 Padding 实现的。
16 |
17 | 1.2 布局行为
18 | Padding 的布局分为两种情况:
19 |
20 | 当 child 为空的时候,会产生一个宽为 left+right,高为 top+bottom 的区域;
21 | 当 child 不为空的时候,Padding 会将布局约束传递给 child,根据设置的 padding 属性,缩小 child 的布局尺寸。然后 Padding 将自己调整到 child 设置了 padding 属性的尺寸,在 child 周围创建空白区域。
22 | 1.3 继承关系
23 | Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > Padding
24 | 从继承关系可以看出,Padding 控件是一个基础控件,不像 Container 这种组合控件。Container 中的 margin 以及 padding 属性都是利用 Padding 控件去实现的。
25 |
26 | 1.3.1 关于 SingleChildRenderObjectWidget
27 | SingleChildRenderObjectWidget 是 RenderObjectWidgets 的一个子类,用于限制只能有一个子节点。它只提供 child 的存储,而不提供实际的更新逻辑。
28 |
29 | 1.3.2 关于 RenderObjectWidgets
30 | RenderObjectWidgets 为 RenderObjectElement 提供配置,而 RenderObjectElement 包含着(wrap)RenderObject,RenderObject 则是在应用中提供实际的绘制(rendering)的元素。
31 |
32 | 1.4 示例代码
33 | 实例代码直接上官方的例子,非常的简单:
34 |
35 | new Padding(
36 | padding: new EdgeInsets.all(8.0),
37 | child: const Card(child: const Text('Hello World!')),
38 | )
39 | 例子中对 Card 设置了一个宽度为 8 的内边距。
40 |
41 | 1.5 源码解析
42 | 构造函数如下:
43 |
44 | const Padding({
45 | Key key,
46 | @required this.padding,
47 | Widget child,
48 | })
49 | 包含一个 padding 属性,相当的简单。
50 |
51 | 1.5.1 属性解析
52 | padding:padding 的类型为 EdgeInsetsGeometry,EdgeInsetsGeometry 是 EdgeInsets 以及 EdgeInsetsDirectional 的基类。在实际使用中不涉及到国际化,例如适配阿拉伯地区等,一般都是使用 EdgeInsets。EdgeInsetsDirectional 光看命名就知道跟方向相关,因此它的四个边距不限定上下左右,而是根据方向来定的。
53 |
54 | 1.5.2 源码
55 | @override
56 | RenderPadding createRenderObject(BuildContext context) {
57 | return new RenderPadding(
58 | padding: padding,
59 | textDirection: Directionality.of(context),
60 | );
61 | }
62 | Padding 的创建函数,实际上是由 RenderPadding 来进行的。
63 |
64 | 关于 RenderPadding 的实际布局表现,当 child 为 null 的时候:
65 |
66 | if (child == null) {
67 | size = constraints.constrain(new Size(
68 | _resolvedPadding.left + _resolvedPadding.right,
69 | _resolvedPadding.top + _resolvedPadding.bottom
70 | ));
71 | return;
72 | }
73 | 返回一个宽为 _resolvedPadding.left+_resolvedPadding.right,高为 _resolvedPadding.top+_resolvedPadding.bottom 的区域。
74 |
75 | 当 child 不为 null 的时候,经历了三个过程,即调整 child 尺寸、调整 child 位置以及调整 Padding 尺寸,最终达到实际的布局效果。
76 |
77 | // 调整 child 尺寸
78 | final BoxConstraints innerConstraints = constraints.deflate(_resolvedPadding);
79 | child.layout(innerConstraints, parentUsesSize: true);
80 |
81 | // 调整 child 位置
82 | final BoxParentData childParentData = child.parentData;
83 | childParentData.offset = new Offset(_resolvedPadding.left, _resolvedPadding.top);
84 |
85 | // 调整 Padding 尺寸
86 | size = constraints.constrain(new Size(
87 | _resolvedPadding.left + child.size.width + _resolvedPadding.right,
88 | _resolvedPadding.top + child.size.height + _resolvedPadding.bottom
89 | ));
90 | 到此处,上面介绍的 padding 布局行为就解释的通了。
91 |
92 | 1.6 使用场景
93 | Padding 本身还是挺简单的,基本上需要间距的地方,它都能够使用。如果在单一的间距场景,使用 Padding 比 Container 的成本要小一些,毕竟 Container 里面包含了多个 widget。Padding 能够实现的,Container 都能够实现,只不过,Container 更加的复杂。
94 |
95 | 2. Align
96 | A widget that aligns its child within itself and optionally sizes itself based on the child's size.
97 |
98 | 2.1 简介
99 | 在其他端的开发,Align 一般都是当做一个控件的属性,并没有拿出来当做一个单独的控件。Align 本身实现的功能并不复杂,设置 child 的对齐方式,例如居中、居左居右等,并根据 child 尺寸调节自身尺寸。
100 |
101 | 2.2 布局行为
102 | Align 的布局行为分为两种情况:
103 |
104 | 当 widthFactor 和 heightFactor 为 null 的时候,当其有限制条件的时候,Align 会根据限制条件尽量的扩展自己的尺寸,当没有限制条件的时候,会调整到 child 的尺寸;
105 | 当 widthFactor 或者 heightFactor 不为 null 的时候,Aligin 会根据 factor 属性,扩展自己的尺寸,例如设置 widthFactor 为 2.0 的时候,那么,Align 的宽度将会是 child 的两倍。
106 | Align 为什么会有这样的布局行为呢?原因很简单,设置对齐方式的话,如果外层元素尺寸不确定的话,内部的对齐就无法确定。因此,会有宽高因子、根据外层限制扩大到最大尺寸、外层不确定时调整到 child 尺寸这些行为。
107 |
108 | 2.3 继承关系
109 | Object > Diagnosticable > DiagnosticableTree > Widget > RenderObjectWidget > SingleChildRenderObjectWidget > Align
110 | 可以看出,Align 跟 Padding 一样,也是一个非常基础的组件,Container 中的 align 属性,也是使用 Align 去实现的。
111 |
112 | 2.4 示例代码
113 | new Align(
114 | alignment: Alignment.center,
115 | widthFactor: 2.0,
116 | heightFactor: 2.0,
117 | child: new Text("Align"),
118 | )
119 | 例子依旧很简单,设置一个宽高为 child 两倍区域的 Align,其 child 处在正中间。
120 |
121 | 2.5 源码解析
122 | const Align({
123 | Key key,
124 | this.alignment: Alignment.center,
125 | this.widthFactor,
126 | this.heightFactor,
127 | Widget child
128 | })
129 | Align 的构造函数基本上就是宽高因子、对齐方式属性。日常使用中,宽高因子属性基本上用的不多。如果是复杂的布局,Container 内部的 align 属性也可以实现相同的效果。
130 |
131 | 2.5.1 属性解析
132 | alignment:对齐方式,一般会使用系统默认提供的 9 种方式,但是并不是说只有这 9 种,例如如下的定义。系统提供的 9 种方式只是预先定义好的。
133 |
134 | /// The top left corner.
135 | static const Alignment topLeft = const Alignment(-1.0, -1.0);
136 | Alignment 实际上是包含了两个属性的,其中第一个参数,-1.0 是左边对齐,1.0 是右边对齐,第二个参数,-1.0 是顶部对齐,1.0 是底部对齐。根据这个规则,我们也可以自定义我们需要的对齐方式,例如
137 |
138 | /// 居右高于底部 1/4 处.
139 | static const Alignment rightHalfBottom = alignment: const Alignment(1.0, 0.5),
140 | widthFactor:宽度因子,如果设置的话,Align 的宽度就是 child 的宽度乘以这个值,不能为负数。
141 |
142 | heightFactor:高度因子,如果设置的话,Align 的高度就是 child 的高度乘以这个值,不能为负数。
143 |
144 | 2.5.2 源码
145 | @override
146 | RenderPositionedBox createRenderObject(BuildContext context) {
147 | return new RenderPositionedBox(
148 | alignment: alignment,
149 | widthFactor: widthFactor,
150 | heightFactor: heightFactor,
151 | textDirection: Directionality.of(context),
152 | );
153 | }
154 | Align 的实际构造调用的是 RenderPositionedBox。
155 |
156 | RenderPositionedBox 的布局表现如下:
157 |
158 | // 根据 _widthFactor、_heightFactor 以及限制因素来确定宽高
159 | final bool shrinkWrapWidth = _widthFactor != null || constraints.maxWidth == double.infinity;
160 | final bool shrinkWrapHeight = _heightFactor != null || constraints.maxHeight == double.infinity;
161 |
162 | if (child != null) {
163 | // 如果 child 不为 null,则根据规则设置 Align 的宽高,如果需要缩放,则根据 _widthFactor 是否为 null 来进行缩放,如果不需要,则尽量扩展。 child.layout(constraints.loosen(), parentUsesSize: true); size = constraints.constrain(new Size(shrinkWrapWidth ? child.size.width * (_widthFactor ?? 1.0) : double.infinity,
164 | shrinkWrapHeight ? child.size.height * (_heightFactor ?? 1.0) : double.infinity));
165 | alignChild();
166 | } else {
167 | // 如果 child 为 null,如果需要缩放,则变为 0,否则就尽量扩展
168 | size = constraints.constrain(new Size(shrinkWrapWidth ? 0.0 : double.infinity,
169 | shrinkWrapHeight ? 0.0 : double.infinity));
170 | }
171 | 2.6 使用场景
172 | 一般在对齐场景下使用,例如需要右对齐或者底部对齐之类的。它能够实现的功能,Container 都能实现。
173 |
174 | 3. Center
175 | Center 继承自 Align,只不过是将 alignment 设置为 Alignment.center,其他属性例如 widthFactor、heightFactor,布局行为,都与 Align 完全一样,在这里就不再单独做介绍了。Center 源码如下,没有设置 alignment 属性,是因为 Align 默认的对齐方式就是居中。
176 |
177 | class Center extends Align {
178 | /// Creates a widget that centers its child.
179 | const Center({Key key, double widthFactor, double heightFactor, Widget child})
180 | : super(key: key, widthFactor: widthFactor, heightFactor: heightFactor, child: child);
181 | }
182 |
183 | 4. 后话
184 | 笔者建了一个 flutter 学习相关的项目,github 地址,里面包含了笔者写的关于 flutter 学习相关的一些文章,会定期更新,也会上传一些学习 demo,欢迎大家关注。
185 |
186 | 5. 参考
187 | Padding class
188 | EdgeInsetsGeometry class
189 | EdgeInsets class
190 | EdgeInsetsDirectional class
191 | RenderPadding class
192 | Align class
193 | Center class
--------------------------------------------------------------------------------
/BlogArchive/video.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/BlogArchive/video.mp4
--------------------------------------------------------------------------------
/BlogArchive/使用 libclang 实现 iOS 代码中的明文加密.md:
--------------------------------------------------------------------------------
1 | ### 前言
2 |
3 | 之前写过一个小工具 [MixPlainText](https://github.com/danleechina/mixplaintext),可以将 Xcode 工程代码中所有的明文加密。原理是使用正则表达式来提取代码中所有的明文。现在介绍一种新的更加完善、更有拓展性的方法。用到的工具主要是 libclang。
4 |
5 | 这里我已经将所有代码、配置上传到 GitHub 了,所以有兴趣也可以直接下载代码查看,地址 [UsingLibClang](https://github.com/danleechina/UsingLibClang)
6 |
7 | ### 配置 Xcode 工程
8 |
9 | 由于我是用 C 语言来调用 libclang 的。所以这里介绍一下怎么配置 Xcode 工程来使用这个库。当然你也可以用 Python 来使用这个库,具体方式可以看这个文章 [Parsing C++ in Python with Clang](http://eli.thegreenplace.net/2011/07/03/parsing-c-in-python-with-clang)
10 |
11 | 1. 去 http://llvm.org/svn/llvm-project/cfe/trunk/include/clang-c/ 下载所有头文件。
12 | 2. 工程中添加上面下载的头文件
13 | 3. 点击工程配置中的 ‘Build Phases’,打开 ‘Link Binary With Libraries’,点击 ‘+’ 号,然后选择 ‘Add other…’。
14 | 4. 使用快捷键 ⌘⇧G 打开 ```/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/lib/libclang.dylib```,将 Xcode 自带的 libclang.dylib 添加到环境中。
15 | 5. 转到 Build Setting。
16 | 6. 添加一个新的 Runpath search paths:```$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib```
17 | 这里的```$(DEVELOPER_DIR) ``` 指代 ```/Applications/Xcode.app/Contents/Developer```
18 |
19 | 7. 添加一个新的 header search paths:```$(SRCROOT)/path_to_clang_header_file```
20 | 注意这里的 $(SRCROOT) 指代工程所在的目录。后面的具体路径就是上面下载的头文件的位置。
21 |
22 | 8. 添加新的 Library Search Paths: ```$(DEVELOPER_DIR)/Toolchains/XcodeDefault.xctoolchain/usr/lib```
23 | 9. 将 Enable Modules (C and Objective-C) 设置为 NO
24 |
25 | ### 使用 libclang API
26 |
27 | 代码如下,必要地方有注释说明:
28 |
29 | ```
30 | #import
31 | #include
32 | #include
33 | #include
34 | // libclang 公开 API 均在这里
35 | #include "clang-c/Index.h"
36 |
37 |
38 | int main(int argc, const char * argv[]) {
39 | @autoreleasepool {
40 | // 一个编译单元,通常是一个文件
41 | CXTranslationUnit tu;
42 | // 一个 index 可以包含多个编译单元
43 | CXIndex index = clang_createIndex(1, 1);
44 | // 需要分析混淆的 Objective C 源代码文件
45 | const char *filePath = "/path_to_OC_code/HomeViewController.m";
46 | //
47 | tu = clang_parseTranslationUnit(index, filePath, NULL, 0, nullptr, 0, 0);
48 | if (!tu) {
49 | printf("Couldn't create translation unit");
50 | return 1;
51 | }
52 | // 根 cursor
53 | CXCursor rootCursor = clang_getTranslationUnitCursor(tu);
54 | // 一个个经过词法分析以后得到的 token
55 | CXToken *tokens;
56 | unsigned int numTokens;
57 | CXCursor *cursors = 0;
58 | CXSourceRange range = clang_getCursorExtent(rootCursor);
59 | // 获取所有的 token
60 | clang_tokenize(tu, range, &tokens, &numTokens);
61 | cursors = (CXCursor *)malloc(numTokens * sizeof(CXCursor));
62 | // 获取每个 token 对应的 cursor
63 | clang_annotateTokens(tu, tokens, numTokens, cursors);
64 | // 遍历 token
65 | for(int i=0; i < numTokens; i++) {
66 | CXToken token = tokens[i];
67 | CXCursor cursor = cursors[i];
68 | CXString tokenSpelling = clang_getTokenSpelling(tu, token);
69 | CXString cursorSpelling = clang_getCursorSpelling(cursor);
70 | const char *tokenName = clang_getCString(tokenSpelling);
71 | if (CXToken_Literal == clang_getTokenKind(token) // 是明文的 token
72 | && CXCursor_PreprocessingDirective != cursor.kind // 排除预编译 token
73 | && strlen(tokenName) >= 2 // 排除所有非字符串 token
74 | && tokenName[0] == '\"'
75 | && tokenName[strlen(tokenName) - 1] == '\"' ) {
76 | // Do some replacing.
77 | NSData *content = [[NSFileManager defaultManager] contentsAtPath:[NSString stringWithUTF8String:filePath]];
78 | NSString *contentString = [[NSString alloc] initWithData:content encoding:NSUTF8StringEncoding];
79 | // stringToBeResplaced 是需要被混淆的代码
80 | NSString *stringToBeResplaced = [NSString stringWithUTF8String:tokenName];
81 | // stringToBePutted 是经过混淆的代码
82 | NSString *stringToBePutted = @"\"Hello\"";
83 | contentString = [contentString stringByReplacingOccurrencesOfString:stringToBeResplaced withString:stringToBePutted];
84 | // 将经过混淆的代码写回原文件
85 | [contentString writeToFile:[NSString stringWithUTF8String:filePath] atomically:YES encoding:NSUTF8StringEncoding error:nil];
86 | printf("\t%d\t%s\n", cursor.kind, tokenName);
87 | }
88 | // 释放内存
89 | clang_disposeString(tokenSpelling);
90 | clang_disposeString(cursorSpelling);
91 | }
92 | // 释放内存
93 | clang_disposeTokens(tu, tokens, numTokens);
94 | clang_disposeIndex(index);
95 | clang_disposeTranslationUnit(tu);
96 | free(cursors);
97 | }
98 | return 0;
99 | }
100 | ```
101 |
102 | ### 使用方式
103 |
104 | 建议将上述代码编译生成的二进制可执行文件,放到您需要混淆的工程里面。添加一个新的 ‘Run path’,调用这个二进制文件处理每个你想要处理的源代码
105 |
106 |
107 | ### 参考资料
108 |
109 | * [Parsing C++ in Python with Clang](http://eli.thegreenplace.net/2011/07/03/parsing-c-in-python-with-clang)
110 | * [libclang experiments](https://github.com/burnflare/libclang-experiments)
111 | * [Apple libclang video](http://llvm.org/devmtg/2010-11/)
112 | * [liblcang API](https://clang.llvm.org/doxygen/group__CINDEX.html)
--------------------------------------------------------------------------------
/BlogArchive/堆、栈、全局区、常量区、代码区.md:
--------------------------------------------------------------------------------
1 | > 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 https://www.jianshu.com/p/62f1096c2452
2 |
3 | [](https://www.jianshu.com/u/db56e4cae85b)
4 |
5 | 2019.10.31 17:24:28 字数 1,563 阅读 18
6 |
7 | ### 前言
8 |
9 | 内容参考:
10 |
11 | [iOS 内存分配 栈、堆、全局区、常量区、代码区
12 | ](https://links.jianshu.com/go?to=https%3A%2F%2Fblog.csdn.net%2Fzhw521411%2Farticle%2Fdetails%2F89844273)
13 |
14 | [NSString 存储管理 --NSTaggedPointerString](https://www.jianshu.com/p/df630e78df32)
15 |
16 | [iOS 开发中的内存分配(堆和栈)](https://www.jianshu.com/p/746c747e7e00)
17 |
18 | ### 分析
19 |
20 | 
21 |
22 | iOS 内存分配. png
23 |
24 | #### 1. 代码区
25 |
26 | 代码区是用来存放函数的二进制代码,也就是,它是可执行程序在内存中的镜像。代码段需要防止在运行时被非法修改,所以只允许读取操作,而不允许写入操作。
27 |
28 | #### 2. 全局(静态)区
29 |
30 | * 数据区:数据段用来存放可执行文件中已经初始化的全局变量,也就是用来存放静态分配的变量和全局变量。
31 | * BSS 区:BSS 段包含了程序中未初始化的全局变量
32 |
33 | #### 3. 常量区
34 |
35 | 常量存储区,这是一块比较特殊的存储区,他们里面存放的是常量。
36 |
37 | #### 4. 堆(heap)区
38 |
39 | 堆是由程序员分配和释放,用于存放进程运行中被动态分配的内存段。它大小不固定,可动态扩张和缩减。
40 |
41 | #### 5. 栈(stack)区
42 |
43 | 栈是由编译器自动分配释放来管理内存。用户存放程序临时创建的变量、存放函数的参数值、局部变量等。由于栈的先进后出特点,所以特别适合用来做保存 / 恢复现场的操作。从这个吧意义上,我们可以把栈看做一个临时寄存、交换的内存区。
44 |
45 | static 修饰的属性始终保存到常量区。
46 |
47 | > 上述几种内存区域中,数据段、BSS、堆通常都是被连续存储的 - 内存位置上的连续(并不是堆链式存储的内存区域)。而代码段和栈往往会被独立存放。
48 |
49 | > 栈是向低地址扩展的数据结构,是一块连续的内存区域。堆是向高地址扩展的数据结构,是不连续的内存区域。
50 |
51 | ### 内存模型 Heap、Stack
52 |
53 | 以下内容引用自阮一峰老师的 [汇编语言入门教程](https://links.jianshu.com/go?to=http%3A%2F%2Fwww.ruanyifeng.com%2Fblog%2F2018%2F01%2Fassembly-language-primer.html)。
54 |
55 | 对于堆 `heap` 和 栈 `stack` 描述更加详细易懂。
56 |
57 | #### 1. 堆 `Heap`
58 |
59 | 寄存器只能存放少量的数据,大多数时候, `CPU` 还要指挥寄存器,直接跟内存交换数据,所以,除了寄存器,还必须了解内存怎么存储数据。
60 |
61 | 程序运行的时候,操作系统会给它分配一块内存,用来存储程序和运行产生的数据,比如从 `0x1000` 到 `0x8000`,起始地址是较小的那个地址,结束地址是较大的那个地址。
62 |
63 | 
64 |
65 | 内存示意图
66 |
67 | 程序运行过程中,对于动态的内存占用请求(比如新建对象),系统就会从预先分配好的那段内存中,划出一部分给用户,具体规则是从起始地址开始划分(实际上,起始地址会有一段静态数据,这里忽略)。举例来说,用户要求得到 10 个字节内存,那么从起始地址 `0x1000` 开始给他分配,一直分配到 `0x100A`,如果在要求得到 `22` 个字节,那么就分配到 `0x1020`。
68 |
69 | 
70 |
71 | 内存分配
72 |
73 | 这种因为用户主动请求而划分出来的内存区域,叫做 `Heap(堆)`。它由起始位置开始,从低位(地址)向高位(地址)增长。 `Heap` 的一个重要特点就是不会自动消失,必须手动释放,或者由垃圾回收机制来回收。
74 |
75 | #### 2. 栈 `Stack`
76 |
77 | 除了 `Heap` 外,其他的内存占用叫做 `Stack(栈)`。简单来说,`Stack` 是由于函数运行而临时占用的内存区域。
78 |
79 | 
80 |
81 | 栈内存
82 |
83 | 请看下面的例子:
84 |
85 | ```
86 | int main() {
87 | int a = 2;
88 | int b = 3;
89 | }
90 |
91 |
92 | ```
93 |
94 | 上面代码中,系统开始执行 `main` 函数时,会为它在内存里面建立一个 `帧(frame)`,所有的 `main` 的内部变量(比如 `a` 和 `b`)都保存在这个 `帧` 里面。`main` 函数执行结束后,该帧就会被回收,释放所有的内部变量,不再占用空间。
95 |
96 | 
97 |
98 | 帧(frame)
99 |
100 | 如果函数内部调用其他函数,会发生什么情况呢?
101 |
102 | ```
103 | int main() {
104 | int a = 2;
105 | int b = 3;
106 | return add_a_and_b(a,b);
107 | }
108 |
109 |
110 | ```
111 |
112 | 上面代码中,`main` 函数调用了 `add_a_and_b` 函数。执行到这一行的时候,系统也会为 `add_a_and_b` 新建一个 `帧(frame)`,用来存储它的内部变量。也就是说,此时同时存在两个帧:`main` 和 `add_a_and_b`。一般来说,调用栈有多少层,就有多少帧。
113 |
114 | 
115 |
116 | 函数嵌套
117 |
118 | 等到 `add_a_and_b` 运行结束,它的帧就会被回收,系统会回到刚才 `main` 函数中断执行的地方,继续往下执行。通过这种机制,就实现了函数的层层调用,并且每一层都能使用自己的本地变量。
119 |
120 | 所有的帧都存放在 `Stack` ,由于帧是一层层叠加的,所以 `Stack` 叫做 **栈**。生成新的帧,叫 `入栈`,英文单词是 `push`;栈的回收叫 `出栈`,英文是 `pop`。`Stack` 的特点就是,最晚入栈的帧最早出栈(因为最内层的函数调用,最先结束执行),这种叫做 **后进先出** 的数据结构。每一次函数执行结束,就自动释放一个帧,所有的函数执行结束,整个 `Stack` 就都释放了。
121 |
122 | `Stack` 是由内存区域的结束地址开始,从高位(地址)向地位(地址)分配。比如,内存区域的结束地址是 `0x8000`,第一帧假定是 `16` 字节,那么下一次分配的地址就会从 `0x7FF0` 开始;第二帧假定需要 `64` 字节,那么地址就会移到 `0x7FB0`。
123 |
124 | 
125 |
126 | 栈内存地址分配
127 |
128 | ### 关于 `NSString` 的内存分配
129 |
130 | [NSString 存储管理 --NSTaggedPointerString](https://www.jianshu.com/p/df630e78df32) 文章中详细说明了问题,我们并不能单纯的通过打印内存地址,来判断数据存储的区域在常量,或者堆区、栈区。
131 |
132 | "小礼物走一走,来简书关注我"
133 |
134 | 还没有人赞赏,支持一下
135 |
136 | [](https://www.jianshu.com/u/db56e4cae85b)
137 |
138 | 总资产 8 (约 0.78 元) 共写了 5.3W 字获得 79 个赞共 29 个粉丝
139 |
140 | ### 被以下专题收入,发现更多相似内容
141 |
142 | ### 推荐阅读[更多精彩内容](https://www.jianshu.com/)
143 |
144 | * 前言 因为前段时间因为一些事情而晚上失眠多梦,身体素质直线下降,前天下班后去健身房减完身,感到恶心难受,后来发生了...
145 |
146 | * 前言 因为前段时间因为一些事情而晚上失眠多梦,身体素质直线下降,前天下班后去健身房减完身,感到恶心难受,后来发生了...
147 |
148 | [Dely](https://www.jianshu.com/u/e95705fe04d9) 阅读 6
149 |
150 | [](https://www.jianshu.com/p/acb5abc94a0d)
151 | * 一个由 C/C++ 编译的程序占用的内存分为以下几个部分 栈区 (stack): 由编译器自动分配、释放,存放函数的参数值...
--------------------------------------------------------------------------------
/BlogArchive/聊聊 Flutter Platform SDK.md:
--------------------------------------------------------------------------------
1 | > 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 https://juejin.im/post/5bd1270ff265da0ac07c951b
2 |
3 | [TOC]
4 |
5 | 前言
6 | --
7 |
8 | 从 Flutter 的架构图中可以看出,Flutter Platform SDK 处于整个 Flutter 框架的上层,连接了 Java 与 Dart 代码。那么作为 “最上层” 的它,到底扮演了哪些角色,以及是如何扮演好这些角色的呢?Google 工程师用一个封装好的 flutter.jar 包 "show me the answer"。
9 |
10 | Platform SDK 的角色扮演
11 | ------------------
12 |
13 | 通过对 Platform SDK(以下简称 Platform) 源码的阅读,可以大致将它分成三个角色:Creator(创建者),Transmitter(传递者),Registrant(注册人)。
14 |
15 | ### Creator
16 |
17 | 创建者
18 |
19 | ##### FlutterMain
20 |
21 | ##### 时序图
22 |
23 | 
24 |
25 | FlutterMain 担任着 flutter 的初始化工作,在被 Application 的 onCreate 调起后
26 |
27 | * initConfig
28 |
29 | 必须的配置文件名称和路径
30 |
31 | * 通过命令行 flutter build aot 生成的文件
32 |
33 | | 名称 | 内容 |
34 | | --- | --- |
35 | | isolate_snapshot_instr | 应用程序指令段 |
36 | | isolate_snapshot_data | 应用程序数据段 |
37 | | vm_snapshot_instr | VM 虚拟机指令段 |
38 | | vm_snapshot_data | VM 虚拟机数据段 |
39 |
40 |
41 | 注: 详细含义参见[官方说明](https://link.juejin.im?target=https%3A%2F%2Fgithub.com%2Fflutter%2Fengine%2Fwiki%2FFlutter-Engine-Operation-in-AOT-Mode)
42 |
43 | * 路径信息
44 |
45 | flutter_assets 等文件的路径信息
46 |
47 | * initAot
48 |
49 | 1. 初始化标记位: snapshot 文件集成的方式。
50 | 2. sIsPrecompiledAsSharedLibrary 代表的是把所有的 snapshot 文件打包成一个动态库 (一种类似 ios 的集成方式)。
51 | 3. 禁止同时采用两种集成方式。
52 | * initResource
53 |
54 | 1. 创建了一个 ResourceExtractor 对象, 他是 Resource 文件的搬运工
55 | 2. 通过 ResourceExtractor 对象的 addResource 方法初始化需要搬运的文件
56 | 3. ResourceExtractor 启动异步任务把 asset 下面的文件搬运到 DataDir 的 flutter 目录下面
57 |
58 | #### FlutterActivityDelegate
59 |
60 | ##### WhatDelegate
61 |
62 | ```
63 | //FlutterActivity.java
64 | ......
65 | private final FlutterActivityEvents eventDelegate;
66 | private final Provider viewProvider;
67 | private final PluginRegistry pluginRegistry;
68 | private final FlutterActivityDelegate delegate = new FlutterActivityDelegate(this, this);
69 | ......
70 | public FlutterActivity() {
71 | this.eventDelegate = this.delegate;
72 | this.viewProvider = this.delegate;
73 | this.pluginRegistry = this.delegate;
74 | }
75 | ......
76 | 复制代码
77 |
78 | ```
79 |
80 | 我们可以从上面 FlutterActivity 的构造函数中看出 Delegate 到底代理了哪些职责
81 |
82 | * FlutterActivityEvents:将 Activity 生命周期的具体处理逻辑传递给 FlutterView
83 |
84 | * Provider:在 onCreate 中创建的 FlutterView,通过实现 Provider 的接口暴露出来
85 |
86 | * PluginRegistry: 插件信息的注册与查询传递给 FlutterView
87 |
88 | 从上面看来,其实 FlutterActivityDelegate 直接交互的对象就是 FlutterView,通过这样的设计,提高了每一个类的内聚性
89 |
90 |
91 | 
92 |
93 | #### FlutterView
94 |
95 | 可以先简单的把 FlutterView 看成是负责显示的,而把后面的 FlutterNativeView 看成是负责通信的。
96 |
97 | * 解偶系统控件
98 |
99 | 首先我们可以看到 FlutterView 是继承自 SurfaceView 的,提到 SurfaceView 我们肯定会想到 “挖洞”,“双缓冲” 这些词,也正是因为这些特性 FlutterView 可以很好的把 UI 渲染工作交给 Flutter( 后者通过 dart->组装 LayerTree->Skia 完成绘制 )。
100 |
101 |
102 | 
103 |
104 | * 传递状态消息给 Dart UI
105 |
106 | 这些消息大致可以将它们分成七个模块,两大类
107 |
108 | 1. 通过反射原生系统的 api 进行数据通讯
109 |
110 | 多语言模块、系统信息和用户设置
111 |
112 | 2. 将数据打包成特殊格式以消息的形式和使用 Dart 编写的 flutter 控件交互
113 |
114 | 生命周期、按键消息、路由导航和平台插件
115 |
116 |
117 | #### FlutterNativeView
118 |
119 | 可以先简单的把 FlutterNativeView 看成是负责通信的。它在系统层面上实现了 BinaryMessenger 接口 [这在下文 **Transmitter** 中详细介绍]。
120 |
121 | ### Transmitter
122 |
123 | 传递者
124 |
125 | #### 消息渠道
126 |
127 | * Flutter 针对不同的应用场景封装了 3 类 Channel
128 |
129 | 1. MethodChannel:调用方法
130 | 2. BasicMessageChannel:自定义结构信息
131 | 3. EventChannel:事件的通知
132 | * 3 类 Channel 拥有相似的结构类型
133 |
134 | 1. 信使 BinaryMessenger:我们自己创建的 channel 一般就是 FlutterNativeView
135 | 2. channel 名:channel 的 key 值,不可重复
136 | 3. MethodCodec /MessageCodec 解码器: 针对不同的 channle 解码二进制应答数据
137 |
138 | 
139 |
140 | #### 消息编解码
141 |
142 | 标准平台通道使用一个标准的消息编解码器。简单的 JSON 类值(如布尔值)的高效二进制序列化,数字、字符串、字节缓冲区以及这些列表和映射。(查看细节 [`StandardMessageCodec`](https://link.juejin.im?target=https%3A%2F%2Fdocs.flutter.io%2Fflutter%2Fservices%2FStandardMessageCodec-class.html))。这些值的序列化和反序列化在消息发送和接收值时自动发生。(对应的数据转化关系如下)
143 |
144 | 
145 |
146 | #### 传递流程
147 |
148 | 通过 Flutter Engine 的数据转换, 使得 Dart 和 Android 之间可以进行通信
149 |
150 | 
151 |
152 | ### Registrant
153 |
154 | 注册人
155 |
156 | #### 情境转换
157 |
158 | 首先这里有三个形似得英文单词 registry, registrar and registrant 分别对应注册局,注册商和注册人。把它们翻译到现实的生活场景中的角色其实是一个 “注册人通过注册商,更新注册信息后,注册商把信息传递给注册局进行保存” 的过程。下面我们把这个过程再翻译回代码:
159 |
160 | 首先我们新建一个 plugin 插件, 作为说明的对象:
161 |
162 | ```
163 | // 实现 PluginRegistry.ActivityResultListener
164 | public class FlutterMusicPlugin implements MethodCallHandler, PluginRegistry.ActivityResultListener {
165 | ...
166 | public static void registerWith(Registrar registrar) {
167 | //传入Activity
168 | final FlutterMusicPlugin plugin = new FlutterMusicPlugin(registrar.activity());
169 | ...
170 | // 注册ActivityResult回调
171 | registrar.addActivityResultListener(plugin);
172 | }
173 |
174 | @Override
175 | public void onMethodCall(MethodCall call, Result result) {
176 | ...
177 | }
178 |
179 | @Override
180 | public boolean onActivityResult(int requestCode, int resultCode, Intent data) {
181 | ...
182 | return false;
183 | }
184 | }
185 |
186 | 复制代码
187 |
188 | ```
189 |
190 | 同时在 GeneratedPluginRegistrant 类中会自动生成
191 |
192 | ```
193 | public final class GeneratedPluginRegistrant {
194 | public static void registerWith(PluginRegistry registry) {
195 | if (alreadyRegisteredWith(registry)) {
196 | return;
197 | }
198 | FlutterMusicPlugin.registerWith(registry.registrarFor("com.plugin.FlutterMusicPlugin"));
199 | }
200 |
201 | private static boolean alreadyRegisteredWith(PluginRegistry registry) {
202 | final String key = GeneratedPluginRegistrant.class.getCanonicalName();
203 | if (registry.hasPlugin(key)) {
204 | return true;
205 | }
206 | registry.registrarFor(key);
207 | return false;
208 | }
209 | }
210 | 复制代码
211 |
212 | ```
213 |
214 | #### 注册人
215 |
216 | 它对应的是代码中的 GeneratedPluginRegistrant 类
217 |
218 | * 发起注册
219 |
220 | GeneratedPluginRegistrant 类中的
221 |
222 | ```
223 | FlutterMusicPlugin.registerWith(registry.registrarFor("com.plugin.FlutterMusicPlugin"));//即为发起注册点
224 | 复制代码
225 |
226 | ```
227 |
228 | * 通过注册商更新注册
229 |
230 | FlutterMusicPlugin 类中的
231 |
232 | ```
233 | registrar.addActivityResultListener(plugin);//即为通过注册商更新了需要Activity回调的信息
234 | 复制代码
235 |
236 | ```
237 |
238 | * 同步给注册局
239 |
240 | sdk 中的 FlutterRegistrar 类
241 |
242 | ```
243 | FlutterPluginRegistry.this.mActivityResultListeners.add(listener);//即为把信息同步给了注册局
244 | 复制代码
245 |
246 | ```
247 |
248 |
249 | #### 注册商
250 |
251 | 它对应的是代码中的 FlutterPluginRegistry 内部类 FlutterRegistrar。
252 |
253 | 不看不知道,"注册商" 其实给我们提供了很多功能,比如获取 activity,viewDestory 的生命周期的回调,获取 surfaceTexture 等等,真是一个能力强大的 "注册商"。
254 |
255 | ```
256 |
257 | Activity activity();//返回 Host app的Activity
258 | Context context();//返回 Application Context.
259 | Context activeContext();//返回 活动Context
260 | //返回 BinaryMessenger 主要用来注册Platform channels
261 | BinaryMessenger messenger();
262 | //返回 TextureRegistry,从里面可以拿到SurfaceTexture
263 | TextureRegistry textures();
264 | //返回 当前Host app创建的FlutterView
265 | FlutterView view();
266 | //返回Asset对应的文件路径
267 | String lookupKeyForAsset(String var1);
268 | //返回Asset对应的文件路径
269 | String lookupKeyForAsset(String var1, String var2);
270 | //插件对外发布的一个"值"
271 | PluginRegistry.Registrar publish(Object var1);
272 | //注册权限相关的回调
273 | PluginRegistry.Registrar addRequestPermissionsResultListener(PluginRegistry.RequestPermissionsResultListener var1);
274 | //注册ActivityResult回调
275 | PluginRegistry.Registrar addActivityResultListener(PluginRegistry.ActivityResultListener var1);
276 | //注册NewIntent回调
277 | PluginRegistry.Registrar addNewIntentListener(PluginRegistry.NewIntentListener var1);
278 | //注册UserLeaveHint回调
279 | PluginRegistry.Registrar addUserLeaveHintListener(PluginRegistry.UserLeaveHintListener var1);
280 | //注册View销毁回调
281 | PluginRegistry.Registrar addViewDestroyListener(PluginRegistry.ViewDestroyListener var1);
282 | 复制代码
283 |
284 | ```
285 |
286 | #### 注册局
287 |
288 | 它对应的是代码中的 FlutterPluginRegistry
289 |
290 | 
291 |
292 | 从成员变量可以看出 FlutterPluginRegistry 主要维护两类信息:
293 |
294 | 1. 注册插件唯一标识信息汇总
295 | 2. FlutterRegistrar 所开放的那些功能 (比如:addActivityResultListener) 的信息汇总
--------------------------------------------------------------------------------
/BlogArchive/让你的 Swift 代码更 Swift.md:
--------------------------------------------------------------------------------
1 | > 本文由 [简悦 SimpRead](http://ksria.com/simpread/) 转码, 原文地址 [juejin.cn](https://juejin.cn/post/7028506186743808008)
2 |
3 | > 这是我参与 11 月更文挑战的第 5 天,活动详情查看:[2021 最后一次更文挑战](https://juejin.cn/post/7023643374569816095 "https://juejin.cn/post/7023643374569816095")
4 |
5 | 引言
6 | --
7 |
8 | Swift 有很多其他语言所没有的独特的结构和方法,因此很多刚开始接触 Swift 的开发者并没有发挥它本身的优势。
9 |
10 | 所以,我们就来看一看那些让你的 Swift 代码更 Swift 的写法吧~
11 |
12 | 有条件的 for 循环
13 | -----------
14 |
15 | 现在,我们要对`view.subviews`中的`UIButton`做一些不可描述的事情,用 for 循环怎么来遍历呢?
16 |
17 | 在下面的写法中,更推荐后面两种写法:
18 |
19 | ```
20 | ❌
21 | for subView in view.subviews {
22 | if let button = subView as? UIButton {
23 | //不可描述的事情
24 | }
25 | }
26 |
27 | ✅
28 | for case let button as UIButton in view.subviews {
29 | //不可描述的事情
30 | }
31 |
32 | ✅
33 | for button in view.subviews where button is UIButton {
34 | //不可描述的事情
35 | }
36 |
37 | 复制代码
38 |
39 | ```
40 |
41 | enumerated()
42 | ------------
43 |
44 | 在 Swift 中进行 for 循环,要拿到下标值,一般的写法要么`定义局部变量记录下标值`,要么`遍历 0.. YourManager {
162 | //不可描述的事情
163 | }
164 | }
165 |
166 | let manager = YourManager.shared()
167 |
168 | ❌
169 | extension Date {
170 | func formattedString() -> String {
171 | //不可描述的事情
172 | }
173 | }
174 |
175 | let string = Date().formattedString()
176 |
177 |
178 | ✅
179 | class YourManager {
180 | static var shared: YourManager {
181 | //不可描述的事情
182 | }
183 | }
184 |
185 | let manager = YourManager.shared
186 |
187 | ✅
188 | extension Date {
189 | var formattedString: String {
190 | //不可描述的事情
191 | }
192 | }
193 |
194 | let string = Date().formattedString
195 | 复制代码
196 |
197 | ```
198 |
199 | 协议 vs 子类化
200 | ---------
201 |
202 | 尽量使用协议而不是继承。协议可以让代码更加灵活,因为类可同时遵守多个协议。
203 |
204 | 此外,结构和枚举不能子类化,但是它们可以遵守协议,这就更加放大了协议的好处
205 |
206 | Struct vs Class
207 | ---------------
208 |
209 | 尽可能使用 Struct 而不是 Class。Struct 在多线程环境中更安全,更快。
210 |
211 | 它们最主要的区别, Struct 是值类型,而 Classe 是引用类型,这意味着 Struct 的每个实例都有它自己的唯一副本,而 Class 的每个实例都有对数据的单个副本的引用。
212 |
213 | 这个链接是苹果官方的文档,解释如何在 Struct 和 Class 之间做出选择。 [Choosing Between Structures and Classes | Apple Developer Documentation](https://link.juejin.cn?target=https%3A%2F%2Fdeveloper.apple.com%2Fdocumentation%2Fswift%2Fchoosing-between-structures-and-classes "https://developer.apple.com/documentation/swift/choosing-between-structures-and-classes")
214 |
215 | 结语
216 | --
217 |
218 | 让我们的 Swift 代码更 Swift 的方法远不止上面这些,这里要说的是,平时写代码时,要刻意的使用 Swift 强大的特性,才能发挥它本身的价值。
219 |
220 | 而这些特性就需要大家去多看看官网的例子,或者一些主流的 Swift 第三方库,看看他们是如何运用 Swift 的特性的。
--------------------------------------------------------------------------------
/Files/3DTouch.md:
--------------------------------------------------------------------------------
1 | 使用3Dtouch请注意机型和系统的判断
2 |
3 | > ### 快捷启动
4 |
5 | * #### 姿势一: 配置plist文件
6 |
7 | 1.在inof.plist文件中添加数组类型的 UIApplicationShortcutitems
8 |
9 | 2.在这个数组(UIApplicationShortcutitems)里添加字典类型,表示每个选项
10 |
11 | 3.在字典中配置每个选项的属性值,如
12 |
13 | UIApplicationShortcutItemType:该QuickAction的标示符,全局唯一;
14 |
15 | UIApplicationShortcutItemTitle: 大字号主title
16 |
17 | UIApplicationShortcutItemSubtitle:中字号子title;
18 |
19 | UIApplicationShortcutItemIconType:该QuickAction的图标。
20 |
21 |
22 |
23 | 系统提供的UIApplicationShortcutItemIconType有如下类型:
24 |
25 | UIApplicationShortcutIconTypeCompose,
26 |
27 | UIApplicationShortcutIconTypePlay,
28 |
29 | UIApplicationShortcutIconTypePause,
30 |
31 | UIApplicationShortcutIconTypeAdd,
32 |
33 | UIApplicationShortcutIconTypeLocation,
34 |
35 | UIApplicationShortcutIconTypeSearch,
36 |
37 | UIApplicationShortcutIconTypeShare,
38 |
39 | UIApplicationShortcutIconTypeProhibit NS_ENUM_AVAILABLE_IOS(9_1),
40 |
41 | UIApplicationShortcutIconTypeContact NS_ENUM_AVAILABLE_IOS(9_1),
42 |
43 | UIApplicationShortcutIconTypeHome NS_ENUM_AVAILABLE_IOS(9_1),
44 |
45 | UIApplicationShortcutIconTypeMarkLocation NS_ENUM_AVAILABLE_IOS(9_1),
46 |
47 | UIApplicationShortcutIconTypeFavorite NS_ENUM_AVAILABLE_IOS(9_1),
48 |
49 | UIApplicationShortcutIconTypeLove NS_ENUM_AVAILABLE_IOS(9_1),
50 |
51 | UIApplicationShortcutIconTypeCloud NS_ENUM_AVAILABLE_IOS(9_1),
52 |
53 | UIApplicationShortcutIconTypeInvitation NS_ENUM_AVAILABLE_IOS(9_1),
54 |
55 | UIApplicationShortcutIconTypeConfirmation NS_ENUM_AVAILABLE_IOS(9_1),
56 |
57 | UIApplicationShortcutIconTypeMail NS_ENUM_AVAILABLE_IOS(9_1),
58 |
59 | UIApplicationShortcutIconTypeMessage NS_ENUM_AVAILABLE_IOS(9_1),
60 |
61 | UIApplicationShortcutIconTypeDate NS_ENUM_AVAILABLE_IOS(9_1),
62 |
63 | UIApplicationShortcutIconTypeTime NS_ENUM_AVAILABLE_IOS(9_1),
64 |
65 | UIApplicationShortcutIconTypeCapturePhoto NS_ENUM_AVAILABLE_IOS(9_1),
66 |
67 | UIApplicationShortcutIconTypeCaptureVideo NS_ENUM_AVAILABLE_IOS(9_1),
68 |
69 | UIApplicationShortcutIconTypeTask NS_ENUM_AVAILABLE_IOS(9_1),
70 |
71 | UIApplicationShortcutIconTypeTaskCompleted NS_ENUM_AVAILABLE_IOS(9_1),
72 |
73 | UIApplicationShortcutIconTypeAlarm NS_ENUM_AVAILABLE_IOS(9_1),
74 |
75 | UIApplicationShortcutIconTypeBookmark NS_ENUM_AVAILABLE_IOS(9_1),
76 |
77 | UIApplicationShortcutIconTypeShuffle NS_ENUM_AVAILABLE_IOS(9_1),
78 |
79 | UIApplicationShortcutIconTypeAudio NS_ENUM_AVAILABLE_IOS(9_1),
80 |
81 | UIApplicationShortcutIconTypeUpdate NS_ENUM_AVAILABLE_IOS(9_1),
82 |
83 | 4.在AppDelegate 中实现方法
84 |
85 | ```
86 | -(void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
87 |
88 | if ([shortcutItem.type isEqualToString:@"ShortCutOpen"]) {
89 | NSLog(@"ShortCutOpen");
90 | }
91 |
92 | if ([shortcutItem.type isEqualToString:@"ShortCutShare"]) {
93 | NSLog(@"ShortCutShare");
94 | SecondViewController *vc = [[SecondViewController alloc] init];
95 | [self.window.rootViewController presentViewController:vc animated:YES completion:nil];
96 | }
97 | }
98 | ```
99 |
100 | * #### 姿势二: 纯代码
101 |
102 | ```
103 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
104 |
105 | self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
106 |
107 | [self.window makeKeyAndVisible];
108 |
109 | self.window.rootViewController = [[ViewController alloc] init];
110 |
111 | [self creatShortcutItem];
112 |
113 | UIApplicationShortcutItem *shortcutItem = [launchOptions valueForKey:UIApplicationLaunchOptionsShortcutItemKey];
114 | /** app不在后台(已杀死),处理逻辑,返回NO,不调用 -application:performActionForShortcutItem:completionHandler: */
115 | if (shortcutItem) {
116 | if([shortcutItem.type isEqualToString:@"open_search"]){
117 | DDYInfoLog(@"open_search");
118 | } else if ([shortcutItem.type isEqualToString:@"open_qrcode"]) {
119 | DDYInfoLog(@"open_qrcode");
120 | }
121 | return NO;
122 | }
123 | return YES;
124 | }
125 |
126 | #pragma mark - 3D Touch
127 | #pragma mark 创建3DTouch列表
128 | - (void)creatShortcutItem {
129 | // 创建系统风格的icon
130 | UIApplicationShortcutIcon *icon1 = [UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeShare];
131 | UIApplicationShortcutItem *item1 = [[UIApplicationShortcutItem alloc] initWithType:@"open_search" localizedTitle:@"分享" localizedSubtitle:@"分享副标题" icon:icon1 userInfo:nil];
132 |
133 | // 创建自定义图标的icon
134 | UIApplicationShortcutIcon *icon2 = [UIApplicationShortcutIcon iconWithTemplateImageName:@"qrcode"];
135 | UIApplicationShortcutItem *item2 = [[UIApplicationShortcutItem alloc] initWithType:@"open_qrcode" localizedTitle:@"扫描" localizedSubtitle:@"扫描副标题" icon:icon2 userInfo:nil];
136 |
137 | // 添加到快捷选项数组
138 | [UIApplication sharedApplication].shortcutItems = @[item1, item2];
139 | }
140 |
141 | #pragma mark 修改3DTouch列表标签
142 | - (void)editShortcutItem {
143 | // 获取第0个shortcutItem
144 | UIApplicationShortcutItem *shortcutItem = [[UIApplication sharedApplication].shortcutItems objectAtIndex:0];
145 | // 将shortcutItem0的类型由UIApplicationShortcutItem改为可修改类型UIMutableApplicationShortcutItem
146 | UIMutableApplicationShortcutItem *item = [shortcutItem mutableCopy];
147 | // 修改shortcutItem的标题
148 | [item setLocalizedTitle:@"修改"];
149 | [item setLocalizedSubtitle:@"修改副标题"];
150 | [item setIcon:[UIApplicationShortcutIcon iconWithType:UIApplicationShortcutIconTypeAlarm]];
151 | // 将shortcutItems数组改为可变数组
152 | NSMutableArray *itemArray = [[UIApplication sharedApplication].shortcutItems mutableCopy];
153 | // 替换原ShortcutItem
154 | [itemArray replaceObjectAtIndex:0 withObject:item];
155 | [UIApplication sharedApplication].shortcutItems = itemArray;
156 | }
157 |
158 | #pragma mark 后台状态点击3DTouch选项进入APP
159 | /** app不在后台(已杀死),则处理逻辑在 -application:didFinishLaunchingWithOptions:中 */
160 | - (void)application:(UIApplication *)application performActionForShortcutItem:(UIApplicationShortcutItem *)shortcutItem completionHandler:(void (^)(BOOL))completionHandler {
161 |
162 | if (shortcutItem) {
163 | if([shortcutItem.type isEqualToString:@"open_search"]){
164 | DDYInfoLog(@"open_search");
165 | } else if ([shortcutItem.type isEqualToString:@"open_qrcode"]) {
166 | DDYInfoLog(@"open_qrcode");
167 | [self editShortcutItem];
168 | }
169 | }
170 |
171 | if (completionHandler) {
172 | completionHandler(YES);
173 | }
174 | }
175 | ```
176 |
177 |
178 | > ### Peak和Pop
179 |
180 | 1.在父级控制器中遵循 UIViewControllerPreviewingDelegate
181 |
182 | 2.在父级控制器中注册view,例如[self registerForPreviewingWithDelegate:self sourceView:cell];
183 |
184 | 3. 实现代理方法
185 |
186 | ```
187 | #pragma mark Peek预览
188 | - (nullable UIViewController *)previewingContext:(id )previewingContext viewControllerForLocation:(CGPoint)location
189 | {
190 | // 获取按压的cell所在行,[previewingContext sourceView]就是按压的那个视图
191 | NSIndexPath *indexPath = [_tableView indexPathForCell:(UITableViewCell* )[previewingContext sourceView]];
192 | if (indexPath.section==0 && indexPath.row==0) {
193 | // 设定预览的界面
194 | UIViewController *childVC = [NSClassFromString(self.dataArray[indexPath.row]) vc];
195 | childVC.preferredContentSize = CGSizeMake(0.0f, 500.0f);
196 | // 调整不被虚化的范围,按压的那个cell不被虚化(轻轻按压时周边会被虚化,再少用力展示预览,再加力跳页至设定界面)
197 | CGRect rect = CGRectMake(0, 0, DDYSCREENW,40);
198 | previewingContext.sourceRect = rect;
199 | // 返回预览界面
200 | return childVC;
201 | }
202 | return nil;
203 | }
204 |
205 | #pragma mark Pop用力按则进入
206 | - (void)previewingContext:(id )previewingContext commitViewController:(UIViewController *)viewControllerToCommit {
207 | [self showViewController:viewControllerToCommit sender:self];
208 | }
209 | ```
210 |
211 | 4.子级控制器中实现
212 |
213 | ```
214 | - (NSArray> *)previewActionItems {
215 | // 1
216 | UIPreviewAction *action1 = [UIPreviewAction actionWithTitle:@"Aciton1" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
217 | NSLog(@"Aciton1");
218 | }];
219 | // 2
220 | UIPreviewAction *action2 = [UIPreviewAction actionWithTitle:@"Aciton2" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
221 | NSLog(@"Aciton2");
222 | }];
223 | // 3
224 | UIPreviewAction *action3 = [UIPreviewAction actionWithTitle:@"Aciton3" style:UIPreviewActionStyleDefault handler:^(UIPreviewAction * _Nonnull action, UIViewController * _Nonnull previewViewController) {
225 | NSLog(@"Aciton3");
226 | }];
227 | // 先展示分组,点击分组进入分组内的actions
228 | UIPreviewActionGroup *group1 = [UIPreviewActionGroup actionGroupWithTitle:@"1" style:UIPreviewActionStyleDefault actions:@[action1, action2]];
229 | UIPreviewActionGroup *group2 = [UIPreviewActionGroup actionGroupWithTitle:@"2" style:UIPreviewActionStyleDestructive actions:@[action1, action3]];
230 | UIPreviewActionGroup *group3 = [UIPreviewActionGroup actionGroupWithTitle:@"3" style:UIPreviewActionStyleSelected actions:@[action2, action3]];
231 |
232 | NSArray *actions = @[group1, group2, group3];
233 |
234 | return actions;
235 | }
236 | ```
237 |
238 |
--------------------------------------------------------------------------------
/Files/AI.md:
--------------------------------------------------------------------------------
1 | ArtificialIntelligence
2 |
3 | * [tensorflow镜像](https://gitee.com/mirrors/tensorflow?_from=gitee_search)
4 | * [tensorflow官网](https://tensorflow.google.cn/lite/guide)
5 | * [tensorflow实例](https://github.com/tensorflow/examples/blob/master/lite/examples/gesture_classification/ios/README.md)
6 | * [开源代码换脸](https://github.com/deepfakes/faceswap)
7 | * [开发者预览版 — 基于 Mobile GPU 的 TensorFlow Lite 处理性能大幅提升](https://mp.weixin.qq.com/s?__biz=MzU1OTMyNDcxMQ==&mid=2247485486&idx=1&sn=a400a27e63538eb377ae3f9a73b6e133&chksm=fc184366cb6fca70e684a61946a3c9a7712de7fd7e9394db77ef4babf701cbbf9538a7b1d0f3&token=727582466&lang=zh_CN#rd)
8 | * [CoreML推测年龄](https://github.com/sayaleepote/Vision_CoreML-App)
9 | * [文本识别](https://github.com/sayaleepote/TextDetect)
10 | * [WhoAreYou](https://github.com/omarmhaimdat/WhoAreYou)
11 | * [面部识别](https://github.com/appcoda/Face-Mesh)
12 |
13 | * 研究AR云技术的公司:
14 | * [SenseAR http://openar.sensetime.com/](http://openar.sensetime.com/)
15 | * [Insider Navigation http://insidernavigation.com/](http://insidernavigation.com/)
16 | * [Scape https://scape.io/](https://scape.io/)
17 | * [YOUar http://youar.io/demos/](http://youar.io/demos/)
18 | * [6D http://6d.ai/](http://6d.ai/)
19 | * [Sturfee https://sturfee.com/](https://sturfee.com/)
20 | * [placenote https://placenote.com/](https://placenote.com/)
21 | * [8th Wall https://www.8thwall.com](https://www.8thwall.com)
22 | * [navisens https://www.navisens.com/](https://www.navisens.com/)
23 | * [contextgrid www.contextgrid.com](www.contextgrid.com)
24 | * [ubiquity6 https://ubiquity6.com/](https://ubiquity6.com/)
25 | * [blue vision https://bluevisionlabs.com](https://bluevisionlabs.com)
26 | * [immersal https://www.immersal.com/](https://www.immersal.com/)
27 | * [fantasmo https://fantasmo.io/](https://fantasmo.io/)
28 | * [dent reality https://www.dentreality.com/](https://www.dentreality.com/)
29 | * [open ar foundation https://arcloudfoundation.org/](https://arcloudfoundation.org/)
30 | * [https://gsdex.org/](https://gsdex.org/)
31 | * [EasyAR https://www.easyar.cn](https://www.easyar.cn)
32 |
33 | > ChatGPT、VITS、
34 | * [VITS-fast-fine-tuning](https://github.com/Plachtaa/VITS-fast-fine-tuning)
35 | * [【VITS/语音合成】贝露丹蒂语音模型文件分享](https://xbeibeix.com/video/BV1WY4y1X7Qx)
36 | * [讯飞语音](https://www.xfyun.cn/doc/tts/online_tts/iOS-SDK.html)
37 | * [huggingface.co](https://huggingface.co/spaces?sort=likes&search=vits)
38 | * [vits-chatgpt-live2d-unity-wife](https://gitee.com/DammonSpace/vits-chatgpt-live2d-unity-wife)
39 | * [Bilibili vits-chatgpt-live2d-unity-wife](https://www.bilibili.com/video/BV14L411U7J2/?vd_source=ced8d5357fe915a3115227c1fe98ea47)
40 | * [Vits-Android-ncnn](https://github.com/weirdseed/Vits-Android-ncnn)
41 | * [AI 唱歌](https://github.com/svc-develop-team/so-vits-svchttps://github.com/svc-develop-team/so-vits-svc)
42 | * [AI唱歌也算AI,sovits 唱歌项目使用分享](https://ngabbs.com/read.php?tid=35678209&rand=231)
43 | * [基于PP-TTS的安卓手机部署](https://aistudio.baidu.com/aistudio/projectdetail/5382080)
--------------------------------------------------------------------------------
/Files/Algorithm.md:
--------------------------------------------------------------------------------
1 | ### 算法
2 |
3 | > #### 求两个自然数P和Q的最大公约数r(P>=Q)
4 |
5 | * 欧几里得算法:
6 |
7 | ```
8 | 若Q为0,则r=P;若Q>0,P%Q=M,P和Q的最大公约数也就是Q和M的最大公约数,递归。
9 | ```
10 |
11 | * 伪代码:
12 |
13 | ```
14 | int gcd(int P, int Q) {
15 | if (0 == Q) {
16 | return P;
17 | } else {
18 | return gcd(Q, (P%Q));
19 | }
20 | }
21 | ```
22 | * 数学证明:
23 |
24 | ```
25 | // 证明Q不为0时,gcd(P,Q) = gcd(Q,P%Q)成立
26 |
27 | 证明:
28 | 设m为P和Q的最大公约数,即m=gcd(P,Q);
29 | 设n为Q和(P%Q)的最大公约数,即n=gcd(Q,P%Q);
30 | 那么存在自然数x,y使P=x*m,Q=y*m成立;
31 | P%Q等价于存在自然数z,r使r=P-z*Q成立;
32 | 那么 r = (x*m - z*(y*m)) = (x-z*y)*m
33 |
34 | ```
35 |
36 |
--------------------------------------------------------------------------------
/Files/AlwaysInline.md:
--------------------------------------------------------------------------------
1 | __attribute__((always_inline)) 的意思是强制内联,所有加了__attribute__((always_inline)) 的函数再被调用时不会被编译成函数调用而是直接扩展到调用函数体内
2 |
3 | 比如定义了函数
4 |
5 | ```
6 | __attribute__((always_inline)) void a()
7 |
8 | void b(){ a(); }
9 |
10 | ```
11 |
12 | b 调用 a 函数的汇编代码不会是跳转到a执行,而是 a 函数的代码直接在 b 内成为 b 的一部分
13 |
14 | #define __inline __attribute__((always_inline)) 的意思就是用
15 | __inline 代替__attribute__((always_inline))
16 | 内声明a的时候可以直接写成__inline void a() 这样比较方便因为__attribute__((always_inline)) 字多。
17 |
--------------------------------------------------------------------------------
/Files/BatteryLevel.md:
--------------------------------------------------------------------------------
1 | * 方法一:通过苹果官方文档里面UIDevice public API来获取 (不够精确)
2 |
3 | ```
4 | NSLog(@"电池电量:%.2f", [UIDevice currentDevice].batteryLevel);
5 | [UIDevice currentDevice].batteryMonitoringEnabled = YES;
6 | [[NSNotificationCenter defaultCenter] addObserverForName:UIDeviceBatteryLevelDidChangeNotification object:nil queue:[NSOperationQueue mainQueue] usingBlock:^(NSNotification *notification) {
7 | NSLog(@"电量改变为:%.2f", [UIDevice currentDevice].batteryLevel);
8 | }];
9 | ```
10 |
11 | * 方法二:利用私有IOKit.framework (不够精确且违规)
12 |
13 | * 方法三:通过runtime 获取iOS 6+ StatusBar上电池电量控件类私有变量的值 (相对精准)
14 |
15 | MRC: Build Phase —> Compile Source -> Compiler Flags : -fno-objc-arc
16 |
17 | ```
18 | - (int)getCurrentBatteryLevel {
19 | if ([UIApplication sharedApplication].applicationState != UIApplicationStateBackground) {
20 | void *result = nil;
21 | object_getInstanceVariable([UIApplication sharedApplication], "_statusBar", &result);
22 | id status = result;
23 | for (id aview in [status subviews]) {
24 | for (id bview in [aview subviews]) {
25 | int batteryLevel = 0;
26 | if ([NSStringFromClass([bview class]) caseInsensitiveCompare:@"UIStatusBarBatteryItemView"] == NSOrderedSame) {
27 | object_getInstanceVariable(bview, "_capacity", &result);
28 | batteryLevel = (int)result;
29 | NSLog(@"电池电量:%d",batteryLevel);
30 | if (batteryLevel > 0 && batteryLevel <= 100) {
31 | return batteryLevel;
32 | } else {
33 | return 0;
34 | }
35 | }
36 | }
37 | }
38 | }
39 | return 0;
40 | }
41 | ```
42 |
43 | ARC: Build Phase —> Compile Source -> Compiler Flags : -fobjc-arc
44 |
45 | ```
46 | - (int)getCurrentBatteryLevel {
47 | if ([UIApplication sharedApplication].applicationState != UIApplicationStateBackground) {
48 | Ivar ivar = class_getInstanceVariable([[UIApplication sharedApplication] class],"_statusBar");
49 | id status = object_getIvar([UIApplication sharedApplication], ivar);
50 | for (id aview in [status subviews]) {
51 | int batteryLevel = 0;
52 | for (id bview in [aview subviews]) {
53 | if ([NSStringFromClass([bview class]) caseInsensitiveCompare:@"UIStatusBarBatteryItemView"] == NSOrderedSame) {
54 | Ivar ivar = class_getInstanceVariable([bview class],"_capacity");
55 | if(ivar) {
56 | batteryLevel = ((int (*)(id, Ivar))object_getIvar)(bview, ivar);
57 | if (batteryLevel > 0 && batteryLevel <= 100) {
58 | return batteryLevel;
59 | } else {
60 | return 0;
61 | }
62 | }
63 | }
64 | }
65 | }
66 | }
67 | return 0;
68 | }
69 |
70 | ```
71 |
72 | 条件判断
73 |
74 | ```
75 | #if !__has_feature(objc_arc)
76 |
77 | #else
78 |
79 | #endif
80 | ```
81 |
--------------------------------------------------------------------------------
/Files/BuildConfiguration.md:
--------------------------------------------------------------------------------
1 | # 配置
2 |
3 | 1. PROJECT ——> Info ——> Configurations
4 | 2. 点击 + 添加新的,如 OnlineDebug
5 | 3. TARGET ——> Build Setting ——> Active Compilation Conditions
6 | 4. 修改新加的OnlineDebug的值为ONLINEDEBUG
7 | 5. TARGET ——> Build Setting ——> Other Swift Flags
8 | 6. 修改新加的OnlineDebug的值为-D ONLINEDEBUG
9 | 7. 修改新加的Debug的值为-D DEBUG
10 | 8. 如果使用CocoaPods可以执行更新命令
11 |
12 | # 使用
13 |
14 | 1. 打印方式
15 |
16 | Objective-C
17 |
18 | ```
19 | // 自定义打印 宏定义
20 | #ifdef DEBUG
21 | #define DDYInfoLog(fmt, ...) NSLog((@"\nDebug\nFileName:%s\nMethodName:%s\nLineNumber:%d\n" fmt),__FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
22 | #elseif ONLINEDEBUG
23 | #define DDYInfoLog(fmt, ...) NSLog((@"\nOnlineDebug\nFileName:%s\nMethodName:%s\nLineNumber:%d\n" fmt),__FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
24 | #else
25 | #define DDYInfoLog(fmt, ...) NSLog((@"\nRelease\nFileName:%s\nMethodName:%s\nLineNumber:%d\n" fmt),__FILE__, __FUNCTION__, __LINE__, ##__VA_ARGS__)
26 | #endif
27 | ```
28 |
29 | Swift
30 |
31 | ```
32 | // 自定义打印 全局函数
33 | func ddyInfoLog(_ message: T, fileName: String = #file, methodName: String = #function, lineNumber: Int = #line) {
34 | #if DEBUG
35 | print("\nDebug\nFileName:\(fileName as NSString)\nMethodName:\(methodName)\nLineNumber:\(lineNumber)\n\(message)")
36 | #elseif ONLINEDEBUG
37 | print("\nOnlineDebug\nFileName:\(fileName as NSString)\nMethodName:\(methodName)\nLineNumber:\(lineNumber)\n\(message)")
38 | #else
39 | print("\nRelease\nFileName:\(fileName as NSString)\nMethodName:\(methodName)\nLineNumber:\(lineNumber)\n\(message)")
40 | #endif
41 | }
42 | ```
43 |
44 | 2. 网络请求Host
45 |
46 | Objective-C
47 |
48 | ```
49 | #ifdef DEBUG
50 | #define requestHost @"http://10.10.8.22:9214"
51 | #elseif ONLINEDEBUG
52 | #define requestHost @"http://online-test.idengyun.com"
53 | #else
54 | #define requestHost @"http://online-test.idengyun.com"
55 | #endif
56 | ```
57 |
58 | Swift
59 |
60 | ```
61 | func requestHost() -> String {
62 | #if DEBUG
63 | return "http://10.10.8.22:9214"
64 | #elseif ONLINEDEBUG
65 | return "http://online-test.idengyun.com"
66 | #else
67 | return "http://app.iblln.com"
68 | #endif
69 | }
70 | ```
71 |
72 | 3. AppIcon
73 |
74 | * 使用Asset Catalog 分别命名为
75 | AppIconDebug
76 | AppIconOnlineDebug
77 | AppIconRelease
78 |
79 | * Target ——> Build Settings 搜索 Asset Catalog App Icon Set Name
80 | 对应的修改选项值
81 |
82 | 4. AppName
83 |
84 | * Target ——> Build Settings里点+号,添加一个User-Defined Setting
85 | * 建立key值 APP_DISPLAY_NAME, 然后对应的修改选项值
86 | * 进到 Target ——> Info里,修改 Bundle Name 为$(APP_DISPLAY_NAME)
87 |
88 | 5. 打包配置
89 |
90 | 将Release环境以外的Skip Install配置成NO。
91 |
92 |
93 |
94 |
95 |
--------------------------------------------------------------------------------
/Files/CallKit.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/Files/CallKit.md
--------------------------------------------------------------------------------
/Files/Carthage.md:
--------------------------------------------------------------------------------
1 | > #### 一、准备(按需执行)
2 |
3 | * ##### 升级homebrew
4 |
5 | 1. 查看版本 ``` brew --version ```
6 | 2. 卸载brew ``` ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)" ```
7 | 3. 安装brew ``` ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" ```
8 | 4. 查看版本 ``` brew --version ```
9 | 5. 安装目录 ``` which brew ```
10 |
11 | > #### 二、安装与使用
12 |
13 | * ##### 安装
14 |
15 | 1. 安装 ``` brew install carthage ```
16 | 2. 版本 ``` carthage version ```
17 | 3. 升级 ``` brew upgrade carthage ```
18 |
19 | * ##### 使用
20 |
21 | 1. cd 工程目录
22 | 2. 建立Cartfile文件 ``` touch Cartfile ```
23 | 3. 打开Cartfile ``` open -e Cartfile ``` 或 ``` open -a Xcode Cartfile ```
24 | 4. 添加github的三方库,如 ``` github "ReactiveCocoa/ReactiveCocoa" # GitHub.com ```
25 | 5. 添加GitHubEnterprise的三方库,如 ```
26 | github "https://enterprise.local/ghe/desktop/git-error-translations" # GitHub Enterprise ```
27 | 6. 添加其他git,如私有git ``` git "git@git.idengyun.com:iOSTeam/KNNewRetail.git" "1.0.80" ```
28 | 7. 只支持二进制文件发framework ``` binary "https://my.domain.com/release/MyFramework.json" ```
29 | 8. 版本号
30 |
31 | ```
32 | github "aaa/bbb" // 不指定版本号,永远获取最新的版本
33 | github "aaa/bbb" == 1.0 // 只1.0版本
34 | github "aaa/bbb" ~> 1.0.0 // 1.0及以上的兼容版本
35 | "some-branch-or-tag-or-commit" //特定的分支、tag、或提交
36 | ```
37 | 9. 更新库
38 | ```
39 | // 指定平台
40 | carthage update --platform iOS
41 | // 不适用二进制
42 | carthage update --no-use-binaries --platform ios
43 | // 更新指定库
44 | carthage update Alamofire
45 | // 更新指定多个库空格分开
46 | carthage update Alamofire SnapKit
47 | ```
48 |
49 | > #### 三、让自己的库支持cocoapods管理
50 |
51 | * ##### Carthage 仅支持动态库
52 | * ##### Carthage 提供给用户的动态库是根据项目中的 动态库 Target 编译打包后生成的
53 | * ##### 步骤
54 |
55 | 1. 新建Target,选择Cocoa Touch Framework,并设置Deployment Target
56 | 2. 添加 .h 文件到 Build Phases -> Headers -> Public
57 | 3. 添加 .m 文件到 Build Phases -> Compile Sources
58 | 4. 添加其它资源文件到 Build Phases -> Copy Bundle Sources
59 | 5. Carthage只构建从 .xcodeproj 分享出来的scheme,所以需要在 Manage Schemes 中将新生成的 scheme 设置为 shared
60 | 6. 通过 ```carthage build --no-skip-current``` 来检测 scheme 是否能够构建成功,然后检查 Carthage/Build 目录
61 | 7. Carthage 通过搜索 Git tag 来决定用户可以下载哪个版本的项目资源,所以还需要在提交代码后添加 tag 并 push 到 GitHub,格式建议写成 1.2.0 或 v1.2
62 | 8. 通过添加下面内容,用来在项目 Readme.md 文件上显示 [](https://github.com/Carthage/Carthage)
63 |
64 | ```
65 | [](https://github.com/Carthage/Carthage)
66 | ```
67 |
68 |
69 |
70 |
71 |
72 |
73 |
74 |
75 |
76 | [Carthage cocoapods](https://zhuanlan.zhihu.com/p/34618747)
77 |
78 |
79 |
--------------------------------------------------------------------------------
/Files/Chrome.md:
--------------------------------------------------------------------------------
1 | > #### 地址栏显示完整地址的方法
2 |
3 | * 地址栏输入chrome://flags/ 回车
4 | * 找到 Omnibox UI Hide Steady-State URL Scheme and Trivial Subdomains
5 | * 设置为Disabled,然后重启浏览器
6 |
7 | > #### 离线程序安装提示'无法从该网站添加应用、扩展程序和用户脚本'
8 |
9 | * 地址栏输入chrome://flags/ 回车
10 | * 找到 Extensions on chrome:// URLs
11 | * 设置为Enabled,然后重启浏览器
12 | * 如果必要,先打开开发者模式,安装后再关闭
13 |
14 | > #### 打开全部下载列表
15 |
16 | * 地址栏输入 chrome://downloads 回车
17 |
18 | > #### 安装同一个账号其他设备上的扩展
19 |
20 | * [https://chrome.google.com/webstore/user/library](https://chrome.google.com/webstore/user/library)
21 |
22 | > #### 扩展镜像打包下载
23 |
24 | * [扩展迷](https://extfans.com)
25 | * [gugeapps](https://gugeapps.net)
26 | * [极简插件](http://chrome.zzzmh.cn)
27 |
28 | > #### 一些好用的插件
29 |
30 | * 访问谷歌服务[谷歌访问助手]()
31 | * 标签页美化[Infinity Pro]
32 | * Github美化目录[Octotree]()
33 | * 资源嗅探[猫抓]()
34 | * 开发工具集[开发工具箱]()
--------------------------------------------------------------------------------
/Files/DeleteSystemABC.md:
--------------------------------------------------------------------------------
1 | # 起因
2 |
3 | 作为一个中国人,使用国内输入法必不可少,但是Mac 系统自带的ABC/U.S 输入法严重干扰了我们的使用。很想把它弄屎。。。
4 |
5 | # 经过
6 |
7 | * 禁止SIP(系统完整性保护-System Integrity Protection)
8 |
9 | 1. 重启系统,按住 Command + R 进入恢复模式;
10 | 2. 点击顶部菜单栏 实用工具 中的 终端;
11 | 3. 输入 ```csrutil disable``` 来禁用 SIP 保护机制;
12 | 4. 重启系统
13 | 5. 如果想重新开启按上述步骤,然后执行 ```csrutil enable```
14 |
15 | * 修改
16 |
17 | 1. 安装国内好用的输入法,例如搜狗输入法、手心输入法
18 | 2. 禁止SIP后正常进入系统,终端输入 ```sudo open ~/Library/Preferences/com.apple.HIToolbox.plist```(最好备份下)
19 | 3. 找到AppleEnabledInputSources 条目下 ABC 或 U.S item项,并删除整个item
20 | 4. 重启电脑(有时候重启不生效,那就关机重新开机)
21 | 5. 如果生效,以后就可以只保留已安装的三方输入法了,按默认shift键就快速切换英汉输入
22 | 6. 恢复ABC输入法 偏好设置->键盘->输入法,点 + 号,重新添加就可以了
23 |
24 |
--------------------------------------------------------------------------------
/Files/DevelopEnglish.md:
--------------------------------------------------------------------------------
1 | anchor : ['æŋkər] 锚点
2 |
3 | asynchronous : [eɪˈsɪŋkrənəs] 异步的
4 |
5 | collider : [kə'laɪdə(r)] 碰撞器
6 |
7 | console : [kənˈsoʊl, ˈkɑːnsoʊl] 控制台
8 |
9 | coroutine : [kəru'tin] 协程
10 |
11 | cylinder : [sɪlɪndər] 圆柱体
12 |
13 | decor : [deɪˈkɔr] 装饰品
14 |
15 | destroy : [dɪ'strɔɪ] 销毁
16 |
17 | device : [dɪˈvaɪs] 设备
18 |
19 | enum : 英[ˈenəm] 美[ɪˌnjuːm] 枚举
20 |
21 | enumeration : 英[ɪˌnjuːmə'reɪʃn] 美[ɪˌnjuːmə'reɪʃn] 列举
22 |
23 | Execute : ['eksə.kjut] 执行
24 |
25 | exit : [ˈeksɪt] 退出
26 |
27 | GUI : [ˈɡuːi] Graphical User Interface 图形用户界面
28 |
29 | hierarchy : [ˈhaɪərɑːrki] 层次体系,层次面板
30 |
31 | horizontal : [.hɔrɪ'zɑnt(ə)l] 横向的
32 |
33 | inspector : [ɪnˈspektər] 检查员,检视面板
34 |
35 | joystick : [ˈdʒɔɪˌstɪk] 摇杆,操纵杆
36 |
37 | Linq : [lin:k] 语言集成查询
38 |
39 | material : [mə'tɪriəl] 材料,材质
40 |
41 | Mono : ['mɑnoʊ] 单声道
42 |
43 | NuGet : New Get 微软包含.net的开发平台包管理器
44 |
45 | Orthographic : [ˌɔrθə'ɡræfɪk] 直线的,正交视图
46 |
47 | perspective : [pərˈspektɪv] n.远景 adj.透视的
48 |
49 | plugin : ['plʌgɪn] 插件
50 |
51 | Probes : [proʊb] 探针,探测点
52 |
53 | projection : [prəˈdʒekʃ(ə)n] 投影,投射
54 |
55 | scene : [sin] 场景
56 |
57 | schema : [ˈskimə] 模式,架构
58 |
59 | sprite : [spraɪt] 精灵
60 |
61 | synchronization : [ˌsɪŋkrənaɪ'zeɪʃ(ə)n] 同步性
62 |
63 | trigger : [ˈtrɪɡər] 触发器
64 |
65 | tutorial : 美[tu'tɔriəl] 英[tjuː'tɔːriəl] 教程,指南
66 |
67 | virtual : [ˈvɜrtʃuəl] 虚拟的,实质上的
68 |
69 | * [程序员常用英语单词汇总](https://blog.csdn.net/RootCode/article/details/93748701)
70 | * [游戏中常用术语](https://blog.csdn.net/cartzhang/article/details/114530419)
--------------------------------------------------------------------------------
/Files/Exit.md:
--------------------------------------------------------------------------------
1 | # 主动退出程序
2 |
3 | ```
4 | typedef NS_ENUM(NSUInteger, AppExitTag) {
5 | AppExitTagExit = 1,
6 | AppExitTagAbort = 2,
7 | AppExitTagAssert = 3,
8 | };
9 |
10 | - (void)exitApplication {
11 | //直接退,看起来好像是 crash 所以做个动画
12 | [UIView beginAnimations:@"exitApplication" context:nil];
13 | [UIView setAnimationDuration:0.5];
14 | [UIView setAnimationDelegate:self];
15 | [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view.window cache:NO];
16 | [UIView setAnimationDidStopSelector:@selector(animationFinished:finished:context:)];
17 | self.view.window.bounds = CGRectMake(0, 0, 0, 0);
18 | [UIView commitAnimations];
19 | }
20 |
21 | - (void)animationFinished:(NSString *)animationID finished:(NSNumber *)finished context:(void *)context {
22 | if ([animationID compare:@"exitApplication"] == 0) {
23 | // 退出代码
24 | [self exitApp:AppExitTagExit];
25 | }
26 | }
27 |
28 | - (void)exitApp:(AppExitTag)tag {
29 | switch (tag) {
30 | case AppExitTestTag_Exit:
31 | exit(0);// exit(1)表示异常退出
32 | break;
33 | case AppExitTestTag_Abort:
34 | abort();
35 | break;
36 | case AppExitTestTag_Assert:
37 | assert(0);
38 | break;
39 | default:
40 | break;
41 | }
42 | }
43 |
44 | ```
--------------------------------------------------------------------------------
/Files/FFMpeg.md:
--------------------------------------------------------------------------------
1 | ```
2 | ffmpeg -y -i 「视频全名」 -vf subtitles=「字幕文件名」 「导出的视频文件名」
3 | // wav 转 mp3
4 | ffmpeg -i /Users/mac/Pictures/Work/yidaozhang/222.wav -b:a 64k -acodec mp3 -ar 44100 -ac 1 2.mp3
5 | // 音频拼接
6 | ffmpeg -i "concat:1.mp3|2.mp3" -acodec copy 3.mp3
7 | // 一张图片 + 音频 -t 30 长度秒
8 | ffmpeg -r 15 -f image2 -loop 1 -i 3.png -i 3.mp3 -c:v libx265 -movflags faststart -tag:v hvc1 -t 30 -y 666.mp4
9 |
10 | ffmpeg -i ${oldFille} -acodec copy -map_metadata -1 -metadata title="com.nwyunlingvideo.mryjios" -y ${newFile}
11 |
12 | python3 /Users/mac/Desktop/cocosProject/AiShangXiaoFangKuai/encrypt.py /Users/mac/Downloads/lottie/pic/ com.nwyunlingvideo.mryjios
13 |
14 | ffmpeg -i ./MQNewMessageRingStyle23.wav -acodec copy -map_metadata -1 -metadata title="com.fkbgyes.luckysongios" -y ./MQNewMessageRingStyle2.wav
15 |
16 | ffmpeg -i ./MQNewMessageRing3.mp3 -acodec copy -map_metadata -1 -metadata title="com.fkbgyes.luckysongios" -y ./MQNewMessageRing.mp3
17 |
18 | ffmpeg -i ./MQSendMessageRing3.mp3 -acodec copy -map_metadata -1 -metadata title="com.fkbgyes.luckysongios" -y ./MQSendMessageRing.mp3
19 |
20 | ffmpeg -i 240103001.mp4 -c:a copy -c:v libx265 -preset slow -vf "deblock,hqdn3d" -movflags faststart -max_muxing_queue_size 2048 -threads 8 -tag:v hvc1 -y 240103009.mp4
21 |
22 | ffmpeg -i 0.mp4 -c:a copy -c:v libx265 -preset slow -vf "deblock,hqdn3d" -movflags faststart -max_muxing_queue_size 2048 -threads 8 -tag:v hvc1 -y 4.mp4
23 |
24 |
25 | ffmpeg -i 240103002.mp4 -c:a copy -c:v libx265 -preset slower -vf "deblock,hqdn3d" -crf 20 -movflags faststart -max_muxing_queue_size 2048 -threads 16 -tag:v hvc1 -y 240103007.mp4
26 | ```
27 |
28 | * [Mac平台下的FFmpeg的安装编译](https://juejin.cn/post/7005112278706028551)
29 | * [在Linux/Mac/Windows上配置FFmpeg开源音频工具,轻松完成视频转码、音频混合等操作](https://www.mintimate.cn/2020/02/25/FFmpeg/)
30 | * [ffmpeg_cheatsheet](https://gitlab.fhnw.ch/hgk-ml/hgk-ml-tools/-/tree/master/ffmpeg_cheatsheet)
31 | * [视频文件太大?使用FFmpeg来无损压缩它](https://zhuanlan.zhihu.com/p/564071964)
32 | * [FFmpeg命令行:如何压制与QuickTime兼容的HEVC视频](https://blog.csdn.net/iBobbyTS/article/details/109402983)
--------------------------------------------------------------------------------
/Files/Flutter.md:
--------------------------------------------------------------------------------
1 | > ## 命令
2 |
3 | * flutter --help 获取命令帮助
4 | * flutter --version 打印版本(flutter版本和dart版本)
5 | * flutter channel 打印渠道(星号表示当前选中的渠道)
6 |
7 | * stable 稳定版,差不多一年才从beta版中择优作为一版
8 | * beta 测试版,每隔几周选取近几个月最好的dev版作beta版
9 | * dev 最新经过测试的版本,包含新功能,但可能存在一些问题
10 | * master 主分支最新版,还未经严格测试
11 |
12 | * flutter channel stable 切换到稳定版
13 | * flutter uograde 升级通道channel和依赖包packages
14 | * flutter packages get 获取pubspec.yaml中所有的依赖关系
15 | * flutter packages upgrade 升级pubspec.yaml中所有的依赖
16 | * flutter emulators 列出所有可用模拟器(如apple_ios_simulator)
17 | * flutter devices 列出所有连接的真机
18 | * flutter create aaa_bbb 创建一个名为aaa_bbb的工程(只能下划线不能横线)
19 | * flutter emulator --launch apple_ios_simulator 启动模拟器
20 | * flutter run 运行工程
21 |
22 | > 库
23 |
24 | * 网络 dio
25 | * 数据库 [sqflite](https://pub.dartlang.org/packages/sqflite)
--------------------------------------------------------------------------------
/Files/Framework.md:
--------------------------------------------------------------------------------
1 | 当我们点击xcode工程的target时,在Build Phases这块framework可选的状态有下面几种:在xcode 10及之前,有三种状态:Do Not Embed、Embed & Sign和Embed Without Signing
2 |
3 | Embed:嵌入,用于动态库,动态库在运行时链接,所以它们需要被打进bundle里面。如何判断呢?使用终端执行
4 |
5 | ```
6 | file frameworkToLink.framework/frameworkToLink
7 |
8 | current ar archive:说明是静态库,选择Do not embed
9 | Mach-0 dynamically:说明是动态库,选择Embed
10 | ```
11 |
12 | 静态库和动态库的区别
13 |
14 | ```
15 | 静态库:链接时完整地拷贝至可执行文件中,被多次使用就有多份冗余拷贝,存在形式:.a和.framework
16 | 动态库:链接时不会拷贝至可执行文件中,程序运行时由系统动态加载到内存以供程序调用,系统只加载一次,多个程序共用,可以节省内存。存在形式:.dylib和.framework
17 | ```
18 |
19 | Signing:只用于动态库,如果已经有签名了就不需要再签名。如何判断呢?使用终端执行
20 |
21 | ```
22 | codesign -dv frameworkToLink.framwork
23 |
24 | code object is not signed at all 或者 adhoc:选择Embed and sign
25 | 其它:表示已经正确签名,选择Embed Without Signing
26 | ```
27 |
28 |
29 | [Unity2019 4.37f1 打包iOS 所遇问题与解决方案](https://www.jianshu.com/p/4381dc7b2fb8)
30 | [C++中调用OC代码](https://blog.csdn.net/u013712343/article/details/122623800)
--------------------------------------------------------------------------------
/Files/Git.md:
--------------------------------------------------------------------------------
1 | > #### 基础命令含义
2 |
3 | * clone 克隆远程仓库
4 | * init 初始化仓库
5 | * remote 连接远程仓库
6 | * pull 从远程仓库下拉获取新数据
7 | * push 将本地仓库新增或修改文件上传到远程仓库
8 | * add 添加文件或者修改文件,commit以及push之前使用
9 | * log 当前仓库提交过的日志信息
10 | * status 当前仓库版本状态
11 | * commit 提交到当前仓库中
12 | * branch 分支命令,相关增删查操作
13 | * checkout 使用远程仓库最后一个版本完全覆盖当前仓库内容/选择分支branch
14 | * diff 对比版本内容
15 | * merge 合并版本内容
16 |
17 | > #### 使用前配置
18 |
19 | * ##### 设置基本信息
20 |
21 | ###### 初始化仓库
22 |
23 | ```
24 | # 在项目中创建.git文件
25 | git init
26 |
27 | ```
28 |
29 | ###### 设置信息
30 |
31 | ```
32 | # 建议局部配置(防止因为不同Email导致无法正常生成记录)
33 | # 设置用户名
34 | git config user.name "MyName"
35 | # 设置Email
36 | git config user.email "My@Email.com"
37 | # 显示配置信息
38 | git config --list
39 | # 开启颜色
40 | git config color.ui true
41 | # 如果全局配置加 --global
42 | # git config --global user.name "MyName"
43 | # git config --global user.email "My@Email.com"
44 | # git config --global --list
45 | # git config --global color.ui true
46 | # 配置选项有三种:–system,–global 和 –local
47 | ```
48 |
49 | ###### 创建忽略文件
50 |
51 | ```
52 | touch .gitignore
53 | ```
54 |
55 | 添加忽略文件内容
56 | (切记,如果想忽略的文件已经进行版本管控了,再添加新的忽略,也不会起作用)
57 |
58 |
59 | ```
60 | # Xcode
61 | .DS_Store
62 | build/
63 | *.pbxuser
64 | !default.pbxuser
65 | *.mode1v3
66 | !default.mode1v3
67 | *.mode2v3
68 | !default.mode2v3
69 | *.perspectivev3
70 | !default.perspectivev3
71 | #*.xcworkspace
72 | #!default.xcworkspace
73 | xcuserdata
74 | profile
75 | *.moved-aside
76 | DerivedData
77 | .idea/
78 | *.xcuserstate
79 | # Pods - for those of you who use CocoaPods
80 | #Pods
81 | ```
82 |
83 | ###### 将项目中所有修改过的工作文件提交暂存区
84 |
85 | ```
86 | # 注意空格
87 | git add .
88 | ```
89 |
90 | ###### 提交新增内容
91 |
92 | ```
93 | git commit -m 'git初始化操作'
94 | ```
95 |
96 | ###### 密钥管理
97 |
98 | ```
99 | # 检查 SSH key 是否存在
100 | ls -al ~/.ssh
101 | # 生成新的SSH Key文件(为防止错误,特别公用电脑,最好重新生成)
102 | ssh-keygen -t rsa -C "My@Email.com"
103 | # 此时会生成id_rsa.pub(RSA加密公钥)和id_rsa(RSA加密私钥)
104 | # 如果没有配置过可以三个回车
105 | # 如果配置过,提示overwrite (y/n)? 则输入y并回车
106 | # 提示Enter passphrase 可以不设置密码直接回车
107 | # 添加key到SSH中去
108 | ssh-add ~/.ssh/id_rsa
109 | # 复制SSH key
110 | pbcopy < ~/.ssh/id_rsa.pub
111 | # 打开储存SSH key的文件夹
112 | open ~/.ssh
113 | # 如果想删除key可以把文件夹内容删除(最好别删除)
114 | # 将copy的key添加到远程git的配置中
115 | ```
116 |
117 | ###### 本地关联远程
118 |
119 | ```
120 | # git remote add 仓库名称 仓库地址
121 | git remote add origin project@MyProject.git
122 |
123 | ```
124 |
125 | ###### 查看仓库名称
126 |
127 | ```
128 | git remote
129 | ```
130 |
131 | ###### 将origin仓库推送到master分支
132 |
133 | ```
134 | git push origin master
135 | ```
136 |
137 | ###### 回到指定版本
138 |
139 | ```
140 | # 回到当前版本
141 | git reset --hard HEAD
142 | # 回到上上个版本
143 | git reset --hard HEAD^^
144 | # 回到往前2个版本
145 | git reset --hard HEAD~2
146 | # 回到指定版本(七位版本号)
147 | git reset --hard 1234567
148 | ```
149 |
150 | ###### 日志信息
151 |
152 | ```
153 | # 查看日志版本信息
154 | git log
155 | # 查看日志七位版本号及回退信息
156 | git reflog
157 |
158 |
159 | git log --author='豆电雨' --after='2020-8-16' --before='2020-8-24'
160 | ```
161 |
162 | ###### 查看项目的提交状态
163 |
164 | ```
165 | git status
166 | ```
167 |
168 | ###### 差异化
169 |
170 | ```
171 | git diff # 比较当前文件和暂存区文件差异 git diff
172 | git diff # 比较两次提交之间的差异
173 | git diff .. # 在两个分支之间比较
174 | git diff --staged # 比较暂存区和版本库差异
175 | git diff --cached # 比较暂存区和版本库差异
176 | git diff --stat # 仅仅比较统计信息
177 | ```
178 |
179 | ###### 设置代理
180 |
181 | ```
182 | # socks5代理
183 | git config --global http.proxy 'socks5://127.0.0.1:1080'
184 | git config --global https.proxy 'socks5://127.0.0.1:1080'
185 | // http/https 代理
186 | git config --global https.proxy http://127.0.0.1:1080
187 | git config --global https.proxy https://127.0.0.1:1080
188 |
189 | #取消
190 | git config --global --unset http.proxy
191 | git config --global --unset https.proxy
192 | ```
193 |
194 | > #### SourceTree设置忽略文件不生效问题
195 |
196 | * 点击工程管理界面右上角终端按钮
197 | * 删除缓存(注意有个实心点) ``` git rm -r --cached . ```
198 | * 本工程忽略文件:点击右上角设置->高级->编辑gitignore
199 | * 全局忽略文件:点击左上角菜单SourceTree->首选项(可能有的交偏好设置)->Git->编辑文件
200 | * git add .
201 | * git commit -m 'ignore something'
202 |
203 |
204 | > #### 修改已提交但未推送的message
205 |
206 | ```
207 | Git bush中执行命令 git commit --amend
208 | 然后直接修改备注保存即可。
209 | 保存方式:
210 | 1)按Esc退出编辑
211 | 2)输入 :wq (保存并退出)
212 | 不保存退出输入 :q!
213 | ```
214 |
215 | > #### 删除已经提交但未推送的更改
216 |
217 | ```
218 | 撤销git commit,撤销git add,保留编辑器改动代码 git reset --mixed HEAD~1
219 | 撤销git commit,撤销git add,保留编辑器改动代码 git reset --soft HEAD~1
220 | 撤销git commit,撤销git add,删除编辑器改动代码 git reset --hard HEAD~1
221 | ```
222 |
223 | > #### 从零开始关联提交到git
224 |
225 | ```
226 | mkdir images
227 | cd images
228 | git init
229 | touch README.md
230 | git add README.md // git add .
231 | git commit -m "first commit"
232 | git remote add origin https://gitee.com/rainopen/images.git
233 | git push -u origin master
234 | ```
235 |
236 | > #### 附
237 |
238 | * [参考](https://git-scm.com/book/zh/v1/自定义-Git-配置-Git)
239 | * [参考](http://www.cocoachina.com/articles/21163)
240 | * [参考](https://blog.csdn.net/hmh007/article/details/50726318)
241 | * [参考](https://www.jianshu.com/p/f46aa9d0dc43)
242 | * [git自动补全](https://github.com/git/git/tree/35f6318d44379452d8d33e880d8df0267b4a0cd0/contrib/completion)
243 | * [gitforwindows淘宝镜像](http://npm.taobao.org/mirrors/git-for-windows/)
244 | * [如何删除未推送的git commit?](https://blog.csdn.net/asdfgh0077/article/details/103596340)
245 | * [Git删除已提交但未推送的commit](https://blog.csdn.net/u013986317/article/details/107106702)
246 | * [macOS 升级 Git 版本](https://www.jianshu.com/p/6eca0eadcc22)
--------------------------------------------------------------------------------
/Files/Hackintosh.md:
--------------------------------------------------------------------------------
1 | * n[macOS Monterey 12.0安装中常见的问题及解决方法](https://blog.daliansky.net/Common-problems-and-solutions-in-macOS-Monterey-12.0-installation.html)
2 | * [升级黑苹果EFI内OpenCore和驱动等](https://blog.51cto.com/u_15898395/5901458)
3 | * [苹果 macOS Monterey 12.6.4 (21G526) 原版镜像发布下载](www.dayanzai.me/macos-monterey.html)
4 | * [OC Auxiliary Tools](https://www.mfpud.com/opencore/ocat/page/2/)
5 | * [OC(OpenCore) EFI引导版本升级](https://hackintosh.myitnote.com/efi/update.html#_1-挂载-efi-分区)
--------------------------------------------------------------------------------
/Files/Handoff.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/Files/Handoff.md
--------------------------------------------------------------------------------
/Files/Homebrew.md:
--------------------------------------------------------------------------------
1 | * Xcode 工具按需安装 ``` xcode-select --install ```
2 | * 卸载Homebrew ``` /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)" ```
3 | * 安装Homebrew ``` /usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" ```
4 | * 帮助 ``` brew help ```
5 | * 版本 ``` brew -v ``` 或 ``` brew --version ```
6 | * 更新Homebrew自己 ``` brew update ```
7 | * 安装软件包 ``` brew install 包名 ```
8 | * 重置Homebrew ``` brew update-reset ```
9 | * 查看哪些安装包需要更新 ``` brew outdated ```
10 | * 更新安装包 ``` brew upgrade # 更新所有的包 brew upgrade $FORMULA # 更新指定的包 ```
11 | * 清理旧版本 ``` brew cleanup # 清理所有包的旧版本
12 | brew cleanup $FORMULA # 清理指定包的旧版本
13 | brew cleanup -n # 查看可清理的旧版本包,不执行实际操作
14 | ```
15 | * 锁定不想更新的包 ``` brew pin $FORMULA # 锁定某个包 brew unpin $FORMULA # 取消锁定 ```
16 | * 查看安装包的相关信息 ``` brew info $FORMULA # 显示某个包的信息
17 | brew info # 显示安装了包数量,文件数量,和总占用空间
18 | brew deps --installed --tree # 查看已安装的包的依赖,树形显示
19 | ```
20 | * 列出已安装包 ``` brew list ```
21 | * 搜索 ``` brew search ffmpeg ```
22 | * 删除 ``` brew rm $FORMULA # 删除某个包
23 | brew uninstall --force $FORMULA # 删除所有版本 ```
24 |
25 | brew tap --repair
26 |
27 | brew doctor
28 |
29 |
30 |
31 | ```
32 | Error: Another active Homebrew update process is already in progress.
33 | Please wait for it to finish or terminate it to continue.
34 | 1
35 | 2
36 | 解决方法:rm -rf /usr/local/var/homebrew/locks
37 | ```
38 |
39 | ```
40 | LibreSSL SSL_connect: SSL_ERROR_SYSCALL in connection to github.com:443
41 |
42 | sudo xcode-select --reset
43 |
44 | // git config --global http.proxy 127.0.0.1:9909
45 | // git config --global https.proxy 127.0.0.1:9909
46 | git config --global --unset http.proxy
47 | git config --global --unset https.proxy
48 | ```
49 |
50 | 升级Python3.x
51 |
52 | ```
53 | brew install python@3.9
54 |
55 | brew link python@3.9
56 |
57 | echo "alias python=/usr/local/bin/python3.9" >> ~/.zshrc
58 |
59 | source ~/.zshrc
60 | ```
61 |
62 |
63 | * [Mac下Homebrew的基本命令](https://zhuanlan.zhihu.com/p/90765541)
64 | * [2020-01-20 Homebrew换源和更新](https://www.jianshu.com/p/906e10bb6a21)
65 | * [Homebrew教程](https://www.knowledgedict.com/tutorial/homebrew-command-update.html)
66 | * [Homebrew总结](https://blog.csdn.net/tom_ke/article/details/79321210)
--------------------------------------------------------------------------------
/Files/IJKPlayer.md:
--------------------------------------------------------------------------------
1 | #### 进入桌面(也可用自己喜欢的目录)
2 |
3 | 1. 进入桌面 ``` cd ~/Desktop/ ```
4 | 2. 创建文件夹 ``` mkdir ijk ```
5 | 3. 进入ijk文件夹 ``` cd ijk/ ```
6 |
7 | #### 安装Homebrew(可能用到,按需执行,如果有则可以不执行某些命令)
8 |
9 | 1. 查看版本 ``` brew --version ```
10 | 2. 卸载brew ``` ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)" ```
11 | 3. 安装brew ``` ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" ```
12 | 4. 查看版本 ``` brew --version ```
13 | 5. 安装目录 ``` which brew ```
14 |
15 | #### 安装git(可能用到,按需执行,如果有则可以不执行某些命令)
16 |
17 | 1. 查看版本 ``` git --version ```
18 | 2. 安装git ``` brew install git ```
19 |
20 | #### 安装yasm(可能用到,按需执行,如果有则可以不执行某些命令)
21 |
22 | 1. 查看版本 ``` yasm --version ```
23 | 2. 安装yasm ``` brew install yasm ```
24 |
25 | #### 克隆项目与检出分支
26 |
27 | 1. github克隆 ``` git clone https://github.com/Bilibili/ijkplayer.git ijkplayer-ios ```
28 | 2. gitee克隆 ``` git clone https://gitee.com/mirrors/ijkplayer.git ijkplayer-ios ```
29 | 3. 进入ijkplayer-ios ``` cd ijkplayer-ios ```
30 | 4. 检出并命名分支 ``` git checkout -B latest k0.8.8 ```
31 |
32 | #### 准备活动,防止不必要问题
33 |
34 | config/module-lite-hevc.sh文件添加更多支持
35 |
36 | ```
37 | # OpenSSL
38 | export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-openssl"
39 | # RTSP
40 | export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=rtsp"
41 | # MJPEG
42 | export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=mjpeg"
43 | export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=mjpeg"
44 | # TCP
45 | export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-protocol=tcp"
46 | # SDP
47 | export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=sdp"
48 | # RTP
49 | export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-demuxer=rtp"
50 | # Nellymoser
51 | export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-decoder=nellymoser"
52 | # mp3_header_decompress
53 | export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-bsf=mp3_header_decompress"
54 | # mpeg4_unpack_bframes
55 | export COMMON_FF_CFG_FLAGS="$COMMON_FF_CFG_FLAGS --enable-bsf=mpeg4_unpack_bframes"
56 | ```
57 |
58 | ios/compile-ffmpeg.sh 和 ios/compile-openssl.h
59 |
60 | ```
61 | // 去掉armv7(32位)支持 如
62 | FF_ALL_ARCHS_IOS8_SDK="armv7 arm64 i386 x86_64"
63 | 改为
64 | FF_ALL_ARCHS_IOS8_SDK="arm64 i386 x86_64"
65 |
66 | "$FF_TARGET" = "armv7" -o "$FF_TARGET" = "armv7s" -o "$FF_TARGET"
67 | 改为
68 | "$FF_TARGET" = "armv7s" -o "$FF_TARGET" = "arm64"
69 |
70 | echo " compile-ffmpeg.sh armv7|arm64|i386|x86_64"
71 | 改为
72 | echo " compile-ffmpeg.sh arm64|i386|x86_64"
73 | ```
74 |
75 | 修改 xcode-select
76 |
77 | ```
78 | sudo /usr/bin/xcode-select -switch /Applications/Xcode.app/Contents/Developer
79 | ```
80 |
81 | 修改init-ios-openssl.sh
82 |
83 | ```
84 | 该更为镜像
85 | #IJK_OPENSSL_UPSTREAM=https://github.com/openssl/openssl
86 | IJK_OPENSSL_UPSTREAM=https://gitee.com/mirrors/openssl
87 |
88 | 去除armv7支持 pull_fork "armv7"
89 | ```
90 |
91 | 修改hosts文件
92 |
93 | ```
94 | sudo vim /etc/hosts
95 |
96 | 浏览器访问 www.ipaddress.com 和 http://tool.chinaz.com/dns
97 | 分别查找github.com 和 github.global.ssl.fastly.net 对应ip
98 |
99 | 写入hosts文件(wq退出并保存)
100 |
101 | 格式为: 199.232.5.194 github.global.ssl.fastly.net
102 |
103 | 刷新DNS缓存 sudo killall -HUP mDNSResponder
104 | 然后强制退出终端或者重启大法
105 | ```
106 |
107 | 去除armv7引入
108 |
109 | ```
110 | /build/universal/include/libavutil/avconfig.h:34
111 | 去掉行 include "armv7/avconfig.h"
112 |
113 | /build/universal/include/libffmpeg/config.h:34
114 | 去掉行 include "armv7/config.h"
115 | ```
116 |
117 | #### 选择支持的解码配置
118 |
119 | 1. 进入 config 目录,删除当前的 module.sh 文件
120 |
121 |
122 | ```
123 | rm module.sh
124 | ```
125 |
126 | 2. 创建软链接 module.sh 指向 module-lite-hevc.sh
127 |
128 | ```
129 | ln -s module-lite-hevc.sh module.sh
130 | ```
131 |
132 | #### 编译openssl和ffmpeg
133 |
134 | 1. 进入ios目录执行
135 |
136 | ```
137 | ./compile-openssl.sh clean
138 | ./compile-ffmpeg.sh clean
139 | ```
140 |
141 | 2. 进入ijkplayer-ios目录执行
142 |
143 | ```
144 | // 下载openssl
145 | ./init-ios-openssl.sh
146 |
147 | // 下载ffmpeg
148 | ./init-ios.sh
149 | ```
150 |
151 | 3. 进入ios目录执行
152 |
153 | ```
154 | // 编译openssl
155 | ./compile-openssl.sh all
156 |
157 | // 编译ffmpeg
158 | ./compile-ffmpeg.sh all
159 | // ./compile-ffmpeg.sh all x86_64 编译单个指令集
160 | ```
161 |
--------------------------------------------------------------------------------
/Files/IM.md:
--------------------------------------------------------------------------------
1 | > ### Instant Messaging
2 |
3 | * 去哪儿[星语QTalk](https://github.com/qunarcorp/qtalk)
4 | * [Startalk](https://github.com/startalkIM/Startalk)
5 | * [cim](https://github.com/crossoverJie/cim)
6 | * 野火IM[wildfirechat](https://github.com/wildfirechat)
7 | * 蘑菇街[TeamTalk](https://github.com/meili/TeamTalk)
8 | * 融云[rongcloud](https://github.com/rongcloud)
9 |
10 |
11 | > ### 文章
12 |
13 | * [移动IM开源框架对比](https://blog.csdn.net/mozartisme/article/details/79925842)
14 | * [蘑菇街的开源IM:TeamTalk](https://blog.csdn.net/tiny_lxf/article/details/80222446)
15 | * [开源项目索引](https://www.rongcloud.cn/docs/open_source.html)
--------------------------------------------------------------------------------
/Files/IPATransportation.md:
--------------------------------------------------------------------------------
1 | 目前上传ipa 包到 AppStore 有四种姿势
2 |
3 | * Organizer Upload
4 |
5 | ```
6 | 利用 Xcode -> Window -> Organizer 直接上传
7 | ```
8 |
9 | * Application loader(目前仍能用)
10 |
11 | ```
12 | 从旧版拷贝或网上下载Application loader 然后上传
13 | ```
14 |
15 | * xcrun altool
16 |
17 | ```
18 | 使用命令行工具 xcrun altool
19 |
20 | 官方文档
21 | https://help.apple.com/asc/appsaltool/#/apdATD1E53-D1E1A1303-D1E53A1126
22 | 其他文档
23 | https://testerhome.com/topics/10507
24 | https://www.jianshu.com/p/52a1b9a42afa
25 | ```
26 |
27 | * Transporter
28 |
29 | ```
30 | Mac AppStore下载 Transporter 进行上传
31 | ```
--------------------------------------------------------------------------------
/Files/IpaProcessingFailed.md:
--------------------------------------------------------------------------------
1 | ##### Xcode11后打包不允许i386和x86_64,否则报错 IPA processing failed。
2 |
3 | * i386:模拟器32位,iPhone 5s及以下
4 | * x86_64:模拟器64位, iPhone 6及以上
5 | * armv7:真机32位, iPhone 4及以下
6 | * armv7s:真机32位,iPhone 5, iPhone 5s
7 | * arm64:真机64位,iPhone 6及以上
8 |
9 |
10 | ##### 方案一:
11 |
12 | * 暂时使用Xcode 10打包
13 |
14 | ##### 方案二:
15 |
16 | * 去除不支持的架构。
17 |
18 | 1. 进入SDK内 ``` cd aa.framework ```
19 | 2. 查看支持的架构 ``` lipo -inof aa ```
20 | 3. 可能显示 Architectures in the fat file: aa are: i386 x86_64 armv7 arm64
21 | 4. 删除不支持的架构
22 |
23 | ```
24 | lipo -remove i386 aa -o aa
25 | lipo -remove x86_64 aa -o aa
26 | ```
27 | 5. 重新打包
28 |
29 |
--------------------------------------------------------------------------------
/Files/LineBreakMode.md:
--------------------------------------------------------------------------------
1 | NS_ENUM_AVAILABLE(10_0, 6_0);
2 |
3 | ```
4 | // NSParagraphStyle
5 | typedef NS_ENUM(NSInteger, NSLineBreakMode) {
6 | NSLineBreakByWordWrapping = 0, // Wrap at word boundaries, default
7 | NSLineBreakByCharWrapping, // Wrap at character boundaries
8 | NSLineBreakByClipping, // Simply clip
9 | NSLineBreakByTruncatingHead, // Truncate at head of line: "...wxyz"
10 | NSLineBreakByTruncatingTail, // Truncate at tail of line: "abcd..."
11 | NSLineBreakByTruncatingMiddle // Truncate middle of line: "ab...yz"
12 | } NS_ENUM_AVAILABLE(10_0, 6_0);
13 | ```
14 |
15 |
16 | NS_DEPRECATED_IOS(2_0,6_0) __TVOS_PROHIBITED; Deprecated: use NSLineBreakMode instead
17 |
18 | ```
19 | typedef NS_ENUM(NSInteger, UILineBreakMode) {
20 | UILineBreakModeWordWrap = 0, // Wrap at word boundaries
21 | UILineBreakModeCharacterWrap, // Wrap at character boundaries
22 | UILineBreakModeClip, // Simply clip when it hits the end of the rect
23 | UILineBreakModeHeadTruncation, // Truncate at head of line: "...wxyz". Will truncate multiline text on first line
24 | UILineBreakModeTailTruncation, // Truncate at tail of line: "abcd...". Will truncate multiline text on last line
25 | UILineBreakModeMiddleTruncation, // Truncate middle of line: "ab...yz". Will truncate multiline text in the middle
26 | } NS_DEPRECATED_IOS(2_0,6_0) __TVOS_PROHIBITED;
27 | ```
28 |
29 | 因为映射的枚举值一样所以即使 NS* 用了 UI* 也不会出错
30 |
31 | * NSLineBreakByWordWrapping;以单词为显示单位显示,后面部分省略不显示。
32 | * NSLineBreakByCharWrapping;以字符为显示单位显示,后面部分省略不显示。
33 | * NSLineBreakByClipping;剪切与文本宽度相同的内容长度,后半部分被删除。
34 | * NSLineBreakByTruncatingHead;前面部分文字以……方式省略,显示尾部文字内容。
35 | * NSLineBreakByTruncatingTail;结尾部分的内容以……方式省略,显示头的文字内容。
36 | * NSLineBreakByTruncatingMiddle;中间的内容以……方式省略,显示头尾的文字内容。
37 |
--------------------------------------------------------------------------------
/Files/Mac.md:
--------------------------------------------------------------------------------
1 | ##### Mac OSX 校验文件 MD5/SHA1
2 |
3 | ```
4 | # MD5
5 | md5 filePath
6 | # SHA1
7 | shasum filePath
8 | # SHA1
9 | shasum -a 1 filePath
10 | # SHA 256
11 | shasum -a 256 filePath
12 | ```
13 |
14 | ##### 终端 sqlite3
15 |
16 | ```
17 | // 创建或打开
18 | sqlite3 SongListCache.sqlite
19 |
20 | // 数据库文件所包含的所有自定义数据表
21 | .tables
22 |
23 | // 查看某个数据表所有内容
24 | select * from MusicListTable_1000;
25 |
26 | // https://www.cnblogs.com/Camier-myNiuer/p/5716826.html
27 | ```
28 |
29 | ##### 字符
30 |
31 | ```
32 | 半角空格(0×20)
33 | 制表符(t)
34 | 全角空格 (u3000)
35 | u0009 CHARACTER TABULATION u000A LINE FEED u000D CARRIAGE RETURN u0020 SPACE u0085 NEXT LINE u00A0 NBSP u1680 OGHAM SPACE MARK u180E MONGOLIAN VOWEL SEPARATOR u2000 EN QUAD u200A HAIR SPACE u200B ZERO WIDTH SPACE u2028 LINE SEPARATOR u2029 PARAGRAPH SEPARATOR u202F NARROW NO-BREAK SPACE u205F MEDIUM MATHEMATICAL SPACE u3000 IDEOGRAPHIC SPACE
36 | ```
37 | ##### 查看文件附加属性
38 |
39 | ```
40 | // 查看文件夹内所有文件附加属性
41 | ls -al@
42 |
43 | // 查看单个文件附加属性
44 | ls -l@ confuse.dmg
45 | xattr -l a.txt
46 |
47 | // 删除隔离属性 -r是递归,如果不需要递归可以去除
48 | sudo xattr -rd com.apple.quarantine /Applications/WebStrom.app
49 |
50 | xattr -rd com.apple.quarantine directoryname
51 |
52 | // 删除单个文件所有扩展属性
53 | xattr -c s.7z
54 | // 递归删除文件夹里所有文件所有扩展属性
55 | xattr -rc /path/to/directory
56 | ```
57 |
58 | ##### 文件已损坏解决
59 |
60 | ```
61 | // 允许任何来源
62 | sudo spctl --master-disable
63 |
64 | sudo xattr -d com.apple.quarantine /Applications/xxxx.app
65 | ```
66 |
67 | ##### 在Mac下使用crontab执行定时脚本
68 |
69 | [在Mac下使用crontab执行定时脚本](https://tool.4xseo.com/article/311355.html)
70 |
71 | ##### Jenkins 打包
72 |
73 | https://www.cnblogs.com/somepark/p/16813250.html
74 |
75 | ##### 在APP下载链接里查看
76 |
77 | ```
78 | https://itunes.apple.com/lookup?id=951937596.
79 | ```
80 | ##### 黑苹果
81 |
82 | https://apple.sqlsec.com/5-%E5%AE%9E%E6%88%98%E6%BC%94%E7%A4%BA/5-7.html
83 |
84 | ##### 消除更新红点
85 |
86 | ```
87 | defaults write com.apple.systempreferences AttentionPrefBundleIDs 0
88 |
89 | killall Dock
90 | ```
91 |
92 | ##### MAC 命令行工具获取手机信息
93 |
94 | ```
95 | brew install libimobiledevice
96 | brew install ideviceinstaller
97 | https://cloud.tencent.com/developer/article/1536056
98 | [使用libimobiledevice + ifuse提取iOS沙盒文件](https://cloud.tencent.com/developer/article/1521371)
99 | ```
100 |
101 | ##### 查看图片元数据
102 |
103 | ```
104 | [Exiftool 命令行操作图片元信息](https://blog.csdn.net/weixin_34393428/article/details/88679127)
105 | ```
106 |
107 | ##### 显示隐藏文件
108 |
109 | ```
110 | // 如果不想立刻重启Finder,去掉 ;killall Finder
111 | defaultswritecom.apple.finder AppleShowAllFiles-boolean true;killall Finder
112 |
113 | 也可以快捷键 Command + Shift + .
114 | Funter是Mac上的一款高级文件隐藏工具
115 | ```
116 |
117 | ##### 系统设置扩展没有Xcode
118 |
119 | ```
120 | PATH=/System/Library/Frameworks/CoreServices.framework/Frameworks/LaunchServices.framework/Support:"$PATH"
121 | lsregister -f /Applications/Xcode.app
122 | ```
123 | [修复Xcode Source Editor在masOS的扩展中不显示](https://www.sunyazhou.com/2020/10/XcodeSourceEditorNotWork/)
124 |
125 | https://www.jianshu.com/p/ff6308236a7c
--------------------------------------------------------------------------------
/Files/NSInvocation.md:
--------------------------------------------------------------------------------
1 | performSelector传参一般不能超过2个,但我们有时需要传递两个以上的参数,那就不能直接用performSelector了。这里提供了两种方案:
2 |
3 | 1.用NSInvocation代替performSelector
4 |
5 | 2.将参数进行封装,如:结构体、Class、字典等,然后定义一个传递单参的方法即可
6 |
7 |
8 | ```
9 | - (void)test {
10 | // 方法签名(方法的描述)
11 | NSMethodSignature *singture = [[self class] instanceMethodSignatureForSelector:@selector(test1:test2:test3:test4:)];
12 | // 包装方法
13 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:singture];
14 | // 设置方法调用者
15 | [invocation setTarget:self];
16 | // 设置需要调用的方法,必须和NSMethodSignature里面的SEL方法一样
17 | [invocation setSelector:@selector(test1:test2:test3:test4:)];
18 | NSString *test1 = @"invocation test";
19 | int test2 = 2;
20 | NSNumber *test3 = @12;
21 | NSArray *test4 = @[@"test1" ,@"test2" ,@"test3" ,@"test4"];
22 | // 0表示target, 1为_cmd, 所以保存从索引2幵始
23 | [invocation setArgument:&test1 atIndex:2];
24 | [invocation setArgument:&test2 atIndex:3];
25 | [invocation setArgument:&test3 atIndex:4];
26 | [invocation setArgument:&test4 atIndex:5];
27 | [invocation retainArguments];
28 | // retain所有参数,防止参数被释放dealloc
29 | [invocation invoke];
30 | }
31 |
32 | - (void)test1:(NSString *)test1 test2:(int)test2 test3:(NSNumber *)test3 test4:(NSArray *)test4 {
33 | NSLog(@"\n%@\n%d\n%@\n%@", test1, test2, test3, test4);
34 | }
35 | ```
36 |
37 |
38 | 有返回值情况
39 |
40 | ```
41 | - (void)test {
42 | // 方法签名(方法的描述)
43 | NSMethodSignature *singture = [[self class] instanceMethodSignatureForSelector:@selector(test1:test2:test3:test4:)];
44 | // 包装方法
45 | NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:singture];
46 | // 设置方法调用者
47 | [invocation setTarget:self];
48 | // 设置需要调用的方法,必须和NSMethodSignature里面的SEL方法一样
49 | [invocation setSelector:@selector(test1:test2:test3:test4:)];
50 | NSString *test1 = @"invocation test";
51 | int test2 = 2;
52 | NSNumber *test3 = @12;
53 | NSArray *test4 = @[@"test1" ,@"test2" ,@"test3" ,@"test4"];
54 | // 可以有返回参数 这里举例子为NSString类型返回值
55 | NSString *returnValue = @"我是原始值";
56 | // 0表示target, 1为_cmd, 所以保存从索引2幵始
57 | [invocation setArgument:&test1 atIndex:2];
58 | [invocation setArgument:&test2 atIndex:3];
59 | [invocation setArgument:&test3 atIndex:4];
60 | [invocation setArgument:&test4 atIndex:5];
61 | [invocation retainArguments];
62 | // retain所有参数,防止参数被释放dealloc
63 | [invocation invoke];
64 | [invocation getReturnValue:&returnValue];
65 | NSLog(@"%@", returnValue);
66 | }
67 |
68 | - (NSString *)test1:(NSString *)test1 test2:(int)test2 test3:(NSNumber *)test3 test4:(NSArray *)test4 {
69 | NSLog(@"\n%@\n%d\n%@\n%@", test1, test2, test3, test4);
70 | return @"我是返回值";
71 | }
72 | ```
73 |
74 |
--------------------------------------------------------------------------------
/Files/NSTimer.md:
--------------------------------------------------------------------------------
1 | # [NSTimer](https://developer.apple.com/documentation/foundation/nstimer?language=occ)
2 |
3 | https://juejin.im/post/5afaaf996fb9a07ac5604a92
4 |
5 | gcd定时 https://www.jianshu.com/p/58ec705ef362
--------------------------------------------------------------------------------
/Files/Network.md:
--------------------------------------------------------------------------------
1 | * [iOS计算网络测试中的丢包率,延迟,下载速度等参数、iOS实现ping](https://blog.csdn.net/yingms/article/details/46238407)
2 | * [SimplePing](https://developer.apple.com/library/mac/samplecode/SimplePing/Listings/SimplePing_m.html)
3 | * [STPingTest](https://github.com/lovesunstar/STPingTest)
4 | * [OC iOS-netdiag](https://github.com/qiniu/iOS-netdiag)
5 | * [Swift LPNetdiag](https://github.com/liam-i/LPNetdiag)
--------------------------------------------------------------------------------
/Files/Nil_nil_Null_NSNull.md:
--------------------------------------------------------------------------------
1 | > # nil
2 |
3 | nil -> Null-pointer to objective- c object
4 |
5 | nil 特对于表示Object-C的除Class类型外的对象为NULL,表示其对象指针不指向任何对象。NSArray末用nil来表示结束。
6 |
7 | > # Nil
8 |
9 | NIL -> Null-pointer to objective- c class
10 |
11 | NIL 特对于表示Object-C的Class类型对象为NULL,表示其对象指针不指向任何对象。
12 |
13 |
14 | > # Null
15 |
16 | NULL其实就是C\C++的用法,用来表示一个对象指针不指向任何对象,其值为0,
17 |
18 | > # NSNull
19 |
20 | NSNull是一个类,它只有一个方法:+ (NSNull *) null;
21 |
22 |
23 |
24 | * nil与Nil可以简单的理解为Object-C自己搞的对objective- c的NULL表示,用来表示一个对象指针不指向任何对象。但是当在对象指针为nil 或NIL的对象上调用方法或访问成员变量时,返回NO,不会抛异常,程序将继续执行下去。发给nil对象的消息返回值取决于其方法的返回类型。如果返回方法返回某个指针类型(例如对象指针),则返回值是nil.表示安全地将消息传递给了nil对象-nil仅起着传递作用。如果返回方法是返回类型长度和指针类型相等或更小的int话,返回值是零。如果返回值是浮点类型或结构体的话,将得到某个未定义的结果。
25 |
26 | * 当在对象指针为NULL的对象上调用方法或访问成员变量时,会抛异常
27 |
28 | * [NSNull null]用来在NSArray和NSDictionary中加入非nil(表示列表结束)的空值. [NSNull null]是一个对象,用来表示空,他用在不能使用nil的场合。
--------------------------------------------------------------------------------
/Files/OverTheAirInstallation.md:
--------------------------------------------------------------------------------
1 | > #### OTA(Over_The_Air Installation)内部测试版分发
2 |
3 | 有很多方式
4 |
5 | * www.pgyer.com(蒲公英,简单粗暴,需要认证)
6 | * www.fir.im (风起云飞,简单粗暴,需要认证)
7 | * TestFlight (苹果官方,麻烦还得下载TestFlight)
8 | * 自建分发
9 |
10 |
11 | > #### 用gitee建立分发功能
12 |
13 | 本来用github,但是gh pages刷新相对麻烦且可能存在无法访问,所以用了gitee。用哪个都一样,只要是https能访问下载plist的都可以(ipa可以不用https,甚至可以放本地体验超快下载安装)。
14 |
15 |
16 | * 登录gitee 创建工程,我这里命名idengyun (你想要的合法不重复的就行)
17 | * 上传57×57和512×512尺寸的Icon图,并获取实际原始地址(即下载地址)
18 | * 上传plist文件,内容见附加
19 | * 制定相应静态网页,用来触发下载
20 | * 开启gitee pages:服务-->gitee pages
21 |
22 | > #### 本地Apache
23 |
24 | * 开启本地服务器 ``` sudo apachectl start ```
25 | * 重启本地服务器 ``` sudo apachectl restart ```
26 | * 关闭本地服务器 ``` sudo apachectl stop ```
27 | * 测试是否已开启 ``` 127.0.0.1 ``` 或者 ``` localhost ``` 或 局域网的ip
28 | * 访达前往 Command+Shift+G ``` /Library/WebServer/Documents ```
29 | * 复制粘贴命名ipa包 ``` local360.ipa ```
30 |
31 |
32 | > #### 附加
33 |
34 | * 每次更新ipa后要重启本地服务器
35 | * ip地址可通过系统偏好设置中网络查看
36 | * 如果更新了git工程文件要在gitee工程pages页更新部署
37 |
38 |
39 | * index.html
40 |
41 | ```
42 |
43 |
44 |
45 | 妃子校
46 |
47 |
48 |
49 |
50 |
51 |
59 |
60 |
88 |
89 |
90 |
91 |
92 |
妃子校
93 |
94 |
95 | 注意: 请用浏览器打开链接
96 |
97 |
98 |
99 |
100 |
101 |
102 |
103 |
104 |
105 |
106 |
107 |
108 | ```
109 |
110 | * 360.plist内容(名字任意和下载中一致合法即可)
111 |
112 | ```
113 |
114 |
115 |
116 |
117 | items
118 |
119 |
120 | assets
121 |
122 |
123 | kind
124 | software-package
125 | url
126 | http://172.50.3.209/360.ipa
127 |
128 |
129 | kind
130 | display-image
131 | url
132 | https://gitee.com/starainDou/idengyun/raw/master/icon/icon1.png
133 |
134 |
135 | kind
136 | full-size-image
137 | url
138 | https://gitee.com/starainDou/idengyun/raw/master/icon/icon2.png
139 |
140 |
141 | metadata
142 |
143 | bundle-identifier
144 | com.kenuo.training
145 | bundle-version
146 | 3.5.0
147 | kind
148 | software
149 | platform-identifier
150 | com.apple.platform.iphoneos
151 | title
152 | 妃子校
153 |
154 |
155 |
156 |
157 |
158 | ```
159 |
160 | [Java读取apk、ipa包名、版本名、版本号、图标等信息](https://www.cnblogs.com/wjp1122/p/8984163.html)
161 |
--------------------------------------------------------------------------------
/Files/Project.md:
--------------------------------------------------------------------------------
1 | > #### 工程初始化配置
2 |
3 | 1. 在指定目录下建立 cocosProject 和 cocos_build 文件夹,以Desktop路径为例
4 |
5 | ```
6 | cd ~/Desktop
7 |
8 | mkdir cocosProject
9 |
10 | mkdir cocos_build
11 |
12 | cd ~/Desktop/cocos_build
13 |
14 | mkdir market
15 | ```
16 |
17 | 2. 进入 cocosProject 目录,拉取 cocos 代码(若无访问权限则需让管理员添加)
18 |
19 | ```
20 | cd ~/Desktop/cocosProject
21 |
22 | git clone https://gitlab.huixuanjiasu.com/hongbaogame/market.git
23 |
24 | cd ~/Desktop/cocosProject/market
25 |
26 | git checkout ios-test
27 | ```
28 |
29 | 3. 安装 CocosCreator 并用其打开 market 工程
30 |
31 | ```
32 | open -a CocosCreator
33 |
34 | CocosCreator 菜单栏 打开其他项目 选择 ~/Desktop/cocosProject/market 目录
35 | ```
36 |
37 | 4. 导出 CocosCreator 工程为原生工程
38 |
39 | ```
40 | 菜单栏 - 项目 - 构建发布
41 | ```
42 |
43 | 5. 填写导出配置信息
44 |
45 | ```
46 | 游戏名称 market
47 | 发布平台 iOS
48 | 发布路径 ~/Desktop/cocos_build/market
49 | 包名 com.kdsjge.imarket
50 | ```
51 | 6. 删除导出工程 jsb-link/frameworks/runtime-src/proj.ios_mac 文件夹
52 |
53 | ```
54 | rm -rf ~/Desktop/cocos_build/market/jsb-link/frameworks/runtime-src/proj.ios_mac/
55 | ```
56 |
57 | 7. 进入 runtime-src 并克隆原生壳工程命名为 proj.ios_mac,并检出分支
58 |
59 | ```
60 | cd ~/Desktop/cocos_build/market/jsb-link/frameworks/runtime-src/
61 |
62 | git clone https://gitlab.huixuanjiasu.com/hongbaogame/iossdk.git proj.ios_mac
63 |
64 | cd ~/Desktop/cocos_build/market/jsb-link/frameworks/runtime-src/proj.ios_mac/
65 |
66 | git checkout feature-market
67 | ```
68 |
69 | 8. 安装 pod 库 (如果本地版本低则需要先 pod repo update)
70 |
71 | ```
72 | cd ~/Desktop/cocos_build/market/jsb-link/frameworks/runtime-src/proj.ios_mac/
73 |
74 | pod install
75 | ```
76 |
77 | [cocoaPods安装](https://github.com/starainDou/DDYKnowledge/blob/master/Files/CocoaPods.md)
78 |
79 | 9. 安装 node,安装 Python3 环境并执行热更命令
80 |
81 | ```
82 | brew install node
83 |
84 | cd ~/Desktop/cocosProject/market
85 |
86 | 修改 updateCfg.template 为 updateCfg.yaml
87 |
88 | mv updateCfg.template updateCfg.yaml
89 |
90 | open -e updateCfg.yaml
91 |
92 | 并修改其内容 source_folder: "/Users/chuangaofeng/Desktop/cocos_build/market/jsb-link/" # 这里用绝对路径
93 |
94 | python3 hotupdate.py -n -i 1.1.0.6
95 | ```
96 |
97 | 如果报错
98 |
99 | ```
100 | ModuleNotFoundError: No module named 'yaml'
101 | sudo python3 -m pip install pyyaml
102 |
103 | ModuleNotFoundError: No module named 'click'
104 | sudo python3 -m pip install click
105 | ```
106 |
107 | ```
108 | [Client] Synchronous remote object proxy returned error: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service named com.apple.commcenter.coretelephony.xpc was invalidated.}
109 |
110 | 终端运行
111 |
112 | xcrun simctl spawn booted log config --mode "level:off" --subsystem com.apple.CoreTelephony
113 |
114 | //https://www.codenong.com/52127186/
115 |
116 | [Client] Updating selectors failed with: Error Domain=NSCocoaErrorDomain Code=4099 "The connection to service on pid 0 named com.apple.commcenter.coretelephony.xpc was invalidated." UserInfo={NSDebugDescription=The connection to service on pid 0 named com
117 |
118 | 这个错误时,说明是你开启了全局代理,而去访问局域网资源。
119 | ```
120 |
121 |
122 | > #### 添加空framework以支持模拟器
123 |
124 | ```
125 | 以 du.framework为例
126 |
127 | 打开Xcode shift + command + N 新建 Framework,命名为du
128 |
129 | 创建framework中所有同名文件.h,如若需要还有.m,将所有方法进行空实现或返回特定值
130 |
131 | 设置Build Setting参数将Build Active Architecture only设置为NO
132 |
133 | Mach-o type 修改为Static Libray
134 |
135 | 在Build Settings下配置,删除arm64架构 Excluded Architecture arm64
136 |
137 | 设置Headers,将要公开的头文件拖到Public下
138 |
139 | Target 点击下面加号 other Aggregate,名字为du_script
140 |
141 | 点击 du_script Target,选择加号,New Run Script Phase
142 |
143 | 内容为
144 |
145 | # Type a script or drag a script file from your workspace to insert its path.
146 |
147 | UNIVERSAL_OUTPUTFOLDER=../Framework/
148 |
149 | # 创建输出目录,并删除之前的framework文件
150 |
151 | mkdir -p "${UNIVERSAL_OUTPUTFOLDER}"
152 |
153 | rm -rf "${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework"
154 |
155 | # 分别编译模拟器和真机的Framework
156 |
157 | # xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
158 |
159 | xcodebuild -target "${PROJECT_NAME}" ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphonesimulator BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" clean build
160 |
161 | # 定义真机、模拟器Build文件夹路径变量
162 |
163 | # IPHONE_BUILD=${BUILD_DIR}/${CONFIGURATION}-iphoneos/${PROJECT_NAME}.framework
164 |
165 | SIMULATOR_BUILD=${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/${PROJECT_NAME}.framework
166 |
167 | # 拷贝framework到univer目录
168 |
169 | # cp -R "${IPHONE_BUILD}" "${UNIVERSAL_OUTPUTFOLDER}/"
170 |
171 | cp -R "${SIMULATOR_BUILD}" "${UNIVERSAL_OUTPUTFOLDER}/"
172 |
173 | # 定义输出路径变量
174 |
175 | OUTPUT_PATH=${UNIVERSAL_OUTPUTFOLDER}/${PROJECT_NAME}.framework
176 |
177 | # 合并framework,输出最终的framework到build目录
178 |
179 | # lipo -create "${IPHONE_BUILD}/${PROJECT_NAME}" "${SIMULATOR_BUILD}/${PROJECT_NAME}" -output "${OUTPUT_PATH}/${PROJECT_NAME}"
180 | lipo -create "${SIMULATOR_BUILD}/${PROJECT_NAME}" -output "${OUTPUT_PATH}/${PROJECT_NAME}"
181 |
182 | 运行选择 du_script
183 |
184 | xcodebuild -create-xcframework \
185 | -framework "刚才的空framework路径" \
186 | -framework "实际只真机的du.framework路径" \
187 | -output "~/Desktop/du.xcframework"
188 |
189 | xcodebuild -create-xcframework \
190 | -framework "/Users/chuangaofeng/Desktop/duEmptySDKSimulator/iphoneOS/du.framework" \
191 | -framework "/Users/chuangaofeng/Desktop/duEmptySDKSimulator/simulator/du.framework" \
192 | -output "/Users/chuangaofeng/Desktop/duEmptySDKSimulator/merge/du.xcframework"
193 |
194 | 用 du.xcframework 替换掉 du.framework
195 |
196 | // https://www.jianshu.com/p/5c54b6e18f1f
197 | // https://www.jianshu.com/p/448529b53bf9
198 | // https://www.codenong.com/js20a92f83f968/
199 | // [xcframework生成与使用](https://www.jianshu.com/p/a4e7c65d0f45)
200 | [iOS_SDK开发之Framework打包](https://juejin.cn/post/6844904166012239886)
201 | https://www.jianshu.com/p/541553f8bce1
202 | ```
203 |
204 | 区分静态库和动态库
205 |
206 | ```
207 | cd .../Bugly.framework
208 | file Bugly
209 |
210 | current ar archive random library : 表示为静态库
211 | Mach-O dynamically linked shared library: 表示为动态库
212 | ```
213 |
214 | [Framework概念](https://www.jianshu.com/p/51a3279c75cb)
215 |
216 |
217 | 区分模拟器
218 |
219 | ```
220 | #if targetEnvironment(simulator)
221 | // 在模拟器的情况下
222 | #else
223 | // 在真机情况下
224 | #endif
225 |
226 | #if (TARGET_IPHONE_SIMULATOR)
227 | // 在模拟器的情况下
228 | #else
229 | // 在真机情况下
230 | #endif
231 | ```
232 |
233 | [Cocos Creator游戏集成到原生iOS及JS和OC交互](https://www.jianshu.com/p/4382c37f5ec4)
234 |
235 |
236 | https://easeapi.com/blog/blog/126-podspec-configurations.html
237 |
238 |
239 | 如果打开提示->XXX.app 已损坏,打不开。您应该将它移到废纸篓 ” 或 “ 打不开 XXX.app,因为它来自身份不明的开发者
240 |
241 | 打开终端(Terminal.app)
242 | 拷贝粘贴 sudo spctl --master-disable,按回车键
243 | 输入你的账户密码,按回车键确认执行(该密码不会显示,直接输入即可)
244 |
245 | 在系统的“安全与隐私”中允许“任何来源”,再打开终端
246 | 输入以下命令,回车(注意路径根据自己的实际情况替换) sudo xattr -d com.apple.quarantine /Applications/ALL_RoundU.app
247 | 重启App即可.
248 |
249 |
250 | https://book.flutterchina.club/
251 | https://github.com/flutter/samples
252 | https://github.com/iampawan/FlutterExampleApps
253 |
254 | https://gitee.com/chenxiancai/STCObfuscator
255 |
256 | [iOS App多环境配置Configuration](https://www.jianshu.com/p/a578555cf339)
257 | [为什么在 Xcode 12.3 及之后版本中使用 iOS 模拟器构建项目会失败](https://docs.agora.io/cn/All/faq/ios_simulator_problem)
258 |
259 |
260 | [添加iOS文件链接,操作.xcodeproj](https://www.jianshu.com/p/e1b8c58cabe2)
261 | [使用代码为 Xcode 工程添加文件](https://blog.csdn.net/sun1018974080/article/details/107641744)
262 | [Xcode工程文件的格式说明](https://www.jianshu.com/p/bd4e3c1a7276)
263 | [iOS自动打包之xcodeproj(二)](https://www.jianshu.com/p/6a7d0a6d9656)
264 | [ruby库xcodeproj使用心得](https://blog.csdn.net/darya_1/article/details/78095821)
265 | [iOS 使用脚本自动化复制target](https://zhuanlan.zhihu.com/p/31514291)
266 |
267 |
268 | http://docs.cocos.com/creator/manual/zh/advanced-topics/oc-reflection.html
269 | [iOS 分类中同名方法的调用顺序](https://www.jianshu.com/p/3907eed7f9f3)
--------------------------------------------------------------------------------
/Files/ProjectNotice.md:
--------------------------------------------------------------------------------
1 | 瞎扯下工程设计注意点,如果你正好和我一样在一个小公司,独自搭建一个0-1的工程...
2 |
3 | > ### 国际化(应用内、跟随系统)
4 |
5 | 你永远不知道你的工程未来是否支持多语言,所以不妨在工程初期就考虑下国际化的事情,哪怕只配置中文,然后加载,而不是直接写死。。。如果某一天产品说,咱们要支持中英切换,恭喜你,你只需要将英文的转换成相关配置文件,然后加个切换语言工具,就可以早早下班了!!!
6 |
7 | > ### 主体(主题色和皮肤)
8 |
9 | 可能某天产品心血来潮,咱们也支持主题切换吧。。。于是你可能Google+Baidu去找各种无侵入方案,,,早知如此何必当初。。。你既然成为0-1的开拓者,为啥不提前预知下未来,把切换主题的方案提前放进去,,,可以只默认一种主题,,,但当某天需要支持多种,哪怕网络下发,你只需要改几行代码,然后又能提前下班了。。。
10 |
11 | > ### 三方分享与登录
12 |
13 | 前期可能你的App很小众,那么除了常规登录还可能有三方登录,国内微信,QQ,微博...国外FaceBook,Instagram,Google...有了三方登录我就不信不加三方分享,然后你提前都设置好了,只等一声令下拿到相关key加进去了。
14 |
15 | 难道你不想你的App有一天也发展壮大,给别人提供登录和分享功能???那就开干吧,让别人也支持用你的app去登录或者分享内容到你App...
16 |
17 | > ### 网络
18 |
19 |
20 |
21 | > ### 解压缩
22 |
23 |
24 | > ### IM
25 |
26 | > ### 数据库
27 |
28 | > ### 埋点与统计
29 |
30 | > ### 热更新
31 |
32 | > ### Js交互
33 |
34 | > ### 刷新控件
35 |
36 | > ### 空白页占位
37 |
38 | >
39 |
40 | >
41 |
42 | >
--------------------------------------------------------------------------------
/Files/RAM.md:
--------------------------------------------------------------------------------
1 | > #### 存储器
2 |
3 | 存储器是计算机系统中的记忆设备,用来存储程序或数据,存储器有很多分类方式。
4 |
5 | * 按存储介质分类
6 |
7 | 作为存储介质的基本要求,必须具备能够区分两个明显不同的物理状态用来表示二进制0和1的特性。常见存储介质有半导体存储器和磁表面存储器(磁盘磁带)
8 |
9 | * 按存取方式分类
10 |
11 | * 随机存储器(存储单元随机存取,且存取时间和存储物理单元无关)
12 | * 顺序存储器(存储单元顺序存取,且存取时间和存储物理单元有关,存取周期较长,如磁带)
13 | * 半顺序存储器(磁盘)
14 |
15 | * 按读写功能分类
16 |
17 | * RAM(Random Access Memory): 随机存取存储器(通常指运行内存,CPU可直接访问,一般不能掉电存储。如果再细分可分为DRAM和SRAM)
18 | * DRAM:动态随机存取存储器,速度相对慢一点,需定期的刷新(充电),价格会稍低一点(电脑内存条,手机运行内存)
19 | * SRAM:静态随机存取存储器,速度相对更快,价格更高(一级缓存,二级缓存,CPU高速缓存)
20 | * ROM(Read Only Memory):只读存储器,存储速度相对RAM较低,但断电后信息不丢失(如BIOS芯片),进一步发展出现可编程只读存储器(PROM)、可擦可编程序只读存储器(EPROM)和电可擦可编程只读存储器(EEPROM)等。笼统意义上SD卡,Flash闪存(固态硬盘SSD的大部分,NandFlash),磁盘(机械硬盘HDD)属于ROM
21 |
22 |
23 | 由于RAM不能掉电存储,所以我们的APP程序,刷机包,下载的文件等等,都是在ROM里面存储的。
24 |
25 | 手机里面使用的ROM基本都是NandFlash,CPU是不能直接访问的,而是需要文件系统/驱动程序(嵌入式中的EMC)将其读到RAM里面,CPU才可以访问。另外,RAM的速度也比NandFlash快。
26 |
27 | > #### iOS内存分区
28 |
29 | 内存分区并不是指物理内存分了五个区(这里指iOS,安卓和iOS不同),而是系统分配给运行程序的内存(分配内存,虚拟内存)分五个区
30 |
31 | * 栈区(stack): 一般由编译器操作(系统管理),会存一些局部变量,函数跳转跳转时现场保护(寄存器值保存于恢复),这些系统都会帮我们自动实现,无需我们干预。 所以大量的局部变量,深递归,函数循环调用都可能耗尽栈内存而造成程序崩溃
32 | * 堆区(heap): 一般由程序员管理,我们创建的对象一般放在这里
33 | * 全局区(静态区 static):全局变量和静态变量的存储是放在一块的,初始化的全局变量和静态变量在一块区域, 未初始化的全局变量和未初始化的静态变量在相邻的另一块区域。程序结束后由系统释放。注意:在嵌入式系统中全局区又可分为未初始化全局区(bss段)和初始化全局区(data段)。举例:int a;未初始化的。int a = 10;已初始化的。
34 | * 常量区:常量字符串就是放在这里的,还有const常量
35 | * 代码区:存放执行代码,app程序会拷贝到这里
36 |
37 |
--------------------------------------------------------------------------------
/Files/Reverse.md:
--------------------------------------------------------------------------------
1 | ### 工程逆向
2 |
3 |
4 |
--------------------------------------------------------------------------------
/Files/SIP.md:
--------------------------------------------------------------------------------
1 | # 简介
2 |
3 | 现在在MAC OS X 系统中有一个跟安全相关的模式叫 SIP(System Integrity Protection),它禁止让软件以 root 身份来在 mac 上运行,并且对于目录 /System 、/sbin、/usr(不包含/usr/local/) 仅仅供系统使用,其它用户或者程序无法直接使用,例如 安装cocoaPods时如果直接安装 /usr 目录可能出问题。
4 |
5 | # 禁止SIP方式
6 |
7 | 1. 重启系统,按住 Command + R 进入恢复模式;
8 | 2. 点击顶部菜单栏 实用工具 中的 终端;
9 | 3. 输入 ```csrutil disable``` 来禁用 SIP 保护机制;
10 | 4. 重启系统
11 | 5. 如果想重新开启按上述步骤,然后执行 ```csrutil enable```
12 |
13 | # App已损坏,无法打开
14 |
15 | ```
16 | sudo xattr -rd com.apple.quarantine /Applications/MyApp.app
17 | ```
--------------------------------------------------------------------------------
/Files/SKAdNetwork.md:
--------------------------------------------------------------------------------
1 | 
2 |
3 | 
4 |
5 |
6 | 目前 SKAdNetwork2.2 支持浏览式广告曝光归因(View-Through Ads)和渲染型广告(StoreKit-Rendered Ads,App Store渲染式广告,可以理解为需要点击跳转App Store 网页页面或者客户端应用落地页的广告)
7 |
8 | StoreKit-Rendered Ads ,主要的归因方式链路式归因,苹果IOS 系统取消IDFA之后,应用的归因由系统提供追踪ID(签名)来实现
9 |
10 | 第一步,进行广告应用的签名,广告平台(Ad Network)在收到媒体端的广告请求时为广告应用进行签名(可以理解为生成一个广告的追踪ID)。
11 |
12 | 第二步,在广告即将曝光前,调用系统的 ``` loadProduct(withParameters:completionBlock:)``` 函数,目的在于预加载一个App Store的web端或者客户端的广告展示落地页。这样可以提升广告展示的速度,同时,将广告的应用相关签名信息和广告网络ID(Ad network ID)等信息传给App Store。
13 |
14 | 第三步,当用户点击广告时,会调起App Store 客户端广告应用的页面或者web 端页面,同时进行签名和广告网络ID信息的透传;
15 |
16 |
17 | 第四步,广告主发送激活通知,当广告主App安装后进行激活时,需要调用系统的函数,发起应用安装验证通知,调用方法 ```registerAppForAdNetworkAttribution() ```或 ``` updateConversionValue(_:) ```。目的是将广告的安装、激活以及转化信息回传给到广告平台。此时默认会启动一个24小时的计时器(Start timer)。超出时间再调用安装验证通知就会无效。当然,广告主可以通过调用updateConversionValue(_:)更新转化的值以及重启一个计时器。
18 |
19 | 第五步,广告平台接收激活和转化信息;当用户安装并启动一个属于广告的应用程序App时,广告主会调用```registerAppForAdNetworkAttribution()```或```updateConversionValue (_:)```。这些调用会将激活和转化信息发送到广告平台注册的回包网址(Postback URL),广告平台收到激活和转化通知后对信息进行确认,以此来完成一次的广告生命周期。
20 |
21 | 从上面的链路流程我们可以看到,这个归因完全不依赖于系统的隐私用户ID。核心关键在于系统提供了Storekit 和对应的API使得广告签名信息可以从广告的曝光一直传递到广告的激活和转化。
22 |
23 |
24 | 这个链路归因的方案涉及到各方的职责如下:
25 |
26 |
27 | 一、广告平台或者广告网络(Ad Network)的职责
28 |
29 | 在Apple 上注册Network ID,用于在广告活动时使用归因验证的各种API。
30 |
31 | 为流量媒体侧App(Source App)提供已签名的广告应用;
32 |
33 | 通过注册的回包网址(Postback URL)接收来自广告主回传的激活和转化信息;
34 |
35 | 确认已接收广告主回传的信息;
36 |
37 |
38 |
39 | 二、媒体APP(Source App)
40 |
41 | 需要在媒体应用的Info.plist 上添加广告网络的ID;
42 |
43 | 展示已签名的广告;
44 |
45 |
46 |
47 | 三、广告主应用(Advertised App)的职责:
48 |
49 | 在应用安装激活后,调用系统的API ```registerAppForAdNetworkAttribution()``` or ```updateConversionValue(_:)```发送激活归因信息;
50 |
51 | 调用```updateConversionValue(_:)```,更新应用后端转化的值,这是一个可选项,广告主根据实际情况决定是否使用;
52 |
53 | 苹果对于应用归因提供了StoreKit-Rendered Ads——基于App Store渲染的广告归因以及View-Through Ads(曝光广告归因)的能力
54 |
55 | ```
56 | - (void)loadProductWithParameters:(NSDictionary *)parameters
57 | completionBlock:(void (^)(BOOL result, NSError *error))block;
58 |
59 | 该方法用来达到从广告展示页面跳转到苹果商店的功能。在之前已经广泛被使用。在此次更新之前,主要传递parameters包含SKStoreProductParameterITunesItemIdentifier,广告应用的商店ID。
60 | 在此次更新后,需要传递的parameters内容增多了。具体如下:
61 |
62 | SKStoreProductParameterAdNetworkVersion -- 版本号,最终会归因后透传给AdNetwork
63 | SKStoreProductParameterAdNetworkIdentifier--AdNetwork在苹果处的识别ID
64 | SKStoreProductParameterAdNetworkCampaignIdentifier-- 广告Campaign id,只能填1到100
65 | )
66 | SKStoreProductParameterITunesItemIdentifier-- 广告主应用的苹果商店ID
67 | SKStoreProductParameterAdNetworkNonce -- 该impression在AdNetwork处的唯一ID,可用来校验真伪
68 | SKStoreProductParameterAdNetworkSourceAppStoreIdentifier -- Publisher应用的苹果商店ID
69 | SKStoreProductParameterAdNetworkTimestamp -- 展示广告的时间戳
70 | SKStoreProductParameterAdNetworkAttributionSignature -- 签名,供给苹果和AdNetwork用来校验真伪
71 | ```
72 |
73 |
74 | * [IOS广告归因](https://www.appganhuo.com/4235273222/)
75 | * [申请过AdNetwork ID](https://developer.apple.com/documentation/storekit/skadnetwork/registering_an_ad_network?language=objc)
76 | * [SkAdNetwork———归因路径从此串联了起来?](https://news.16p.com/892684.html)
77 | * [SKAN - 更新转化值 conversion value](https://zhuanlan.zhihu.com/p/452147151)
78 | * [iOS 14 AdNetwork归因流程](https://www.jianshu.com/p/fc42a3b7c695)
--------------------------------------------------------------------------------
/Files/SafeMainAsync.md:
--------------------------------------------------------------------------------
1 | 很多时候需要返回主线程执行操作,此时最简单粗暴的方式就是直接
2 |
3 | ```
4 | // OC
5 | dispatch_async(dispatch_get_main_queue(), ^{
6 | // code
7 | });
8 | // Swift
9 | DispatchQueue.main.async {
10 | // code
11 | }
12 | ```
13 |
14 | 但是这样并不友好,比如当前如果已经时主线程,所以就有了safe的形式
15 |
16 | ```
17 | // OC 早期SDWebImage
18 | #define dispatch_main_sync_safe(block)
19 | if ([NSThread isMainThread]) {
20 | block();
21 | } else {
22 | dispatch_sync(dispatch_get_main_queue(), block);
23 | }
24 | #define dispatch_main_async_safe(block)
25 | if ([NSThread isMainThread]) {
26 | block();
27 | } else {
28 | dispatch_async(dispatch_get_main_queue(), block);
29 | }
30 |
31 | // Swift 早期Kingfisher
32 | extension DispatchQueue {
33 | func safeAsync(_ block: @escaping ()->()) {
34 | if self === DispatchQueue.main && Thread.isMainThread {
35 | block()
36 | } else {
37 | async { block() }
38 | }
39 | }
40 | }
41 | ```
42 |
43 | 后来有人遇到主线程非主队列[issue](http://blog.benjamin-encz.de/post/main-queue-vs-main-thread/)
44 |
45 | 所以后来SDWebImage中更改了判断方式
46 |
47 | ```
48 | // OC SDWebImage
49 | #ifndef dispatch_main_async_safe
50 | #define dispatch_main_async_safe(block)
51 | if (dispatch_queue_get_label(DISPATCH_CURRENT_QUEUE_LABEL) == dispatch_queue_get_label(dispatch_get_main_queue())) {
52 | block();
53 | } else {
54 | dispatch_async(dispatch_get_main_queue(), block);
55 | }
56 | #endif
57 | ```
58 |
59 |
60 | Kingfisher中貌似没改
61 |
62 | 理应这个样子
63 |
64 | ```
65 | // Swift 自己瞎写的,认真你就输了
66 | import Foundation
67 |
68 | extension DispatchQueue {
69 |
70 | fileprivate static var currentQueueLabel: String? {
71 | let cString = __dispatch_queue_get_label(nil)
72 | return String(cString: cString)
73 | }
74 |
75 | fileprivate static var isMainQueue: Bool {
76 | return currentQueueLabel == self.main.label
77 | }
78 | }
79 |
80 | func ddyMainAsyncSafe(_ execute: @escaping () -> Void) {
81 | DispatchQueue.isMainQueue ? execute() : DispatchQueue.main.async(execute: execute)
82 | }
83 | ```
84 |
85 | 附加一个RxSwift中的判断方式
86 |
87 | ```
88 | extension DispatchQueue {
89 | private static var token: DispatchSpecificKey<()> = {
90 | let key = DispatchSpecificKey<()>()
91 | DispatchQueue.main.setSpecific(key: key, value: ())
92 | return key
93 | }()
94 |
95 | static var isMain: Bool {
96 | return DispatchQueue.getSpecific(key: token) != nil
97 | }
98 | }
99 | ```
100 |
--------------------------------------------------------------------------------
/Files/Singleton.md:
--------------------------------------------------------------------------------
1 | 单例模式:一个类只有一个实例对象
2 | 使用场合:在整个应用程序共享一份资源
3 |
4 | * 写法一:GCD的一次函数(dispatch_once_t)
5 |
6 | ARC
7 | ```
8 | #pragma mark - 单例对象
9 |
10 | static DDYDebugTool *_instance;
11 |
12 | + (instancetype)sharedManager {
13 | return [[self alloc] init];
14 | }
15 |
16 | + (instancetype)allocWithZone:(struct _NSZone *)zone {
17 | static dispatch_once_t onceToken;
18 | dispatch_once(&onceToken, ^{
19 | _instance = [super allocWithZone:zone];
20 | });
21 | return _instance;
22 | }
23 |
24 | - (id)copyWithZone:(NSZone *)zone {
25 | return _instance;
26 | }
27 |
28 | - (id)mutableCopyWithZone:(NSZone *)zone {
29 | return _instance;
30 | }
31 | ```
32 |
33 | MRC 添加下面三个方法
34 | ```
35 | - (oneway void)release {
36 | }
37 | - (instancetype)retain {
38 | return _instance;
39 | }
40 | - (NSUInteger)retainCount {
41 | return MAXFLOAT;
42 | }
43 | ```
44 |
45 | [一劳永逸宏定义](https://www.jianshu.com/p/4867dc92337e)
46 | ```
47 | #define singleH(name) +(instancetype)share##name;
48 |
49 | #if __has_feature(objc_arc)
50 |
51 | #define singleM(name) static id _instance;\
52 | +(instancetype)allocWithZone:(struct _NSZone *)zone\
53 | {\
54 | static dispatch_once_t onceToken;\
55 | dispatch_once(&onceToken, ^{\
56 | _instance = [super allocWithZone:zone];\
57 | });\
58 | return _instance;\
59 | }\
60 | \
61 | +(instancetype)share##name\
62 | {\
63 | return [[self alloc]init];\
64 | }\
65 | -(id)copyWithZone:(NSZone *)zone\
66 | {\
67 | return _instance;\
68 | }\
69 | \
70 | -(id)mutableCopyWithZone:(NSZone *)zone\
71 | {\
72 | return _instance;\
73 | }
74 | #else
75 | #define singleM static id _instance;\
76 | +(instancetype)allocWithZone:(struct _NSZone *)zone\
77 | {\
78 | static dispatch_once_t onceToken;\
79 | dispatch_once(&onceToken, ^{\
80 | _instance = [super allocWithZone:zone];\
81 | });\
82 | return _instance;\
83 | }\
84 | \
85 | +(instancetype)shareTools\
86 | {\
87 | return [[self alloc]init];\
88 | }\
89 | -(id)copyWithZone:(NSZone *)zone\
90 | {\
91 | return _instance;\
92 | }\
93 | -(id)mutableCopyWithZone:(NSZone *)zone\
94 | {\
95 | return _instance;\
96 | }\
97 | -(oneway void)release\
98 | {\
99 | }\
100 | \
101 | -(instancetype)retain\
102 | {\
103 | return _instance;\
104 | }\
105 | \
106 | -(NSUInteger)retainCount\
107 | {\
108 | return MAXFLOAT;\
109 | }
110 | #endif
111 | ```
112 |
113 |
114 | * 写法二:线程锁+懒加载
115 |
116 | ```
117 | static DDYDebugTool *_instance;
118 | + (instancetype)allocWithZone:(struct _NSZone *)zone {
119 | //线程锁
120 | @synchronized (self) {
121 | if (_instance == nil) {
122 | _instance = [super allocWithZone:zone];
123 | }
124 | }
125 | return _instance;
126 | }
127 |
128 | + (instancetype)sharedManager {
129 | return [[self alloc] init];
130 | }
131 | ```
132 |
133 | * 写法三:直接懒加载(超级不安全,不推荐)
134 |
--------------------------------------------------------------------------------
/Files/SiriKit.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/Files/SiriKit.md
--------------------------------------------------------------------------------
/Files/Sox.md:
--------------------------------------------------------------------------------
1 | [Sox特性](http://sox.sourceforge.net/Docs/Features)
2 |
3 | * Tone/filter effects 音色/滤波
4 |
5 | ```
6 | 全通(allpass): RBJ all-pass biquad IIR filter
7 | 带通(bandpass): RBJ band-pass biquad IIR filter
8 | 带阻(bandreject): RBJ band-reject biquad IIR filter
9 | 通带(band): SPKit resonator band-pass IIR filter
10 | 均衡(equalizer): RBJ peaking equalisation biquad IIR filter
11 | FFTFIR滤波(firfit+): FFT convolution FIR filter using given freq. response (W.I.P.)
12 | 高通(highpass): High-pass filter: Single pole or RBJ biquad IIR
13 | 希尔伯特滤波器(hilbert): Hilbert transform filter (90 degrees phase shift)
14 | 低通(lowpass): Low-pass filter: single pole or RBJ biquad IIR
15 | sinc滤波器(sinc): Sinc-windowed low/high-pass/band-pass/reject FIR
16 | 高音(treble): Tone control: RBJ shelving biquad IIR filter
17 | ```
18 |
19 | * Production effects 附加效果
20 |
21 | ```
22 | 合唱(chorus): Make a single instrument sound like many
23 | 延时(delay): Delay one or more channels
24 | 回声(echo): Add an echo
25 | 多回声(echos): Add a sequence of echos
26 | 法兰效应(flanger): Stereo flanger
27 | 过载(overdrive): Non-linear distortion
28 | 相移(phaser): Phase shifter
29 | 重复(repeat): Loop the audio a number of times
30 | 混响(reverb): Add reverberation
31 | 翻转(reverse): Reverse the audio (to search for Satanic messages 😉
32 | 颤音(tremolo): Sinusoidal volume modulation
33 | ```
34 |
35 | * Volume/level effects
36 |
37 | ```
38 | 幅度变化(compand): Signal level compression/expansion/limiting
39 | 对比化(contrast): Phase contrast volume enhancement
40 | 去直流(dcshift): Apply or remove DC offset
41 | 淡入淡出(fade): Apply a fade-in and/or fade-out to the audio
42 | 增益变化(gain): Apply gain or attenuation; normalise/equalise/balance/headroom
43 | 响度控制(loudness): Gain control with ISO 226 loudness compensation
44 | 多带幅度变化(mcompand): Multi-band compression/expansion/limiting
45 | 归一化(norm): Normalise to 0dB (or other)
46 | 音量调节(vol): Adjust audio volume
47 | ```
48 |
49 | * Editing effects
50 |
51 | ```
52 | 拉长(pad): Pad (usually) the ends of the audio with silence
53 | 去除静音(silence): Remove portions of silence from the audio
54 | 结合(splice): Perform the equivalent of a cross-faded tape splice
55 | 裁剪(trim): Cuts portions out of the audio
56 | VAD: Voice activity detector
57 | ```
58 |
59 | * Mixing effects 混音
60 |
61 | ```
62 | 声道混音(channels): Auto mix or duplicate to change number of channels
63 | 分声道(divide+): Divide sample values by those in the 1st channel (W.I.P.)
64 | 任意输出混音(remix): Produce arbitrarily mixed output channels
65 | 翻转声道(swap): Swap stereo channels
66 | ```
67 |
68 | * Pitch/tempo effects 音调/节拍
69 |
70 | ```
71 | 弯曲声调(bend): Bend pitch at given times without changing tempo
72 | 变调(pitch): Adjust pitch (= key) without changing tempo
73 | 变速(speed): Adjust pitch & tempo together
74 | 拉伸压缩(stretch): Adjust tempo without changing pitch (simple alg.)
75 | 变节拍(tempo): Adjust tempo without changing pitch (WSOLA alg.)
76 | ```
77 |
78 | * Mastering effects 母带
79 |
80 | ```
81 | 加入噪声(dither): Add dither noise to increase quantisation SNR
82 | 重采样(rate): Change audio sampling rate
83 | ```
84 |
85 | * Specialised filters/mixers 特殊滤波器/混音器
86 |
87 | ```
88 | 去加重(deemph): ISO 908 CD de-emphasis (shelving) IIR filter
89 | 耳机增强(earwax): Process CD audio to best effect for headphone use
90 | 去噪声(noisered): Filter out noise from the audio
91 | 卡拉ok效应(oops): Out Of Phase Stereo (or `Karaoke’) effect
92 | RIAA: RIAA vinyl playback equalisation
93 | ```
94 |
95 | * Analysis effects 效果分析
96 |
97 | ```
98 | 噪声分析(noiseprof): Produce a DFT profile of the audio (use with noisered)
99 | 频谱分析(spectrogram): graph signal level vs. frequency & time (needs libpng)
100 | 状态分析(stat): Enumerate audio peak & RMS levels, approx. freq., etc.
101 | 多声道状态(stats): Multichannel aware `stat’
102 | ```
103 |
104 | * Miscellaneous effects 其他效果
105 |
106 | ```
107 | LADSPA: Apply LADSPA plug-in effects e.g. CMT (Computer Music Toolkit)
108 | 合成声音(synth): Synthesise/modulate audio tones or noise signals
109 | 新文件(newfile): Create a new output file when an effects chain ends.
110 | 重试(retart): Restart 1st effects chain when multiple chains exist.
111 | ```
112 |
113 | * Low-level signal processing effects 底层信号处理
114 |
115 | ```
116 | 滤波(biquad): 2nd-order IIR filter using externally provided coefficients
117 | 降采样(downsample): Reduce sample rate by discarding samples
118 | fir滤波(fir): FFT convolution FIR filter using externally provided coefficients
119 | 升采样(upsample): Increase sample rate by zero stuffing
120 | ```
121 |
122 |
123 | ```
124 | sox file1.wav -v 0.6 file2.wav
125 | -v 是调节音量的选项,0.6是参数,它是一种线性调整,并不是调整到原来的0.6,而是幅值调整,如果参数大于1则增加音量,反之减小,取值太大会出现削波现象
126 |
127 | sox file1.wav -n stat -v
128 | 1.0003,输出值为不失真最大调整量,stat为效果器,作用是对音频文件做一个统计分析并将结果打印到标准错误文件,-v将打印与音量相关的以Volume Adjustment开头的那行,-n表示输出文件为空,这样在不干扰音频文件的情况下得到文件信息
129 | ```
130 |
131 | [参考](https://www.shuzhiduo.com/A/1O5EgvMaz7/)
132 | [参考](https://github.com/pxhbug123/SoxLibInAndroid/blob/77038094325ebaddc2d0919a88c20127bdd2c70c/soxcommandlibrary/src/main/sox/src/JniNative.c)
133 | [参考](https://github.com/samychen/ffmpegplayer/blob/6e50d5314f2bfaf9300ab6438c1cb2e484bab404/app/src/main/cpp/native-lib.cpp)
134 | [参考](https://github.com/shieldlock/SoX-iPhone-Lib/blob/master/AudioEffects/AudioEffects/ViewController.m)
135 | [参考](https://github.com/mixflame/MixDJ/blob/c125d7372a434a3353c2269fe27c00e52a2d2f3e/MixDJ/soxEncode.m)
136 | [编译](https://github.com/KelvinJin/libsox-iOS)
--------------------------------------------------------------------------------
/Files/Tip005.md:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/Files/Tip005.md
--------------------------------------------------------------------------------
/Files/TypeChange.md:
--------------------------------------------------------------------------------
1 | 常用类型转换
2 |
3 | > # NSData 与 NSString
4 |
5 | ```
6 | // NSData-> NSString
7 | NSString *aString = [[NSString alloc] initWithData:adataencoding:NSUTF8StringEncoding];
8 |
9 | // NSString->NSData
10 | NSString *aString = @"1234abcd";
11 | NSData *aData = [aString dataUsingEncoding: NSUTF8StringEncoding];
12 | ```
13 |
14 |
15 | > # NSData 与 Byte
16 |
17 | ```
18 | // NSData-> Byte数组
19 | NSString *testString = @"1234567890";
20 | NSData *testData = [testString dataUsingEncoding: NSUTF8StringEncoding];
21 |
22 | Byte *testByte = (Byte *)[testData bytes];
23 | for(int i = 0;i<[testData length];i++) {
24 | printf("testByte = %d\n",testByte[i]);
25 | }
26 |
27 | // Byte数组-> NSData
28 | Byte byte[] = {0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22,23};
29 | NSData *adata = [[NSData alloc] initWithBytes:byte length:24];
30 | ```
31 |
32 | > # Byte数组和16进制数
33 |
34 |
35 | ```
36 | // Byte数组->16进制数
37 |
38 | Byte *bytes = (Byte *)[aData bytes];
39 | NSString *hexStr= @"";
40 |
41 | for(int i = 0;i<[encryData length];i++) {
42 | NSString *newHexStr = [NSString stringWithFormat:@"%x",bytes[i]&0xff];// 16进制数
43 | if([newHexStr length]==1) {
44 | hexStr = [NSString stringWithFormat:@"%@0%@",hexStr,newHexStr];
45 | } else {
46 | hexStr = [NSString stringWithFormat:@"%@%@",hexStr,newHexStr];
47 | }
48 | }
49 | NSLog(@"bytes 的16进制数为:%@",hexStr);
50 |
51 | // 16进制数->Byte数组
52 | NSString *hexString = @"3e435fab9c34891f"; //16进制字符串
53 | int j=0;
54 | Byte bytes[128]; // 3ds key的Byte 数组, 128位
55 |
56 | for(int i=0;i<[hexString length];i++) {
57 | // 两位16进制数转化后的10进制数
58 | int int_ch;
59 | // 两位16进制数中的第一位(高位*16)
60 | unichar hex_char1 = [hexString characterAtIndex:i];
61 | int int_ch1;
62 | if(hex_char1 >= '0' && hex_char1 <='9') {
63 | // 0 的Ascll - 48
64 | int_ch1 = (hex_char1-48)*16;
65 | } else if(hex_char1 >= 'A' && hex_char1 <='F') {
66 | // A 的Ascll - 65
67 | int_ch1 = (hex_char1-55)*16;
68 | } else {
69 | // a 的Ascll - 97
70 | int_ch1 = (hex_char1-87)*16;
71 | }
72 | i++;
73 | // 两位16进制数中的第二位(低位)
74 | unichar hex_char2 = [hexString characterAtIndex:i];
75 | int int_ch2;
76 | if(hex_char2 >= '0' && hex_char2 <='9') {
77 | // 0 的Ascll - 48
78 | int_ch2 = (hex_char2-48);
79 | } else if(hex_char1 >= 'A' && hex_char1 <='F') {
80 | // A 的Ascll - 65
81 | int_ch2 = hex_char2-55;
82 | } else {
83 | // a 的Ascll - 97
84 | int_ch2 = hex_char2-87;
85 | }
86 | int_ch = int_ch1+int_ch2;
87 | NSLog(@"int_ch=%d",int_ch);
88 | // 将转化后的数放入Byte数组里
89 | bytes[j] = int_ch;
90 | j++;
91 | }
92 | NSData *newData = [[NSData alloc] initWithBytes:bytes length:128];
93 | NSLog(@"newData=%@",newData);
94 | ```
95 |
96 |
97 | > # NSData 与 UIImage
98 |
99 | ```
100 | // NSData->UIImage
101 | UIImage *aimage = [UIImage imageWithData:imageData];
102 |
103 | //例:从本地文件沙盒中取图片并转换为NSData
104 | NSString *path = [[NSBundle mainBundle] bundlePath];
105 | NSString *name = [NSString stringWithFormat:@"ceshi.png"];
106 | NSString *finalPath = [path stringByAppendingPathComponent:name];
107 | NSData *imageData = [NSData dataWithContentsOfFile: finalPath];
108 | UIImage *aimage = [UIImage imageWithData: imageData];
109 |
110 | // UIImage-> NSData
111 | NSData *imageData = UIImagePNGRepresentation(aimae);
112 | ```
113 |
114 | > # int 和 byte[]
115 |
116 | ```
117 | // 将int数值转换为占四个字节的byte数组,本方法适用于(高位在前,低位在后)的顺序。 和bytesToInt2()配套使用
118 | public static byte[] intToBytes2(int value) {
119 | byte[] src = new byte[4];
120 | src[0] = (byte) ((value>>24) & 0xFF);
121 | src[1] = (byte) ((value>>16)& 0xFF);
122 | src[2] = (byte) ((value>>8)&0xFF);
123 | src[3] = (byte) (value & 0xFF);
124 | return src;
125 | }
126 |
127 | // byte数组中取int数值,本方法适用于(低位在后,高位在前)的顺序。和intToBytes2()配套使用
128 | public static int bytesToInt2(byte[] src, int offset) {
129 | int value;
130 | value = (int) (((src[offset] & 0xFF)<<24) | ((src[offset+1] & 0xFF)<<16) | ((src[offset+2] & 0xFF)<<8) | (src[offset+3] & 0xFF));
131 | return value;
132 | }
133 | ```
--------------------------------------------------------------------------------
/Files/Use_frameworks.md:
--------------------------------------------------------------------------------
1 | \# 在Podfiel中是注释即使用和不使用, \#use_frameworks!表示不使用 use_frameworks!
2 |
3 | > # 使用\#use_frameworks!:
4 |
5 | 如果在Podfile文件里不使用 use_frameworks! 则是会生成相应的 .a文件(静态链接库),通过 static libraries 这个方式来管理pod的代码。
6 |
7 | Linked:libPods-xxx.a包含了其它用pod导入的第三方框架的.a文件。
8 |
9 | > # 而使用use_frameworks!:
10 |
11 | 则cocoapods 会生成相应的 .frameworks文件(动态链接库:实际内容为 Header + 动态链接库 + 资源文件),使用 dynamic frameworks 来取代 static libraries 方式。
12 |
13 | Linked:Pods_xxx.framework包含了其它用pod导入的第三方框架的.framework文件。
14 |
15 |
16 | 即:
17 |
18 | use_frameworks! -> dynamic frameworks 方式 -> .framework
19 | \#use_frameworks! -> static libraries 方式 -> .a
20 |
21 | > # 注意
22 |
23 | Swift项目cocoapods 默认 use_frameworks!
24 | OC项目cocoapods 默认 \#use_frameworks!
25 | 用cocoapods 导入Swift 框架到 swift项目和OC项目都必须要 use_frameworks!
26 | 使用 dynamic frameworks,必须要在Podfile文件中添加 use_frameworks!
27 |
--------------------------------------------------------------------------------
/Files/Wifi.md:
--------------------------------------------------------------------------------
1 | 如果有这样的奇葩要求:wifi连接只能硬件,然后2/3/4/5G上网。看似简单。。。
2 | 问题来了:默认情况wifi连接后2/3/4/5G流量就被阻止了。。。
3 |
4 |
5 | 不过可以进行下面设置,完成上面需求
6 |
7 | 1,先连接上WiFi,打开详情可看到DHCP;
8 | 2,把IP地址和子网掩码,就是前两行抄下来;
9 | 3,点击静态,就是DHCP右边第二个按钮,把刚才抄下来的IP地址和子网掩码写进去;
10 | 4,确保静态下的路由器以及DNS什么的都不要填写;
11 |
12 | 至此返回就可以体验iPhone手机同时连接WiFi和3G/4G了,也达到了APP想要的效果;
13 |
14 | https://discussions.apple.com/thread/3703817?tstart=0
15 | https://support.apple.com/en-us/HT201373
--------------------------------------------------------------------------------
/Files/Xcode.md:
--------------------------------------------------------------------------------
1 | > ### 键盘符号
2 |
3 |
4 | * ⌘ Command / Cmd
5 | * ⌥ Option / Alt
6 | * ⇧ Shift / Caps Loc
7 | * ⌃ Control / Ctrl
8 | * ⏎ Return
9 | * ⌫ Delete
10 | * ← Left
11 | * → Right
12 | * ↑ top
13 | * ↓ down
14 |
15 | > ### 快捷键
16 |
17 | ##### 文件
18 |
19 | * 新建文件: Command + N
20 | * 新建空文件: Command + Ctrl + N
21 | * 新建项目: Command + Shift + N
22 | * 打开文件: Command + O
23 | * 保存文件: Command + S
24 | * 保存所有文件: Command + Alt + S
25 | * 文件另存为: Command + Shift + S
26 | * 关闭窗口: Command + W
27 | * 退出程序: Command + Q
28 | * 关闭文件: Command + Shift + W
29 | * 内容全选: Command + A
30 | * 自动对齐: 选中后Ctrl + I
31 |
32 | ##### 编辑
33 |
34 | * 向左缩进: Command + [
35 | * 向右缩进: Command + ]
36 | * 项目中查找: Command + Shift + F
37 | * 查找下一个: Command + G
38 | * 查找上一个: Command + Shift + G
39 | * 前移光标: Ctrl + F
40 | * 后移光标: Ctrl + B
41 | * 移动光标到上一行: Ctrl + P
42 | * 移动光标到下一行: Ctrl + N
43 | * 移动光标到本行行首(替换Home键): Ctrl + A
44 | * 移动光标到本行行尾(替换end键): Ctrl + E
45 | * 交换光标左右两边的字符: Ctrl + T
46 | * 删除光标右边单个字符(如果选中则删除选中): Ctrl + D
47 | * 删除本行右边所有字符(如果选中则删除选中): Ctrl + K
48 | * 将插入点置于窗口正中: Ctrl + L
49 | * 参数提示: Ctrl + .
50 | * 显示代码提示菜单: Esc
51 | * 向上移动: Command + Option + [
52 | * 向下移动: Command + Option + ]
53 | * 局部折叠: Command + Option + Left
54 | * 局部展开: Command + Option + Right
55 | * 全局折叠: Command + Option + Shift + Left
56 | * 全局展开: Command + Option + Shift + Right
57 |
58 | ##### 调试
59 |
60 | * 运行程序: Command + R
61 | * 停止运行: Command + .
62 | * 编译程序: Command + B
63 | * 清除工程: Command + Shift + K
64 | * 带提示清除: Command + Shift + Option + K
65 | * 切换.h和.m文件: Command + Ctrl + Top/Down
66 | * 设置或取消断点: Command + \
67 | * 允许或禁用当前断点: Command + Alt + \
68 | * 查看全部断点: Command + Alt + B
69 | * 编译并运行(根据设置决定是否启用断点): Command + Enter
70 | * 编译并调试(触发断点): Command + Y
71 | * 终止运行或调试: Command + SHIFT + Enter
72 | * 继续(在调试中): Command + Alt + P
73 | * 跳过: Command + Alt + 0
74 | * 跳入: Command + Alt + I
75 | * 跳出: Command + Alt + T
76 |
77 | > ### 一些默认路径
78 |
79 | * 快捷代码段 Libary/Developer/Xcode/UserData/CodeSnippets
80 | * 真机调试包 /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneOS.platform/DeviceSupport
81 |
82 | > ### Error
83 |
84 | 1. 签名问题
85 | ```
86 | object file format unrecognized, invalid, or unsuitable
87 | /usr/bin/codesign failed with exit code 1
88 | ```
89 | 解决方案
90 | ```
91 | sudo mv /usr/bin/codesign_allocate /usr/bin/codesign_allocate_old
92 | sudo ln -s ...Xcode.app/Platforms/iPhoneOS.platform/Developer/usr/bin/codesign_allocate /usr/bin
93 | ```
94 |
95 | > ### 优化
96 |
97 | // 不每次重复全量编译
98 | user-defined HEADERMAP_USES_VFS YES
99 |
100 | // Command PhaseScriptExecution failed with a nonzero exit code
101 | SWIFT_ENABLE_BATCH_MODE NO
102 |
103 |
104 | > ### 打包前添加Action判断是否release
105 |
106 | Edit Scheme -> Archive -> Pre-actions -> New Run Script Action -> provide build setting from
107 |
108 | ```
109 | if [ $CONFIGURATION != "Release" ]; then
110 |
111 | osascript -e 'tell app "Xcode" to display dialog "正在非Release打包!当前环境'$CONFIGURATION'"'
112 |
113 | fi
114 | ```
115 |
116 | > ### 打包前自增build号
117 |
118 | [持续集成时指定构建号](https://www.jianshu.com/p/eba178ee4150)
119 |
120 | ```
121 | if [ $CONFIGURATION == Release ]; then
122 | echo "Bumping build number..."
123 | plist=${PROJECT_DIR}/${INFOPLIST_FILE}
124 |
125 | # increment the build number (ie 115 to 116)
126 | buildnum=$(/usr/libexec/PlistBuddy -c "Print CFBundleVersion" "${plist}")
127 | if [[ "${buildnum}" == "" ]]; then
128 | echo "No build number in $plist"
129 | exit 2
130 | fi
131 |
132 | buildnum=$(expr $buildnum + 1)
133 | /usr/libexec/Plistbuddy -c "Set CFBundleVersion $buildnum" "${plist}"
134 | echo "Bumped build number to $buildnum"
135 |
136 | else
137 | echo $CONFIGURATION " build - Not bumping build number."
138 | fi
139 | ```
140 |
141 | > ### Xcode objectVersion
142 |
143 | ```
144 | https://www.rubydoc.info/github/CocoaPods/Xcodeproj/Xcodeproj/Constants
145 |
146 | 56 => 'Xcode 14.0',
147 | 55 => 'Xcode 13.0',
148 | 54 => 'Xcode 12.0',
149 | 53 => 'Xcode 11.4',
150 | 52 => 'Xcode 11.0',
151 | 51 => 'Xcode 10.0',
152 | 50 => 'Xcode 9.3',
153 | 48 => 'Xcode 8.0',
154 | 47 => 'Xcode 6.3',
155 | 46 => 'Xcode 3.2',
156 | 45 => 'Xcode 3.1',
157 | ```
158 |
159 | > ### xcode配置dsym文件生成
160 |
161 | ```
162 | XCode -> Build Settings -> Build Option -> Debug Information Format -> DWARF with dSYM File
163 |
164 | XCode -> Build Settings -> Apple Clang - Code Generation -> Generate Debug Symbols -> Yes
165 |
166 | 查找.dsym文件方法:
167 | XCode -> Window -> Organizer -> 找到打包好的文件(Show in Finder)-> 选中文件(右键显示包内容)-> dsYMs文件夹下就是了
168 | ```
169 |
170 |
171 |
172 | > ### 解析project.pbxproj
173 |
174 | ```
175 | plutil -convert json project.pbxproj
176 |
177 | plutil -convert xml1 -s -r -o project.pbxproj.xml project.pbxproj
178 | // https://looseyi.github.io/post/sourcecode-cocoapods/08-cocoapods-xcodeproj/
179 | ```
180 |
181 | * [xcodebuildsettings](https://xcodebuildsettings.com/)
182 | * [How can I modify OTHER_LDFLAGS via CocoaPods post-install hook?](https://stackoverflow.com/questions/30244675/how-can-i-modify-other-ldflags-via-cocoapods-post-install-hook)
--------------------------------------------------------------------------------
/Files/aml.md:
--------------------------------------------------------------------------------
1 | ```
2 | SSDT-PLUG-DRTNIA.aml:用于启用CPU电源管理和睿频。
3 | SSDT-EC.aml:用于修复嵌入式控制器,以避免ACPI错误。
4 | SSDT-GPRW.aml:用于修复睡眠问题。
5 |
6 | SSDT-USB(x).aml:这是每套 EFI 都应该有的
7 | SSDT-RHUB.aml:某些主板的 ACPI 确定存在问题,需要使用此文件进行修复调整,例如华硕 B460、部分微星 B460 等
8 |
9 | SSDT-plug.aml 加载CPU原生电源管理(开启节能四项
10 | SSDT-EC-USBX(同SSDT-EC):禁用EC(Embedded Controller)和修复USB充电问题,可选
11 | SSDT-AWAC.aml 修复RTC禁止AWAC(或者使用RTC0.aml补丁,二者选其一),必须
12 | SSDT-PMC.aml 开启NVRAM (Z370、Z490和B460原生支持,可以不需要此补丁,其他主板基本都需要)可选
13 | SSDT-GPRW.aml 解决大部分PC睡眠即醒问题,需搭配重命名使用(rename 47505257 02 to 58505257 02)
14 | SSDT-PM.aml 加载节能第五项(断电后自动重启生效,PC基本通用的补丁)
15 | SSDT-OC-XOSI.aml 操作系统补丁,配合重命名rename 5F4F5349 to 584F5349,技嘉主板需要
16 |
17 | SSDT-EC.aml 用于防止卡afps_module_start
18 | SSDT-AWAC.aml 用于防止卡afps_module_start
19 | SSDT-XCPM.aml 用于开启CPU的SpeedStep
20 | SSDT-PMCR.aml 开启节能五项
21 | ```
22 |
23 |
24 | ```
25 | 显卡:Lilu.kext, WhateverGreen.kext
26 | 声卡:AppleALC.kext
27 | 网卡:IntelMausi.kext
28 | USB:USBInjectAll.kext
29 | 独立显卡:WhateverGreen.kext, NvidiaGraphicsFixup.kext, NvidiaWebDriverInjector.kext / WhateverGreen.kext, AGDPFix.kext / WhateverGreen.kext, RadeonDeInit.kext
30 | ```
--------------------------------------------------------------------------------
/MindNode/FlutterWidget.mindnode/QuickLook/Preview.jpg:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/MindNode/FlutterWidget.mindnode/QuickLook/Preview.jpg
--------------------------------------------------------------------------------
/MindNode/FlutterWidget.mindnode/contents.xml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/MindNode/FlutterWidget.mindnode/contents.xml
--------------------------------------------------------------------------------
/MindNode/FlutterWidget.mindnode/style.mindnodestyle/contents.xml:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/MindNode/FlutterWidget.mindnode/style.mindnodestyle/contents.xml
--------------------------------------------------------------------------------
/MindNode/FlutterWidget.mindnode/style.mindnodestyle/metadata.plist:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/MindNode/FlutterWidget.mindnode/style.mindnodestyle/metadata.plist
--------------------------------------------------------------------------------
/MindNode/FlutterWidget.mindnode/viewState.plist:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/MindNode/FlutterWidget.mindnode/viewState.plist
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | > 为了方便管理,用的文件名首字符排序
2 |
3 | * [3DTouch 快捷启动,Peak与Pop](https://github.com/starainDou/DDYKnowledge/blob/master/Files/3DTouch.md)
4 | * [强制内联](https://github.com/starainDou/DDYKnowledge/blob/master/Files/AlwaysInline.md)
5 | * [batteryLevel 精准获取电量](https://github.com/starainDou/DDYKnowledge/blob/master/Files/BatteryLevel.md)
6 | * [BuildConfiguration 区分debug和release](https://github.com/starainDou/DDYKnowledge/blob/master/Files/BuildConfiguration.md)
7 | * [Chrome使用小知识](https://github.com/starainDou/DDYKnowledge/blob/master/Files/Chrome.md)
8 | * [CocoaPods 安装管理与支持](https://github.com/starainDou/DDYKnowledge/blob/master/Files/CocoaPods.md)
9 | * [删除MacOSX系统的ABC输入法](https://github.com/starainDou/DDYKnowledge/blob/master/Files/DeleteSystemABC.md)
10 | * [主动退出App](https://github.com/starainDou/DDYKnowledge/blob/master/Files/Exit.md)
11 | * [Git的使用](https://github.com/starainDou/DDYKnowledge/blob/master/Files/Git.md)
12 | * [iOS 13 问题解决以及苹果登录](https://github.com/starainDou/DDYKnowledge/blob/master/Files/iOS13.md)
13 | * [LineBreakMode 折行模式](https://github.com/starainDou/DDYKnowledge/blob/master/Files/LineBreakMode.md)
14 | * [nil/Nil/Null/NSNull](https://github.com/starainDou/DDYKnowledge/blob/master/Files/Nil_nil_Null_NSNull.md)
15 | * [方法调用NSInvocation传多参(performSelector最多两个参数)](https://github.com/starainDou/DDYKnowledge/blob/master/Files/NSInvocation.md)
16 | * [NSPredicate 谓词+正则](https://github.com/starainDou/DDYKnowledge/blob/master/Files/NSPredicate.md)
17 | * [工程0-1时需要考虑的](https://github.com/starainDou/DDYKnowledge/blob/master/Files/ProjectNotice.md)
18 | * [安全返回主线程](https://github.com/starainDou/DDYKnowledge/blob/master/Files/SafeMainAsync.md)
19 | * [Singleton 单例写法和宏定义](https://github.com/starainDou/DDYKnowledge/blob/master/Files/Singleton.md)
20 | * [MacOSX关闭系统防护SIP](https://github.com/starainDou/DDYKnowledge/blob/master/Files/SIP.md)
21 | * [多线程](https://github.com/starainDou/DDYKnowledge/blob/master/Files/Thread.md)
22 | * [Tip001](https://github.com/starainDou/DDYKnowledge/blob/master/Files/Tip001.md)
23 | * [Tip002](https://github.com/starainDou/DDYKnowledge/blob/master/Files/Tip002.md)
24 | * [一些常用类型转换](https://github.com/starainDou/DDYKnowledge/blob/master/Files/TypeChange.md)
25 | * [use_frameworks](https://github.com/starainDou/DDYKnowledge/blob/master/Files/use_frameworks.md)
26 | * [Wifi连接同时2/3/4/5G上网](https://github.com/starainDou/DDYKnowledge/blob/master/Files/Wifi.md)
27 |
28 |
29 |
--------------------------------------------------------------------------------
/video/Android.webm:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/video/Android.webm
--------------------------------------------------------------------------------
/video/iOS.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/video/iOS.mov
--------------------------------------------------------------------------------
/video/iOS.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/video/iOS.mp4
--------------------------------------------------------------------------------
/video/iOS的副本.mp4:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/video/iOS的副本.mp4
--------------------------------------------------------------------------------
/video/puppets_with_alpha_hevc-1.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/video/puppets_with_alpha_hevc-1.mov
--------------------------------------------------------------------------------
/video/puppets_with_alpha_hevc.mov:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/starainDou/DDYKnowledge/793f3ce9f7eb6813682492a37fd86cafd9102726/video/puppets_with_alpha_hevc.mov
--------------------------------------------------------------------------------
/积累知识/影视_歌曲_明星_现代.md:
--------------------------------------------------------------------------------
1 | > # 影视
2 |
3 |
4 | > # 歌曲
5 |
6 | 1. A
7 |
8 |
9 |
10 |
11 | 2. B
12 |
13 |
14 |
15 |
16 | 3. C
17 |
18 |
19 |
20 |
21 | 4. D
22 |
23 | * 大约在冬季
24 |
25 | 5. E
26 |
27 |
28 |
29 |
30 | 6. F
31 |
32 |
33 |
34 |
35 | 7. G
36 |
37 | 关不上的窗-周传雄-2009
38 |
39 |
40 | 8. H
41 |
42 | 后来-刘若英-1999
43 | 花好月圆-刁寒-1995
44 | 花好月圆夜-由任贤齐、杨千嬅(hua4)-2004
45 |
46 |
47 | 9. I
48 |
49 |
50 |
51 |
52 | 10. J
53 |
54 | * 酒干倘卖无
55 |
56 |
57 | 11. K
58 |
59 |
60 |
61 |
62 | 12. L
63 |
64 | * 恋曲1990
65 |
66 |
67 |
68 | 13. M
69 |
70 | * 明天会更好
71 |
72 |
73 | 14. N
74 |
75 | * 你的样子
76 | * 你潇洒我漂亮
77 |
78 |
79 |
80 |
81 | 15. O
82 |
83 |
84 |
85 |
86 | 16. P
87 |
88 |
89 |
90 |
91 | 17. Q
92 |
93 | 青花-周传雄-2007
94 |
95 |
96 | 18. R
97 |
98 |
99 |
100 |
101 | 19. S
102 |
103 | 神话情话-粤语-1995-改编周华健、齐豫《天下有情人》
104 |
105 |
106 | 20. T
107 |
108 |
109 |
110 |
111 | 21. U
112 |
113 |
114 |
115 |
116 | 22. V
117 |
118 |
119 |
120 |
121 | 23. W
122 |
123 | 我的梦-张靓颖-2015改编自《Dream It Possible》
124 | 我是一棵小草
125 |
126 |
127 | 24. X
128 |
129 | 谢谢你的爱-刘德华-1992
130 |
131 |
132 | 25. Y
133 |
134 | * 有一种爱叫做放手-阿木-2007
135 | * 一场游戏一场梦
136 |
137 |
138 | 26. Z
139 |
140 |
141 |
142 |
143 | 27. #
144 |
145 |
146 | > # 乐曲
147 |
148 | * 渔舟唱晚 [天气预报曲]
149 | * 高山流水 []
150 | * 赛马
151 | * 戏梦
152 | * 蕉窗夜雨
153 | * 游园
154 | * 春江花月夜
155 | * 寒鸦戏水
156 | * 花好月圆 [纯音乐,黄贻钧,中央广播民族乐团演奏]
157 | * 彩云追月 [纯音乐,任光、聂耳,此曲最早记载为清代]
158 | * OPening [纯音乐,黄英华,周星驰《少林足球》背景音乐]
159 | * Victory [纯音乐,Two Steps From Hell (地狱咫尺)的单曲]
160 | * 西班牙斗牛士进行曲 [纯音乐,西班牙玛奎纳(帕斯夸尔·玛奎纳·纳罗)]
161 | * 青天变奏 [纯音乐,胡伟立,周星驰《九品芝麻官之白面包青天》背景音乐]
162 | * Presence of the Moment [纯音乐,史蒂夫·霍恩,《今日说法》背景音乐]
163 | * 十面埋伏 [琵琶曲,清代华秋萍]
164 | * 梦回仙游 [游戏仙剑奇侠传4背景音,骆集益]
165 | * 兄弟情谊 [纯音乐,赵季平,水浒传原声音乐]
166 | * Annie's Wonderland [安妮的仙境,班得瑞]
167 | * 大団円 [da4tuan2yuan2,川井宪次]
168 | * 拉德斯基进行曲 [老约翰·施特劳斯]
169 | * 月光下的凤尾竹 [经典葫芦丝,施光南]
170 | * 运动员进行曲 [学校运动会必备,吴光锐、贾双、李明秀]
171 | * Purple Passion [紫色激情,Diana Boncheva]
172 | * 克罗地亚狂想曲 [马克西姆]
173 | * 苦难重重 [《新白娘子传奇》插曲]
174 | * 万里的长城 [太田美知彦]
175 | * 天地孤影任我行 [陈勋奇]
176 | * 西天取经路遥遥 [赵季平,《大话西游》插曲]
177 | * 紫竹调 [民间小调]
178 | * 求神 [周星驰《唐伯虎点秋香》]
179 | * 江河水 [悲情二胡,闵惠芬,周星驰《唐伯虎点秋香》中小强部分]
180 | * 勇往直前 [超级经典,胡伟立,周星驰《唐伯虎点秋香》]
181 | * 市集 [胡伟立,成龙《醉拳2》]
182 | * 偷功 [胡伟立,李连杰《太极张三丰》原声]
183 | * 笑傲江湖曲 [琴箫,胡伟立,笑傲江湖御用]
184 | * 雪千寻 [胡伟立,《东方不败之风云再起》]
185 | * 初识太极 [胡伟立,李连杰《太极张三丰》]
186 | * 国产凌凌漆 [胡伟立,周星驰《国产凌凌漆》]
187 | * 温馨时刻 [胡伟立,成龙《醉拳2》原声]
188 | * 二人心跳 [胡伟立,周星驰《唐伯虎点秋香》号脉背景乐]
189 | * 随缘 [胡伟立,李连杰《太极张三丰》原声]
190 | * 丽春院 [胡伟立,周星驰《鹿鼎记》丽春院经典背景乐]
191 | * 侠风 [胡伟立,武侠必备]
192 | * 太极拳 [胡伟立,李连杰《太极张三丰》原声]
193 | * 慈宁宫森严 [胡伟立,周星驰《鹿鼎记》]
194 | * 母与子 [胡伟立,成龙《醉拳2》原声]
195 | * 片头 [胡伟立,唐伯虎点秋香片头]
196 | * 笑八仙 [胡伟立]
197 | * 琴箫合奏曲 [胡伟立,射雕经典]
198 | * 后楼梯闹鬼 [胡伟立,周星驰《回魂夜》]
199 | * 思念 [胡伟立,武侠回忆音乐背景]
200 | * 庆功天仙曲 [许镜清]
201 | * 天府乐 [许镜清]
202 | * 云宫讯音 [许镜清,《西游记》片头曲]
203 | * 上任弼马温 [许镜清,《西游记》,被误认为猪八戒背媳妇]
204 | * 杨戬擒悟空 [许镜清,《西游记》大闹天宫中杨戬对悟空]
205 | * 三美戏八戒、八戒撞天婚 [许镜清]
206 | * 梦中会御弟 [许镜清]
207 | * 女儿情 [许镜清,《西游记》插曲]
208 | * 助兴鹤仙舞 [许镜清,《西游记》插曲]
209 | * 初称美猴王 [许镜清,《西游记》插曲]
210 | * 天竺少女 [许镜清,《西游记》插曲]
211 | * 仙童斥四僧 [许镜清,《西游记》插曲]
212 | * 敢问路在何方 [许镜清,《西游记》经典]
213 | * 百鸟朝凤 [喜庆经典,任同祥]
214 | * The Party Troll [鬼畜常用]
215 | * 二泉映月 [阿炳]
216 | * 枉凝眉 [王立平]
217 | * 我心永恒 [詹姆斯·霍纳]
218 | * 恨爱交加 [麦振鸿]
219 | * 森林狂想曲 [徐仁修、刘义骅、杨雅棠等]
220 | * String Tek [X-Ray Dog工作室-好莱坞]
221 | * The Glorous Death [壮烈牺牲,悲情,冯曦妤]
222 | * 傲气傲笑万重浪 [黄霑,黄飞鸿打斗御用]
223 | * 梁祝 [何占豪、陈钢]
224 | * 欢沁 [欢快,林海]
225 | * 莫失莫忘 [麦振鸿,仙剑]
226 | * Title Theme [欢快]
227 | * 前世今生 [左宏元,《新白娘子传奇》]
228 | * 七剑战歌 [川井宪次]
229 | * 天龙八部间奏曲 [武聆音雄,乔峰出场必备]
230 | * Immortal [霸气的音乐]
231 | * 猪突猛进 [百石元,欢快而逗比]
232 | * 英雄的黎明 [横山菁儿,日漫《三国志》主题曲之一]
233 | * Star Sky [Two Step From Hell]
234 | * 只要为你活一天 [刘家昌,周星驰《功夫》黄圣依棒棒糖]
235 | * 王进打高球 [赵季平,96版水浒]
236 | * 象王行 [关大洲]
237 | * 故宫的记忆 [神思者S.E.N.S]
238 | * Breath and Life [气势恢宏,Audiomachine]
239 | * Kung Fu 1 [爆款,《功夫》]
240 | * Mission Impossible [丹尼·叶夫曼,《碟中谍》阿汤哥无敌曲]
241 | * 梦中的婚礼 [理查德·克莱德曼]
242 | * The Magnificent Seven [豪勇七蛟龙]
243 | * 赌神 [卢冠廷,赌神出场BGM]
244 | * 琵琶语 [林海,好听]
245 | * He is A Pirate [Klaus Badelt,《加勒比海盗》杰克船长来了]
246 | * 雪见,落入凡尘 [麦振鸿,仙剑]
247 | * Conquest Of Paradise [征服天堂,Vangelis,气派,《士兵突击》用过]
248 | * Hearth Of Courage [震撼,Two Step From Hell]
249 | * 故乡的原风景 [宗次郎,放松]
250 | * 夜莺 [Yanni(雅尼)]
251 | * 天空之城 [久石让,悲情流全身]
252 | * EI Dorado Dubstep(Remix) [Two Step From Hell]
253 | * ScarSong [监控中的神秘事件BGM]
254 | * Going Home [Kenny·G,结束曲或请您欣赏]
255 | * 再见 警察 [陈光荣,一路走好的悲伤]
256 | * Here We Are Again [Cagnet,节奏]
257 | *
--------------------------------------------------------------------------------
/积累知识/电影_动画_文章_网址.md:
--------------------------------------------------------------------------------
1 | > #### 网站
2 |
3 | * [爱动漫](http://www.idm.vip/)
4 | * [超快资源网](http://www.kukuzy.com/)
5 | * [极速云采集](http://www.caijizy.com/)
6 | * [中华电信网络直播](https://www.hinet.net/tv/)
7 | * [台湾电视网](http://www.taiwantv.co/)
8 | * [CCTV直播(官方)](http://tv.cctv.com/live/)
9 | * [北京邮电大学(官方)](http://ivi.bupt.edu.cn/)
10 | * [看看新闻高清(官方)](http://live.kankanews.com/huikan/)
11 | * [浙江卫视中国蓝(官方)](http://tv.cztv.com/live1)
12 | * [湖南电视台官网(官方)](http://live.mgtv.com/)
13 | * [虎牙轮播台](https://www.huya.com/g/2135)
14 | * [成都电视台](http://www.cditv.cn/html/cdrtv/#live)
15 | * [爱酷直播](http://www.ikuzb.com/)
16 | * [龙信影视](http://zb.mylongxin.com/app/view/tv.php)
17 | * [易视网](https://www.cietv.com/)
18 | * [好趣网](http://www.haoqu.net)
19 | * [直播网](http://www.hao5.net)
20 | * [飞流直播](http://chaochaolive.icntv.xyz/)
21 | * [全球网络电视直播网](https://www.nettv.live/)
22 | * [香港台](https://www.rthk.hk/tv)
23 | * [身份证验证](http://qq.ip138.com/baidu-id/index.asp)
24 | * [iOS各个版本安装率](https://developer.apple.com/support/app-store/)
25 | * [Python3_anaconda清华镜像](https://mirrors.tuna.tsinghua.edu.cn/help/anaconda/)
26 | * [3D模型](https://free3d.com/3d-models/)
27 | * [Google ARCore](https://developers.google.cn/ar/develop/ios/cloud-anchors-developer-guide-ios?authuser=0&hl=zh-cn)
28 | * [Google 3D资源](https://poly.google.com/)
29 |
30 |
31 | https://github.com/bannedbook/fanqiang/wiki
32 | https://github.com/yanue/V2rayU
33 | https://github.com/Alvin9999/new-pac/wiki
34 | https://github.com/Alvin9999/new-pac/wiki/v2ray免费账号
35 | https://github.com/Alvin9999/new-pac/wiki/苹果电脑MAC翻墙软件
36 | https://github.com/Jrohy/multi-v2ray
37 | https://iruach.com/?p=146
38 | https://github.com/max2max/freess
39 | https://freefq.com/free-ss/2020/01/16/ss.html
40 | https://shadowsockshelp.github.io/Shadowsocks/ios.html
41 | https://shadowsockshelp.github.io/Shadowsocks/appleid.html
42 | https://github.com/shadowsocks/ShadowsocksX-NG
43 |
44 | > #### 精彩电影
45 |
46 | * 宝莱坞机器人之恋
47 | * 宝莱坞机器人之恋2之重生归来
48 | * 哪吒之魔童降世
49 | * 速度与激情1
50 | * 速度与激情2
51 | * 速度与激情3
52 | * 速度与激情4
53 | * 速度与激情5
54 | * 速度与激情6
55 | * 速度与激情7
56 | * 速度与激情8
57 | * 速度与激情9
58 | * 蜘蛛侠之英雄远征
59 | * 搭错车
60 | * ET外星人
61 | * 阿甘正传
62 | * 血战钢锯岭
63 | * 荒岛余生
64 | * 战狼1
65 | * 战狼2
66 | * 红海行动
67 | * 湄公河行动
68 | * 智取威虎山
69 | * 老师好
70 | * 硬汉
71 | * 拯救大兵瑞恩
72 | * 我不是药神
73 | * 追龙
74 | * 天下无贼
75 | * 失孤
76 | * [赞先生与找钱华](http://www.600m.net/m/gaXjYkQmQnL5SB.html)
77 | * [七月十三之龙婆](https://www.iqiyi.com/v_19rrjbj4hc.html)
78 | * [半夜叫你别回头](http://www.600m.net/m/hKfiZBH1RnT6Sh.html)
79 | * []()
80 |
81 |
82 | > #### 精彩电视剧
83 |
84 | * 大染坊(2003,侯勇,孙俪,萨日娜,罗刚)
85 | * 岁岁年年柿柿红
86 | * 樱桃(宋小宝,沈春阳,赵本山)
87 | * 法医宋慈
88 | * 人民的名义
89 | * 破冰行动
--------------------------------------------------------------------------------
/积累知识/诗词_歌赋_典故_古代.md:
--------------------------------------------------------------------------------
1 | 学无止境,哪怕你在看短视频。。。
2 |
3 | > #### 1. 一树梨花压海棠 的由来(苏轼作诗讽友张先八十娶妻十八)
4 |
5 | 苏轼有个朋友叫张先。
6 | 张先80岁的时候娶到一个18岁的姑娘,为炫耀作诗一首:
7 |
8 | ```
9 | 我年八十卿十八,卿是红颜我白发。
10 | 与卿颠倒本同庚,只隔中间一花甲。
11 | ```
12 |
13 | 苏轼听闻,很是气愤,于是作诗讽刺这位老友:
14 |
15 | ```
16 | 十八新娘八十郎,苍苍白发对红妆。
17 | 鸳鸯被里成双夜,一树梨花压海棠。
18 | ```
19 |
20 | > #### 2. 历史朝代速记
21 |
22 | * 简单版
23 |
24 | ```
25 | 三皇五帝始,尧舜禹相传;
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 | 金田太平国,时适清道光;
52 | 九传至光绪,维新有康梁;
53 | 换位至宣统,民国废末皇;
54 | 五四风雨骤,建国存新纲;
55 | 抗日反内战,五星红旗扬。
56 | ```
57 |
58 | > #### 别称借代
59 |
60 | * 酒:琼、琼浆、玉液、琼浆玉液、佳酿、金浆太醴、香醪(lao2)、红友、杯中物、三酉、般若汤、杜康、曲生、曲秀才、福水。
61 | * 雪:琼玉、琼妃、碎玉、冰花、六出、乱玉、瑞叶、玉沙、玉蝶、璇花、碎琼
62 | * 月:蟾宫、玉盘、银钩、月宫、婵娟、桂宫、望舒
63 | * 钱:泉、方孔、邓通、阿堵物、青蚨、上清童子
64 | * 书信:鸿、鸿雁、尺牍、尺素、函杞
65 |
66 | > #### 谦辞(词)雅语
67 |
68 | * 头次见面——久仰
69 | * 很久不见——久违
70 | * 认识不清——眼拙
71 | * 向人致歉——失敬
72 | * 请人批评——指教
73 | * 请人指点——赐教
74 | * 请人原谅——见谅、包涵、海涵
75 | * 请人帮忙——劳驾
76 | * 请给方便——借光
77 | * 麻烦别人——打扰
78 | * 不知适宜——冒昧
79 | * 赞人见解——高见
80 | * 自己意见——拙见
81 | * 看望别人——拜访
82 | * 贵宾来临——莅临
83 | * 宾客来了——光临
84 | * 中途先走——失陪
85 | * 等待宾客——恭候
86 | * 迎接表歉——失迎
87 | * 请人别送——留步
88 | * 答人问候——托福
89 | * 表演技能——献丑
90 | * 别人赞扬——过奖
91 | * 向人祝贺——恭喜
92 | * 答人道贺——同喜
93 | * 请人担职——屈就
94 |
95 | > #### 四大人物
96 |
97 | * 四大美女:西施(沉鱼)、王昭君(落雁)、貂蝉(闭月)、杨玉环(羞花)
98 | * 江南四大才子:唐伯虎、祝枝山、文征明、徐祯卿
99 | * 四大名医:扁鹊(医祖)、华佗(医神)、李时珍(医圣)、张仲景(方祖)
100 | * 战国四大名将:秦:白起、王翦,赵:李牧、廉颇
101 | * 四大巾帼:花木兰、穆桂英、樊梨花、梁红玉
102 | * 四大判官:魏征、陆之道、钟馗、崔钰
103 |
104 |
105 | > #### 年龄
106 |
107 | * 初度:刚出生的男孩
108 | * 襁褓:不满周岁。
109 | * 孩提:两至三岁。
110 | * 髫年:女孩七岁。
111 | * 龆年:男孩八岁。
112 | * 始龀:女七男八(男孩八岁、女孩七岁换牙,脱去乳齿,长出恒牙)
113 | * 总角:幼年泛称。
114 | * 垂髻之年:指儿童。(古代小孩头发下垂,引申以指未成年的人。)
115 | * 黄口:十岁以下。
116 | * 幼学:十岁。(《礼记·曲礼上》“人生十年曰幼,学。”古代无标点,多用于男子)
117 | * 金钗之年:女孩十二岁。
118 | * 豆蔻年华:女子十三四岁。
119 | * 志学之年:男子十五岁。(《论语》:子曰:“吾十有五而志于学”)
120 | * 束发:男子十五岁
121 | * 及笄:女子十五岁。(《礼记·内则》:“女子十有五年而笄”)
122 | * 结发之年:女子十五岁
123 | * 碧玉年华:女子十六岁
124 | * 二八年华、破瓜之年:女子十六岁(古人拆“瓜”字为二八纪年,谓十六岁,多用于女子)
125 | * 弱冠:男子二十岁。(《礼记·曲礼上》:“二十曰弱冠。”)
126 | * 桃李年华:女子二十岁。
127 | * 花信年华:女子二十四岁。
128 | * 而立:男子三十岁。
129 | * 不惑:男子四十岁。
130 | * 强壮之年:男子四十
131 | * 天命、知命之年:五十岁。(《论语》:子曰:“吾十有五而志于学,三十而立,四十而不惑,五十而知天命,六十而耳顺,七十而从心所欲,不逾矩。“)
132 | * 知非之年:五十岁。(《淮南子·原道训》:“伯玉年五十,而有四十九年非。”说春秋卫国有个伯玉,不断反省自己,到五十岁时知道了以前四十九年中的错误,后世因而用“知非”代称五十岁。)
133 | * 耳顺(耳顺之年)、花甲之年:六十岁。(我国自古以来用天干地支互相错综相合纪年,可组成六十对干支,因而称作“六十干支”或“六十花甲子”,所以六十岁又称作“花甲之年”。)
134 | * 平头甲子、杖乡之年:六十岁
135 | * 古稀:七十岁。(杜甫《曲江二首》:“酒债寻常行处有,人生七十古来稀。”)
136 | * 杖国之年、致事之年、从心之年:七十岁
137 | * 耄耋(耄耋之年):八十、九十岁。(《礼记·曲礼》:“八十九十曰耄。”人们根据这解释,把耄耋两字连用代称八、九十岁。)
138 | * 鲐背之年:九十岁
139 | * 期颐(期颐之年)、人瑞:百岁之人。(《礼记·曲礼》:“百年曰期颐。”意思是人生以百年为期,所以称百岁为“期颐之年。”元人陈浩解释说:“人寿以百年为期,故曰期;饮食起居动人无不待于养,故曰颐。”)
140 |
141 | > #### 名胜古迹
142 |
143 | * 三山:安徽黄山、江西庐山、浙江雁荡山
144 | * 五岳:中岳河南嵩山、东岳山东泰山、西岳陕西华山、南岳湖南衡山、北岳山西恒山
145 | * 五岭:越城岭(湘桂)、都庞岭(湘桂)、萌渚岭(湘桂)、骑田岭(湘南)、大庾岭(赣粤,腹地在江西大庾县)
146 | * 五湖:江西鄱阳湖、湖南洞庭湖、江苏太湖、江苏洪泽湖、安徽巢湖
147 | * 四海:渤海、黄海、东海、南海
148 | * 四大名桥:广济桥、赵州桥、洛阳桥、卢沟桥
149 | * 四大名园:北京颐和园、承德避暑山庄、苏州拙政园、苏州留园
150 | * 四大名寺:山东常青灵岩寺、浙江天台国清寺、湖北江陵玉泉寺、江苏南京栖霞寺
151 | * 四大名楼:湖南岳阳岳阳楼、湖北武汉黄鹤楼、江西南昌滕王阁、云南昆明大观楼
152 | * 四大名亭:北京先农坛陶然亭、杭州西湖湖心亭、安徽滁县醉翁亭、湖南长沙爱晚亭
153 | * 四大古镇:江西景德镇、广东佛山镇、湖北汉口镇、河南朱仙镇
154 | * 四大名塔:嵩山寺塔(河南嵩山寺)、飞虹塔(山西洪洞广胜寺)、释迦塔(山西应县佛宫寺)、千寻塔(云南大理崇圣寺)
155 | * 四大道山:湖北武当山、江西龙虎山、安徽齐云山、四川青城山
156 | * 四大佛山:浙江普陀山(观音)、山西五台山(文殊)、四川峨眉山(普贤)、安徽九华山(地藏王)
157 | * 四大石窟:甘肃天水麦积山石窟、山西大同云冈石窟、甘肃敦煌莫高窟、河南洛阳龙门石窟
158 | * 四大书院:江西庐山白鹿洞书院、湖南长沙岳麓书院、河南嵩山嵩阳书院、河南商丘应天书院
159 |
160 | > #### 二十四节气
161 |
162 | * 春雨惊春清谷天
163 | * 立春:2月4日或5日
164 | * 雨水:2月19或20
165 | * 惊蛰:3月5日或6日
166 | * 春分:3月20或21
167 | * 清明:4月4日或5日
168 | * 谷雨:4月20或21
169 | * 夏满芒夏暑相连
170 | * 立夏:5月5日或6日
171 | * 小满:5月21或22
172 | * 芒种:6月5日或6日
173 | * 夏至:6月21或22
174 | * 小暑:7月5日或6日
175 | * 大暑:7月22或23
176 | * 秋处露秋寒霜降
177 | * 立秋:8月7日或8日
178 | * 处暑:8月23或24
179 | * 白露:9月7日或8日
180 | * 秋分:9月23或24
181 | * 寒露:10月8日或9日
182 | * 霜降:10月23或24
183 | * 冬雪雪冬小大寒
184 | * 立冬:11月7日或8日
185 | * 小雪:11月22或23
186 | * 大雪:12月7日或8日
187 | * 冬至:12月22或23
188 | * 小寒:1月5日或6日
189 | * 大寒:1月20或21
190 |
191 | > #### 历史顺口溜
192 |
193 | * 远古居民
194 |
195 | 一百七十万年前,云南元谋人出现;
196 | 会造工具能用火,因此称为类人猿;
197 | 北京人在周口店,手脚分工已明显;
198 | 群体劳动和生活,打制石器已出现;
199 | 保存火种用途广,原始社会已显现;
200 | 山顶洞人一出现,距今一万八千年;
201 | 磨光钻孔新技术,人工火种史无前;
202 | 血缘关系成氏族,没有贫富和贵贱。
203 |
204 | * 原始农耕生活
205 |
206 | 长江流域河姆渡,磨制石器有进步;
207 | 耒耜耕地种稻谷,干栏房子共居住;
208 | 简单玉器和乐器,挖井养畜陶器储;
209 | 黄河流域有半坡,地穴房子同居住;
210 | 粮食最早种植粟,副食鱼肉和果蔬;
211 | 早起文字出雏形,学会纺织及织布。
212 |
213 | * 华夏文明
214 |
215 | 人文初祖是黄帝,禅让制度尧舜禹;
216 | 禹建夏朝国家始,奴隶社会从此起;
217 | 启得王位传子孙,禅让从此变世袭;
218 | 夏朝经历四百七,暴君夏桀被商取;
219 | 商汤灭夏建立商,盘庚迁都到殷商;
220 | 武王伐纣灭掉商,西周定都镐京上;
221 | 分封制度定国策,天子统治有加强;
222 | 暴君厉王无人道,七七一年周灭亡。
223 |
224 | * 青铜文明
225 |
226 | 原始社会到末期,中国已有青铜器;
227 | 夏朝种类渐增多,商朝青铜灿烂器;
228 | 司母戊鼎造型巨,四羊方尊精工艺;
229 | 举世闻名三星堆,青铜立人有新意;
230 | 奴隶社会好悲惨,带着枷锁搞生产;
231 | 非人待遇好心酸,没有自由和饱暖;
232 | 生命犹如牛羊马,人祭人殉任屠杀。
233 |
234 | * 春秋战国
235 |
236 | 齐国君王齐桓公,任用丞相叫管仲;
237 | 尊王攘夷为口号,第一霸主逞威风;
238 | 第二霸主晋文公,城濮之战称英雄;
239 | 齐楚燕韩赵魏秦,战国七雄多战争;
240 | 齐王军师名孙膑,围魏救赵站桂陵;
241 | 战争发生二六零,秦赵之间战长平;
242 | 赵括纸上来谈兵,四十六天粮草穷;
243 | 赵军大败秦军胜,从此六国难抗衡。
244 |
245 | * 大变革
246 |
247 | 春秋出现铁农具,战国时期遍大地;
248 | 农业史上大革命,春秋末年用牛犁;
249 | 李冰修筑都江堰,消除水患灌农田;
250 | 治水功劳胜大禹,造福人民几千年;
251 | 孝公治国有心计,商鞅变法最有力;
252 | 承认私人有土地,奖励耕战免徭役;
253 | 废除贵族的权利,建立县制搞治理;
254 | 经济得到大发展,军队有了战斗力;
255 | 战国后期秦变强,商鞅变法了不起;
256 |
257 | * 秦王扫六合
258 |
259 | 二三零到二二一,秦灭六国始皇帝;
260 | 嬴政咸阳来登基,至高无上大权集;
261 | 丞相太尉和御史,地方推行郡县制;
262 | 为了思想大控制,焚书坑儒有得失;
263 | 北敌匈奴筑长城,开拓南疆修灵渠;
264 | 货币文字度量衡,方便交流要统一。
265 |
266 | * 中华文化
267 |
268 | 文字可考在商朝,甲骨文字算最早;
269 | 青铜器上刻金文,周晚大篆形成了;
270 | 古人观天很注意,日食月食书中记;
271 | 夏朝历法称夏历,战国二十四节气;
272 | 扁鹊最早称名医,起死回生了不起;
273 | 针刺汤药和按摩,望闻问切诊病疾;
274 | 楚国诗人有屈原,上了世界名人卷;
275 | 离骚抒情爱国篇,思想艺术传千年;
276 | 孔子相传为人圣,思想教育万年青;
277 | 主张爱人察民情,以德为政反酷刑;
278 | 坐下贤人七十二,办学收徒三千众,
279 | 言行收录论语中,儒家学派始创成,
280 | 主张温故而知新,因材施教出贤能;
281 | 老子道家创始人,学说记在道德经;
282 | 主张事物对立面,正反两面要理清;
283 | 百家争鸣的局面,墨儒道法还有兵;
284 | 墨家兼爱和非公,孟子治国说仁政;
285 | 道家庄子无为治,法家法治韩非子;
286 | 兵家鼻祖是孙武,孙子兵法论军事。
287 |
288 | > #### 拆迁顺口溜
289 |
290 | 房子一移,兰博基尼;
291 | 房子一扒,帕拉梅拉;
292 | 房子一动,揽胜运动;
293 | 拆字一盆,立提大奔;
294 | 房子不动,还骑电动;
295 | 不羡鸳鸯不羡仙,只羡房子画个圈;
296 | 拆字写在圆中间,从此快乐每一天。
297 |
298 |
299 |
300 |
301 |
--------------------------------------------------------------------------------