Reat Native ref 使用

State 状态的使用

在父控件中指定,整个生命周期讲不再改变
需求:一段闪烁的文字, Props 属性显示文字内容创建时初始化,State控制随时间变化是否显示,在父控件中

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
class Blink extends Component{
// 构造
constructor(props) {
super(props);
// 初始状态
this.state = {showWithText:true};
this.state = {}
setInterval(() => {
this.setState(previousState => {
return {showWithText: !previousState.showWithText}
});
}, 100);
}
render() {
let display= this.state.showWithText ? this.props.text : ' ';
return(
<Text>{display}</Text>
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
export default class App extends Component<Props> {
render() {
return(
<View style={styles.container}>
<Blink
text='I love to blink'
/>

<Blink
text='猜猜猜'
/>

<Blink
text='Blink is great'
/>
</View>
);
}
}

Props 属性的使用

1
2
3
4
5
6
7
8
9
// 定义一个组件
class Greeting extends Component {
render() {
return(
<Text> Hello {this.props.name}!
</Text>
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
export default class App extends Component<Props> {
render() {
return(
<View style={styles.container}>
<Image source={{uri:'https://upload.wikimedia.org/wikipedia/commons/d/de/Bananavarieties.jpg'}}
style={{width: 190, height: 110}}
/>
<Text style={styles.instructions}>
使用Props属性
</Text>
<View>
<Greeting name='React-Native'
/>
<Greeting name='iOS'
/>
<Greeting name='Swift'
/>
</View>

</View>
);
}
}

ref的使用

  • 可以理解为组件渲染后指向组件的一个应用,可以通过ref获取到真实的组件(类似指针?)

定义

1
ref='scrollView'

获取

1
2
let scrollView = this.refs.scrollView
let scrollView = this.refs['scrollView']
  • 可以通过ref访问组件的属性和方法

ES6 定时器

  • 开启定时器
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
let scrollView = this.refs.scrollView;
// 2.4timer 定时器的写法
this.timer = setInterval(
()=>{
var tempPage = 0;
// 修改banner索引
if ((this.state.currentPage+1) >= ImageData.data.length) {
tempPage = 0;
} else {
tempPage = this.state.currentPage+1;
}

// 更新状态
this.setState({
currentPage: tempPage
})

let offSet_x = width * tempPage
scrollView.scrollResponderScrollTo({x:offSet_x, y:0, animated: true})
},
this.state.duration
);
  • 暂停定时器
1
this.timer && clearInterval(this.timer)

js 学习

数据类型

1
2
3
4
5
6
7
8
var fullName;
// undefined

fullName
// undefined

fullName + 2
// NaN
  • 判断类型名称

    1
    2
    3
    4
    fullName = '张'
    "张"
    typeof(fullName)
    // "string"
1
2
3
4
var weight = 100;
undefined
typeof(weight)
// "number"
1
2
3
4
var firstName = '王', lastName = '张'
undefined
firstName + lastName
// "王张"
  • 类型不相同时转换后在拼接

    1
    2
    3
    4
    var weightIncrease = '2.5斤'
    undefined
    weight + weightIncrease
    // "1002.5斤"

数组

var array = [];
undefined
array.length
// 0
typeof(array)
// "object"
  • 增加元素

    1
    2
    3
    4
    array.push('1')
    // 4
    array
    // (4) ["ab", "cbd", "fcg", "1"]
  • 数组前面添加

1
2
3
4
array.unshift('0')
// 6
array
// (6) ["0", "ab", "cbd", "fcg", "1", Array(2)]
  • 删除最后元素

    1
    2
    3
    4
    array.pop() // 返回删除的元素
    // (2) ["2", "3"]
    array
    // (5) ["0", "ab", "cbd", "fcg", "1"]
  • 删除第一个元素

    1
    2
    3
    4
    5
    6
    	array.shift()
    // "0"
    array
    // (4) ["ab", "cbd", "fcg", "1"]
    ```
    - 删除指定的值,但数组元素没有被删

    delete array[2]
    // true
    array
    // (4) [“ab”, “cbd”, empty, “1”]

    1
    2
    	
    - 删除指定的元素

    array.splice(1)
    // (3) [“cbd”, empty, “1”]
    array
    // [“ab”]

    1
    2
    3
    4
    	
    ## 函数

    ### 调用调用

alertMessage();

function alertMessageWithParamter(message) {
alert(message)
}

alertMessageWithParamter(‘有参数的函数’)
alertMessageWithParamter(250)
alertMessageWithParamter(
console.log(‘test’)
)

1
### 函数表达式,使用函数声明的方式

var alertMessage_expression = function expression_alert (message) {
alert(message)
}

alertMessage_expression(‘匿名函数调用’)

expression_alert(‘函数表达式’)
`

Masonry使用

基本使用官网Demo非常详细,以下总结的是常见问题和技巧

安装遇到的问题

  • pod 安装后出现⚠️,项目运行报错

    1
    [UIView mas_makeConstraints:]: unrecognized selector sent to instance

    github

    解决方法

  • 使用lastBaseline属性crash

    解决办法

使用时注意点

  • edgesForExtendedLayout 方法

    重写此方法的目的是为了确定布局位置从什么位置开始什么位置结束,

    1
    2
    3
    - (UIRectEdge)edgesForExtendedLayout {
    return UIRectEdgeNone;
    }
**重写后**
![](https://ws1.sinaimg.cn/large/006tNc79ly1fsgcn3fmo0j30s61iyalk.jpg)

**重写前**
![](https://ws4.sinaimg.cn/large/006tNc79ly1fsgcokvpdwj30s61iy7eq.jpg)
  • translucent 设置UINavigationBar是否半透明, 如果设置了导航栏的styleUIBarStyleBlackTranslucent 就为true

    设置为false不透明效果

  • extendedLayoutIncludesOpaqueBars 导航栏不透明条件下是否可以扩展,默认是NO不可以扩展

    1
    2
    self.navigationController?.navigationBar.isTranslucent = false
    self.extendedLayoutIncludesOpaqueBars = true
**设置不透明,设置可以扩展此时从坐标的(0,0)点开始布局**
![](https://ws2.sinaimg.cn/large/006tNc79ly1fsggem13mjj30ow0j83zy.jpg)    
  • inset 的使用,当约束控件的属性相同时不用再考虑正负值的问题,例如要约束一个控件左边距离另一控件的右边位置时还需要使用负值情况

    1
    2
    3
    4
    5
    6
    7
    [yellowdView makeConstraints:^(MASConstraintMaker *make) {
    make.height.equalTo(@150);
    make.top.equalTo(self).inset(220);
    make.leading.equalTo(self).inset(10);
    make.trailing.equalTo(greenView.leading).inset(10);
    make.width.equalTo(greenView);
    }];
  • edges的使用,约束边距更方便

    1
    2
    3
    [edgeView remakeConstraints:^(MASConstraintMaker *make) {
    make.edges.equalTo(lasView).insets(UIEdgeInsetsMake(10, 5, 5, 5));
    }];
  • Priority 设置约束的优先级

    • priorityHigh
    • priorityMedium
    • priorityLow
  • makeConstraintsupdateConstraintsremakeConstraints三者区别

    • makeConstraints 添加约束
    • updateConstraints 更新约束,更新之前会查找一边控件已经存在的约束,没有就添加,有就更新到最新的约束
    • remakeConstraints删除控件以前的所有约束重新添加约束
  • 设置控件或者某一约束的’key’ 方便冲突时⚠️查找

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    	greenView.mas_key = @"greenView";
    [greenView makeConstraints:^(MASConstraintMaker *make) {
    make.height.equalTo(yellowdView).key(@"greenView-height");
    make.top.equalTo(yellowdView).key(@"greenView-top");
    make.width.equalTo(yellowdView).key(@"greenView-width");
    make.trailing.equalTo(self).inset(10).key(@"greenView-trailing");
    // 冲突约束
    // make.leading.equalTo(greenView.trailing).inset(10).key(@"greenView-leading");
    }];
    ```

    - 使用 `MASAttachKeys`批量给`view`设置key

    MASAttachKeys(greenView, yellowdView);

    1
    2
    3
    4
    	
    ![](https://ws3.sinaimg.cn/large/006tNc79ly1fsgalvd4l6j31a20modnp.jpg)

    - `dividedBy`和 `multipliedBy` 约束宽高比

    [topInnerView makeConstraints:^(MASConstraintMaker *make) {

    // 设置自己的宽高比是3:1
    make.width.equalTo( topInnerView.height).multipliedBy(3); // 乘因数
    
    // 设置宽高并且设置他们的优先级最低
    make.width.height.lessThanOrEqualTo(topView);
    make.width.height.equalTo(topView).priorityLow();
    
    // 设置位置
    make.top.equalTo(topView);
    

    }];

    1
    - 多个控件批量约束

    NSValue sizeValue = [NSValue valueWithCGSize:CGSizeMake(100, 100)];
    [@[blueView, redView, yellowView] makeConstraints:^(MASConstraintMaker
    make) {

    make.size.equalTo(sizeValue);
    

    }];

    [@[blueView, redView, yellowView] mas_makeConstraints:^(MASConstraintMaker *make) {

    make.top.equalTo(self).inset(20);
    

    }];

    [blueView makeConstraints:^(MASConstraintMaker *make) {

    make.left.equalTo(self).inset(20);
    

    }];

    [redView makeConstraints:^(MASConstraintMaker *make) {

    make.left.equalTo(blueView.right).inset(10);
    

    }];

    [yellowView makeConstraints:^(MASConstraintMaker *make) {

    make.left.equalTo(redView.right).inset(10);
    

    }];

    1
    2
    3
    4

    ![批量约束](https://ws1.sinaimg.cn/large/006tNc79ly1fsgaz670hvj30s61iyn2l.jpg)

    **以上代码也可以简化为**

    [redView makeConstraints:^(MASConstraintMaker *make) {

    make.left.equalTo(blueView.right).inset(10);
    

    }];

    [yellowView makeConstraints:^(MASConstraintMaker *make) {

    make.left.equalTo(redView.right).inset(10);
    

    }];

[blueView makeConstraints:^(MASConstraintMaker *make) {
    make.top.left.equalTo(self);
    make.size.equalTo(@[redView, yellowView, sizeValue]);
}];

1
2
3
4
5
	![](https://ws2.sinaimg.cn/large/006tNc79ly1fsgbhz8lw5j30s61iyte5.jpg)

## Snapkit 使用

- Swift 中`edgesForExtendedLayout:UIRectEdge` 扩展布局的边缘是一个属性,默认是`All`
self.edgesForExtendedLayout = []
1
2
3
4

在Swift中闭包参数可以使用$0、$1、$2 一次代表第一个,第二个,第三个参数

- 使用$0 来代替闭包参数
nullDataImageView.snp.makeConstraints { $0.top.equalTo(view).offset(44) $0.centerX.equalTo(view) $0.width.height.equalTo(200) }
1
2
3
4
5
6
7
	
- `deactivate` 和 `activate` 使用

- `activate` 激活指定的约束
- `deactivate` 移除指定的约束

添加约束
nullDataImageView.snp.makeConstraints { nullDataViewTopConstraint = $0.top.equalTo(view).offset(80).constraint nullDataViewLeftConstraint = $0.left.equalTo(view).inset(10).constraint $0.width.height.equalTo(200) }
1
2

移除对应约束,设置约束再激活约束
nullDataViewLeftConstraint?.deactivate() nullDataViewLeftConstraint?.update(inset: 100) nullDataViewLeftConstraint?.activate() UIView.animate(withDuration: 1.5) { self.view.layoutIfNeeded() }
1
2
3
4

- 更新约束

- 添加约束
nullDataImageView.snp.makeConstraints { nullDataViewTopConstraint = $0.top.equalTo(view).offset(64).constraint $0.centerX.equalTo(view) $0.width.height.equalTo(200) }
1
2

- 更新约束
nullDataViewTopConstraint?.update(inset: 84) UIView.animate(withDuration: 0.5, delay: 0, options: .curveEaseOut, animations: { self.view.layoutIfNeeded() }) { (finished) in print("动画执行完毕") }
1
2
	
- 添加`debug`模式中的 `key`使用`labeled()`方法
nullDataImageView.snp.makeConstraints { nullDataViewTopConstraint = $0.top.equalTo(view).offset(80).constraint nullDataViewLeftConstraint = $0.left.equalTo(view).inset(10).constraint $0.width.height.equalTo(200).labeled("width和height约束") } ```
  • 其他注意点都和Masnory相同

JS ES6 语法

1. let var 变量,作用域

var a = 10;

if (a > 10) {
    let b = 5; // let 只能在代码块内被访问

    console.log(b);
}

// 访问 b 报错
console.log(b);
console.log(a);

2. const 只能分配一次值

{
const const_a = 1;
console.log(const_a)

// 报错
const_a = 2;

// 声明一个常量数组
const const_array = [];
const_array.push(1);
const_array.push(2);
// 再次赋值时会报错
const_array = [3];

}

3. 解构语法

{
// 1.解构数组
function getArray() {
return [10, 20, 30];
}

let [a,b,c] = getArray()
console.log(a, b, c)


// 函数返回一个对象
function getObj() {
    return {dessert: '面包', drink: '水', play: 'Game'};
}

// 2.解构对象
let {des: dessert,  dri: drink, pla: play} = getObj()
console.log(des, dri, pla);

}

4. 模版字符串

{
let name = ‘姓名:’, password = ‘密码:’
let str_4 = name + ‘李老师’ + ‘—-‘ + password + ‘北京太热。。。’
console.log(str_4)

// 使用 `${}` 包裹会生成字符串
let str_41 = `${name}李老师----${password}北京太热`
console.log(str_41)

// 多行显示时直接回车换行
let str_42 = `${name}李老师
----
${password}北京太热`
console.log(str_42)

}

5. 带标签的模版字符串

{
let name = ‘姓名:’, password = ‘密码:’
// 多行显示时直接回车换行
let str_5 = strTest${name}李老师 ---- ${password}北京太热
console.log(str_5)

// strings 字符中包含的被插值分割的子字符串已数组形式展现
// values 字符串中的插值数组
function strTest(strings, ...values) {
    console.log(strings)
    console.log(values)
}

function strTest1(strings, ...values) {
    let result = '';
    for (let i = 0; i < values.length; i++) {
        result += strings[i]
        result += values[i]
    }
    return result
}

}

6. 判断字符串是否包含其他字符

{
let name = ‘姓名:’, password = ‘密码:’
let str_6 = ${name}李老师---${password}北京真热
console.log(str_6.startsWith(${name}))
console.log(str_6.endsWith(${name}))
console.log(str_6.includes(‘李老师’))
}

7. 函数默认参数

{
function funcDefaultParame(param1 = ‘a’, param2 = ‘b’, param3 = ‘c’) {
return ${param1}--${param2}--${param3}
}
console.log(funcDefaultParame(1, 2,3))
}

8. “…”展开操作符

{
let a = [1,2,3];
console.log(a);
console.log(…a)

let b = [...a, 4, 5];
console.log(a);
console.log(b)

}

9. ‘… ‘剩余操作符, 一般用在函数参数, 可以看作是一个可以展开的参数

//  ... param3表示函数可以接收除了param1, param2,两个参数外,多个参数,都会放在param3中
function operator(param1, param2, ...param3) {
    console.log(param1, param2, param3)
}
operator('a','b','c','d','e','f','g')

10. 解构对象解构函数

// 当函数参数是对象是可以按照对象解构
function getObjcValue(param1, param2, {value1, value2} = {}) {
    console.log(param1, param2, value1, value2)
}

getObjcValue(1,2,{value1: -3,value2: -4})

11. 获取函数名称

function getObjcValue(param1, param2, {value1, value2} = {}) {
    console.log(param1, param2, value1, value2)
}
console.log(getObjcValue.name)

let funName = function getfunctionName() {  }
console.log(funName.name)

12. 箭头函数

// 原来普通写法
var funType = function arrowfunction(param) {
    return param
}

// 函数参数 => 函数返回值
// '=>' 的左边表示箭头函数的参数,多个时表示为 (param1, param2, param3)
// '=>' 的右边表示箭头函数的返回值,如果返回值是一个对象时用 { } 表示
let arrowFunction = (param1, param2) => {
    return `${param1}${param2}`

}

13

flutter 常用组件

组件

  • StatefulWidget
    • 具有可变状态的窗口部件,使用应用时可随时变化,例如进度条
  • StatelessWidget
    • 不可变窗口部件

Text 组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
//  Text 组件
class MyText extends StatelessWidget{
@override
Widget build(BuildContext context){
return Text('reacctNative、 flutter 学习之路是非常坚信不疑的,作为一个程序员,因该对于技术有着追求,不断的提高自己才是王道,可是道理都懂依然过不好这一生',
maxLines: 2,
overflow: TextOverflow.fade,
textAlign: TextAlign.center,
style: TextStyle(
fontSize: 20.0,
color: Colors.deepOrange,
decoration: TextDecoration.underline,
decorationColor: Colors.redAccent,
decorationStyle: TextDecorationStyle.dotted
),
);
}
}

COntainer 组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28

// Container容器组件
class MyContainer extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
child: Text('Container 容器中有文字',
style: TextStyle(
backgroundColor: Colors.cyan,
),
),
alignment: Alignment.center, // 容器中内容对其方式
width: 300.0,
height: 200.0,
padding: const EdgeInsets.all(10), // 容器内边距
margin: const EdgeInsets.fromLTRB(10, 5, 10, 5), // container 和外部控件的边距
decoration: new BoxDecoration(
gradient: const LinearGradient(
colors: [Colors.lightBlue, Colors.greenAccent, Colors.yellow]
),

// 设置 border 的宽度
border: Border.all(width: 5, color: Colors.black)

),
);
}
}

Image 组件

fit属性

  • BoxFit.fill:全图显示,图片会被拉伸,并充满父容器。
  • BoxFit.contain:全图显示,显示原比例,可能会有空隙。
  • BoxFit.cover:显示可能拉伸,可能裁切,充满(图片要充满整个容器,还不变形)。
  • BoxFit.fitWidth:宽度充满(横向充满),显示可能拉伸,可能裁切。
  • BoxFit.fitHeight :高度充满(竖向充满),显示可能拉伸,可能裁切。
  • BoxFit.scaleDown:效果和contain差不多,但是此属性不允许显示超过源图片大小,可小不可大。

图片的混合模式

  • color:是要混合的颜色,如果你只设置color是没有意义的。
  • colorBlendMode: 是混合模式。

repeat 图片填充模式

  • ImageRepeat.repeat : 横向和纵向都进行重复,直到铺满整个画布。
  • ImageRepeat.repeatX: 横向重复,纵向不重复。
  • ImageRepeat.repeatY:纵向重复,横向不重复
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
class MyImage extends StatelessWidget {
@override
Widget build(BuildContext context){
return Container(
child: new Image.network(
// 'https://images.xiaozhuanlan.com/photo/2019/28ed76123023e46483fcf0ae5c2ba11b.png',
'https://p.ampmake.com/mall/product/9666f00e-f02a-46ce-9b7c-090bf6aba9aa.png',

// 1. 设置填充模式
// fit: BoxFit.scaleDown,
// fit: BoxFit.none,
// fit: BoxFit.fill,
// fit: BoxFit.fitHeight,
// fit: BoxFit.fitWidth,

// 保持原图比例
// fit: BoxFit.contain,

// 充满整个容器,图片被裁切
// fit: BoxFit.cover,
// scale: 1.0,

// 2. 图片混合
color: Colors.red,
colorBlendMode: BlendMode.overlay,

// 3. reap
repeat: ImageRepeat.repeat,
),
width: 300.0,
height: 200.0,
color: Colors.lightBlue,
);
}
}

ListView 列表组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class MyListView extends StatelessWidget{
@override
Widget build(BuildContext contex){

return ListView(
children: <Widget>[
new ListTile(
leading: new Icon(Icons.camera),
title: Text('相册'),
),

new ListTile(
leading: new Icon(Icons.camera_alt),
title: Text('相机'),
),

new ListTile(
leading: new Icon(Icons.camera_enhance),
title: Text('相机1'),
),

new ListTile(
leading: new Icon(Icons.camera_front),
title: Text('相机2'),
),

new ListTile(
leading: new Icon(Icons.camera_rear),
title: Text('相机3'),
),
],
);
}
}

ListView.builder 适合列表项比较多(或者无限)的情况

1
2
3
4
5
6
7
8
9
10
11
12
13
class MyListViewBuilder extends StatelessWidget {

@override
Widget build(BuildContext context){
return ListView.builder(
itemCount: 100, // 数量
itemExtent: 40, // Tile 高度
itemBuilder: (BuildContext context, int index){
return ListTile(title: Text("$index"));
}
);
}
}

横向列表

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
class MyHorizontalListView extends StatelessWidget {
@override
Widget build(BuildContext context) {
return Container(
height: 100,
child: ListView(
// 设置滚动方式
scrollDirection: Axis.horizontal,
children: <Widget>[
new Container(
width: 180.0,
color: Colors.green,
),
new Container(
width: 180.0,
color: Colors.yellow,
),
new Container(
width: 180.0,
color: Colors.blue,
),
new Container(
width: 180.0,
color: Colors.cyan,
),
new Container(
width: 180.0,
color: Colors.purple,
),
],
),
);
}
}

动态列表和构造方法的创建

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class MyDynamicListView extends StatelessWidget {
// 声明参数
final List<String> items;
// 构造方法
MyDynamicListView({Key key, @required this.items}):super(key:key);
@override
Widget build(BuildContext context) {
return Container(
child: new ListView.builder(
itemCount: items.length,
itemBuilder: (context, index){
return ListTile(
title: new Text('通过构造方法创建的动态列表${items[index]}'),
);
},
),
);
}
}

GridView 网格列表的使用

GCD信号量用法

对于异步网络请求相互依赖问题一般用三种方式解决:

  • 网络请求嵌套
  • 使用 BlockOperation
  • GCD DispatchGroup
  • GCD semaphore(信号量)

GCD 信号量

  • semaphore 值 <= 0 阻塞
  • semaphore semaphore.signal() 使信号量值增加
  • semaphore.wait() 等待,可设置时长

request – 3 依赖 request – 1 和 request – 2,1 和 2 无需关注顺序

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private func gcdSemaphore() {
let semaphore = DispatchSemaphore(value: 0)
DispatchQueue.global().async {
for i in 0...300 {
print("request -- 1")
}
semaphore.signal()
}

DispatchQueue.global().async {
for i in 0...200 {
print("request -- 2")
}
semaphore.signal()
}


DispatchQueue.global().async {
semaphore.wait()
semaphore.wait()
for i in 0...160 {
print("request -- 3")
}
}
}

request – 3 ,request – 2 和 request – 1,依次相互依赖

private func gcdSemaphore() {
        let semaphore = DispatchSemaphore(value: 0)
        DispatchQueue.global().async {
            for i in 0...300 {
                print("request -- 1")
            }
            semaphore.signal()
        }

        DispatchQueue.global().async {
            semaphore.wait()
            for i in 0...200 {
                print("request -- 2")
            }
            semaphore.signal()
        }


        DispatchQueue.global().async {
            semaphore.wait()
            for i in 0...160 {
                print("request -- 3")
            }
        }
    }

Charles 抓包

原理

简单理解如下:

  • 正常请求

    客户端 ——> 服务器

  • Charles 抓包

    客户端 ——> 代理 (Charles)——> 服务器

安装

Charles官网

破解版本请自行百度

重要说明安装之前请暂时关闭电脑的VPN

重要说明安装之前请暂时关闭电脑的VPN

重要说明安装之前请暂时关闭电脑的VPN

启动Charles

安装Charles证书

如果安装失败,请检查以前是否已经安装过,如果已经安装过并且已经失效,请删除失效证书后再安装

打开钥匙串–> 选择Charles CA -> 双击证书 –> 信任证书

设置 https

- Proxy -> SSL Proxying Settings -> SSL Proxying -> Add
- Host: * 为需要过滤的域名地址,
- *: 表示不过滤Port, 固定为443 `*`表示任意端口

Mac 抓包

  • Proxy -> macOS Proxy (☑️)

真机抓包

此时可以将 macOS Proxy 选项中的 ✅ 去掉,

Mac与iPhone连接必须同一网络

设置代理端口号

手机安装证书

  • 安装手机证书

  • 安装完成后弹窗

  • 查看mac 地址,为手机设置代理

    1. 根据安装手机证书后的弹窗显示IP配置

    2. Charles –> Help –> Loca IP Address

    3. 打开电脑网络设置查看

  • 设置代理

    第一步

    第二步

    第三步

  • 根据弹窗提示,在手机浏览器下载并安装证书

  • 手机信任证书

    • 设置 –> 通用 –> 关于本机 –> 证书信任设置

模拟器抓包

  • 安装模拟器证书

  • 勾选 macOS Proxy 选项

如果失败,请先关闭模拟器,重新启动Charles 再打开模拟器

使用浏览器打开网页提示不是私密链接

解决办法

Flutter 入门.md

flutter安装

flutter入门

flutter 安装

flutter 项目代码

fluter 中一切皆是组件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
// 导入头文件
import 'package:flutter/material.dart';

// 程序的入口,main 函数
void main() => (MyApp());

// 定义类, 继承

class MyApp extends StatelessWidget {
// 重写
@override

Widget build(BuildContext context) {

// 返回一窗口
return MaterialApp(
title:'Flutter',
home: Scaffold(
appBar: AppBar(
title: Text('flutter 初体验')
),

body: Center(
child: Text('flutter 学习之路'),
),
),
);
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
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
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

import 'package:flutter/material.dart';

void main() => runApp(MyApp());

class MyApp extends StatelessWidget {
// This widget is the root of your application.
@override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
theme: ThemeData(
// This is the theme of your application.
//
// Try running your application with "flutter run". You'll see the
// application has a blue toolbar. Then, without quitting the app, try
// changing the primarySwatch below to Colors.green and then invoke
// "hot reload" (press "r" in the console where you ran "flutter run",
// or simply save your changes to "hot reload" in a Flutter IDE).
// Notice that the counter didn't reset back to zero; the application
// is not restarted.
primarySwatch: Colors.blue,
),
home: MyHomePage(title: 'Flutter Demo Home Page'),
);
}
}

class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);

// This widget is the home page of your application. It is stateful, meaning
// that it has a State object (defined below) that contains fields that affect
// how it looks.

// This class is the configuration for the state. It holds the values (in this
// case the title) provided by the parent (in this case the App widget) and
// used by the build method of the State. Fields in a Widget subclass are
// always marked "final".

final String title;

@override
_MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
int _counter = 0;

void _incrementCounter() {
setState(() {
// This call to setState tells the Flutter framework that something has
// changed in this State, which causes it to rerun the build method below
// so that the display can reflect the updated values. If we changed
// _counter without calling setState(), then the build method would not be
// called again, and so nothing would appear to happen.
_counter++;
});
}

@override
Widget build(BuildContext context) {
// This method is rerun every time setState is called, for instance as done
// by the _incrementCounter method above.
//
// The Flutter framework has been optimized to make rerunning build methods
// fast, so that you can just rebuild anything that needs updating rather
// than having to individually change instances of widgets.
return Scaffold(
appBar: AppBar(
// Here we take the value from the MyHomePage object that was created by
// the App.build method, and use it to set our appbar title.
title: Text(widget.title),
),
body: Center(
// Center is a layout widget. It takes a single child and positions it
// in the middle of the parent.
child: Column(
// Column is also layout widget. It takes a list of children and
// arranges them vertically. By default, it sizes itself to fit its
// children horizontally, and tries to be as tall as its parent.
//
// Invoke "debug painting" (press "p" in the console, choose the
// "Toggle Debug Paint" action from the Flutter Inspector in Android
// Studio, or the "Toggle Debug Paint" command in Visual Studio Code)
// to see the wireframe for each widget.
//
// Column has various properties to control how it sizes itself and
// how it positions its children. Here we use mainAxisAlignment to
// center the children vertically; the main axis here is the vertical
// axis because Columns are vertical (the cross axis would be
// horizontal).
mainAxisAlignment: MainAxisAlignment.center,
children: <Widget>[
Text(
'你可以点击按钮来修改文字,我是热重载的结果',
),
Text(
'$_counter',
style: Theme.of(context).textTheme.display1,
),
],
),
),
floatingActionButton: FloatingActionButton(
onPressed: _incrementCounter,
tooltip: 'Increment',
child: Icon(Icons.add),
), // This trailing comma makes auto-formatting nicer for build methods.
);
}
}

Mac安装VirtualBox连接U盘

最近因为某些原因需要再Mac上安装虚拟机,所以选择了VirtualBox安装了
win10系统,但是需要再虚拟机的win10中访问U盘数据,遇到的问题是不能连接并且读取到U盘,错误提示不能分配USB内存。。。

网上找了好多办法都胡扯,根本没有解决…

解决方法:
1.升级VirtualBox到最新版
2.关闭当前的虚拟机中的操作系统
3.安装增强工具
4.重启VirtualBox,回到Mac桌面推出U盘即可

最重要的就是在第四步