0%

The terms parameter and argument are used interchangeably by vast majority of programmers but they both have different meanings. In this post, we will see the difference between an argument and a parameter.

Although parameters are commonly referred to as arguments, but both are very different. According to wikipedia, a parameter is a special kind of variable, used in a subroutine to refer to one of the pieces of data provided as input to the subroutine. These pieces of data are the values of the arguments with which the subroutine is going to be called/invoked.

In simpler terms, the argument the actual value that is supplied to a function whereas the parameter is the variable inside the definition of the function. We can say that a parameter is a type that appear in function definitions, while an argument is an instance that appear in function calls.

For example, consider the following function definition:

int add (int x, int y) {
return x + y;
}

The add() function takes two parameters x and y. If the function is called as add(2, 3), then 2, 3 are the arguments.

It is worth noting that variables can be arguments. If the function is called as shown below, then the variables a and b are both arguments to the add() function, and not the values 2, 3.

int a = 3;
int b = 2;
add (a,b);

Important Points:

  1. A parameter is also called as formal parameter or formal argument and an argument is often called as actual arguments or actual parameters.
  2. A parameter is optional in some programming langauges and some programming languages allows for a default argument to be provided in a function’s declaration. This means that while calling the function, the caller can omit that argument.
  3. A parameter has a name, a data type, and calling mechanism (call by reference, or call by value), whereas an argument is an expression which do not have any name, but it can be a variable, a constant, or a literal.
  4. The scope of a parameter is the function itself and it serves as a local variable inside the function.
  5. The number of arguments in a function call should match with the number of parameters in the function definition. One exception to this rule is functions with variable-length parameter lists.
  6. The data type of arguments in a function call should match with the data type of parameters in the function definition.
  7. If a parameter is passed by value, modifying it inside the function does not change the corresponding argument in the caller. However, if it is passed by reference, the values of corresponding argument can be chnaged in the caller.

Flutter install guide for Mac

intrudution

Flutter是谷歌的移动UI框架,可以快速在iOS和Android上构建高质量的原生用户界面。
Flutter可以与现有的代码一起工作。
在全世界,Flutter正在被越来越多的开发者和组织使用,并且Flutter是完全免费、开源的。

Using Flutter in China

  • Configuring Flutter to use a mirror site

    export PUB_HOSTED_URL=https://pub.flutter-io.cn
    export FLUTTER_STORAGE_BASE_URL=https://storage.flutter-io.cn
    git clone -b dev https://github.com/flutter/flutter.git
    export PATH="$PWD/flutter/bin:$PATH"
    cd ./flutter
    flutter doctor
  • Configuring iOS toolchain

    brew update
    brew install --HEAD usbmuxd
    brew link usbmuxd
    brew install --HEAD libimobiledevice
    brew install ideviceinstaller
  • Configuring Android toolchain

    [✗] Android toolchain - develop for Android devices✗ Unable to locate Android SDK.Install Android Studio from:https://developer.android.com/studio/index.html On first launch it will assist you in installing the Android SDK components.(or visit https://flutter.io/setup/#android-setup for detailed instructions).If Android SDK has been installed to a custom location, set $ANDROID_HOME to that location.

    resolve :

    * download android studio at https://developer.android.com/studio/index.html
    * installed
    * Configuring android SDK (best 27)
    * set ANDROID_HOME in .bash_profile :

    export ANDROID_HOME=/Users/your_name/Library/Android/sdk
    export PATH=${PATH}:${ANDROID_HOME}/tools
    export PATH=${PATH}:${ANDROID_HOME}/platform-tools

    * download flutter plugin and dart plugin
Read more »

JavaScript syntax introduction:

  1. mode : 'use strict' (严格模式)

  2. 打印 : console.log()

  3. 比较运算符 : ===

  4. NaN : not a number, 判断NaN的方法通过 isNaN()函数

  5. null 和 undefined : null 表示“空”的值, undefined 表示值未定义,仅仅在判断函数参数是否传递的情况下有用

  6. for ... in 循环:

    var o = {
    name: 'Jack',
    age: 20,
    city: 'Beijing'
    };
    for (var key in o) {
    console.log(key); // 'name', 'age', 'city'
    }
  7. 对象 :由一组键-值组成的无序集合,用{}表示, 其中 必须是字符串

    var person = {
    name: 'Bob',
    age: 20,
    tags:['js', 'web', 'mobile'],
    city: 'beijing',
    hasCar: true,
    zipcode: null
    }

    person.age = 18;
    delete person.school; //删除一个不存在的school属性也不会报错
    delete person.zipcode;//删除zipcode属性
    person.school = 'qinghua'; //新增一个school属性

    'toString' in person; // true;
    //因为toString定义在object对象中,而所有对象最终都会在原型链上指向object,所以person也拥有toString属性

    hasOwnProperty(); //判断一个属性是否是xiaoming自身拥有的,而不是继承得到的
Read more »

对称加密 和 非对称加密:

  • 对称加密加密与解密使用的是同样的密钥,所以速度快,但由于需要将密钥在网络传输,所以安全性不高。

    对称加密算法 AES 128位 192位 256位

    密钥管理比较难,不适合互联网,一般用于内部系统

    快好几个数量级(软件加解密速度至少快100倍,每秒可以加解密数M比特数据),适合大数据量的加解密处理

  • 非对称加密使用了一对密钥,公钥与私钥,所以安全性高,但加密与解密速度慢。

    非对称加密算法 RSA, ECC

    密钥容易管理

    慢,适合小数据量加解密或数据签名

  • 解决的办法是将对称加密的密钥使用非对称加密的公钥进行加密,然后发送出去,接收方使用私钥进行解密得到对称加密的密钥,然后双方可以使用对称加密来进行沟通。

为系统而生,为框架而死,为debug奋斗一辈子; 吃符号的亏,上大小写的当,最后死在需求上。


客户端在使用HTTPS方式与Web服务器通信时有以下几个步骤:

  • (1) 客户使用https的URL访问Web服务器,要求与Web服务器建立SSL连接。

  • (2) Web服务器收到客户端请求后,会将网站的证书信息(证书中包含公钥)传送一份给客户端。

  • (3) 客户端的浏览器与Web服务器开始协商SSL连接的安全等级,也就是信息加密的等级。

  • (4) 客户端的浏览器根据双方同意的安全等级,建立会话密钥,然后利用网站的公钥将会话密钥加密,并传送给网站。

  • (5) Web服务器利用自己的私钥解密出会话密钥。

  • (6) Web服务器利用会话密钥加密与客户端之间的通信。


    Read more »

Private Pods

1.Create a Private Spec Repo (创建私有 Spec 仓库)

例子: 在 Coding 上新建项目 CCSpecs,
私有Spec仓库地址https://git.coding.net/colorface/CCSpecs.git

2.Add your Private Repo to your CocoaPods installation

  • 拉取 Pod 仓库到本地:
$ pod repo add REPO_NAME SOURCE_URL
  • To check if your installation is successful and ready to go:

    $ cd ~/.cocoapods/repos/REPO_NAME
    $ pod repo lint .

3.创建私有 Pod 工程文件

  • 在 Coding 上新建项目用于存放私有 Pod 工程源码,本地创建工程文件,添加至 git 管理并 push 到远端仓库。

    • 在工程根目录下执行命令,建立本地工程和远程仓库的关联
    $ git remote add origin SOURCE_URL
    • 本地工程push到远程仓库
    $ git add .
    $ git commit -m "修改信息"
    $ git push -u origin master

    # 组件化开发时,我们希望某些基础模块的内容是稳定的,不会经常变更。
    # 基础模块开发稳定后需要打 tag,保证主工程的开发过程中不会因为子工程的变更而变化。
    # 这里我们在工程上打 tag 并 push 到远程仓库。

    $ git tag 0.0.1
    $ git push --tags

4. 创建私有 Pod 的 podspec

  • 在工程的根目录下执行:
$ pod spec create xxx
:xxx为工程名,创建成功后会在根目录下创建 xxx.podspec 文件
  • 根据实际情况配置podspec文件

根据实际情况配置

  • 验证 podspec 文件有效性:

    $ pod lib lint

    $ pod spec lint

    # 都验证通过后,podspec 文件配置成功。
    # 可选参数 --verbose --allow-warnings
  • 提交 podspec 至私有 Spec 仓库

    $ pod repo push REPO_NAME SPEC_NAME.podspec

Your private Pod is ready to be used in a Podfile. You can use the spec repository with the source directive in your Podfile as shown in the following example:

source 'URL_TO_REPOSITORY'

Effective Objective 2.0

(编写高质量iOS与OS X代码的52个有效方法)

1. runtime :

  • 消息机制
  • 消息转发

2. 在类的头文件中尽量少引入其他头文件

  • 减少编译时间,降低耦合
  • 使用import而非include指令不会导致循环引用,但两个类里有一个无法被正确编译,建议使用@class 向前声明
  • 有些协议,例如委托协议(delegate protocol)不用单独写一个头文件
  • 协议单独写.h.m文件,或者在委托协议里声明协议,
  • 一般遵循协议,建议写在扩展分类后边(代理对象的扩展分类),向外界隐藏实现

3. 多用字面量语法,少用与之等价的方法

  • 字面量语法创建数组或者字典时,若值中有nil,则会抛出异常

4. 多用类型常量,少用#define预处理指令

  • 不要用预处理指令代替常量,不含类型信息,并且不安全

    static const NSTimeinterval kAnimationDuration = 0.3; 代替

    _#define ANIMATION_DURATION 0.3

  • OC 没有“名称空间”(namespace)这一概念

  • 若常量局限于实现文件之内,则在前面加字母k,若常量在类之外可见,则通常以类名为前缀

  • 定义常量的位置很重要。

  • 在头文件中使用extern来声明全局常量,并在相关实现文件中定义其值,这种常量为全局常量,会出现在全局符号表中,其名称应添加类名前缀
    也可以单独定义.h.m文件用来声明所有的全局常量。

5. 用枚举表示状态、选项、状态码

  • << 左移运算符

  • 宏为完全替代操作

    _#define NS_ENUM(_type, _name) enum _name : _type _name; enum _name : _type

    typedef enum EOCConnectionState : NSUInteger EOCConnectionState;

    enum EOCConnectionState : NSUInterger {

    };

Read more »

任务和队列

任务:

  • block中代码;
  • 执行任务两种方式:同步执行(sync)和 异步执行(async);
  • 同步异步区别:
    • 是否等待队列的任务执行结束
    • 是否具备开启新线程的能力

队列:

  • 一种特殊的线性表,遵循先进先出(FIFO)原则

  • 两种队列:串行队列并发队列

  • 串行并发区别:

    • 执行顺序不同
    • 开启线程数不同
  • 系统提供的串行队列:主队列 (Main Dispatch Queue)

    所有放到主队列中的任务,都会放在主线程执行
    dispatch_get_main_queue();

  • 系统提供的并发队列:全局并发队列 (Global DisPatch Queue)

    dispatch_get_global_queue(优先级,0);
    优先级:high、default、low、background;

Read more »

performSelector调用和直接调用的区别:

[self method];//直接调用
[self performSelector:@selector(method) withObject:nil];
  • performSelector是运行时系统负责去找方法的,在编译时不做任何校验(编译器没任何提示),如果方法不存在运行时程序崩溃;直接调用编译是会自动校验的,方法不存在时编译时候就能够发现(Xcode有提示)。

Cocoa支持在运行时向某个类添加方法,即方法编译时不存在,但是运行时候存在,这时候必然需要使用performSelector去调用。所以有时候如果使用了performSelector,为了程序的健壮性,会使用检查方法
- (BOOL)respondsToSelector:(SEL)aSelector;

  • 直接调用方法时,一定要在头文件中声明该方法的使用,也要将头文件import进来。而使用performSelector时候,可以不用import头文件包含方法的对象

方法分析:

  • 同步执行方法
- (id)performSelector:(SEL)aSelector;  
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;

这三个方法,均为同步执行,与线程无关,主线程和子线程中均可调用成功。等同于直接调用该方法。在需要动态的去调用方法的时候去使用。

  • 异步执行方法
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay inModes:(NSArray *)modes;  
- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;

这两个方法为异步执行,即使delay传参为0,仍为异步执行。只能在主线程中执行,在子线程中不会调到aSelector方法。
在方法未到执行时间之前,取消方法为:

+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget selector:(SEL)aSelector object:(id)anArgument;  
+ (void)cancelPreviousPerformRequestsWithTarget:(id)aTarget;

NOTE:
在调用方法之前或在该方法所在的viewController生命周期结束的时候去调用取消函数,以确保不会引起内存泄露。

拓展:

- (void)performSelector:(SEL)aSelector withObject:(id)anArgument afterDelay:(NSTimeInterval)delay;

这个方法是单线程的,也就是说只有当前调用次方法的函数执行完毕后,selector方法才会被调用。

- (void)changeText:(NSString *)string  
{
NSLog(@"changeText:(NSString *)string");
}
- (void)changePopoverSize
{
[self performSelector:@selector(changeText:) withObject:@"Happy aha" afterDelay:1];
NSLog(@"changePopoverSize#####end");
sleep(5);
NSLog(@"changePopoverSize-----end");
}

打印结果:

changePopoverSize#####end
changePopoverSize-----end
changeText:(NSString *)string
  • wait 函数
- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg  
或者
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

这两个方法,在主线程和子线程中均可执行,均会调用主线程的aSelector方法;
如果设置wait为YES:等待当前线程执行完以后,主线程才会执行aSelector方法;

设置为NO:不等待当前线程执行完,就在主线程上执行aSelector方法。
如果,当前线程就是主线程,那么aSelector方法会马上执行。

注意:apple不允许程序员在主线程以外的线程中对UI进行操作,此时我们必须调用performSelectorOnMainThread函数在主线程中完成UI的更新。

  • 多线程执行
- (void)performSelectorInBackground:(SEL)aSelector withObject:(id)arg  
或者
- (void)performSelectorOnMainThread:(SEL)aSelector withObject:(id)arg waitUntilDone:(BOOL)wait;

GCD经典面试题

{
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"2--%@",[NSThread currentThread]);
NSLog(@"A");
});
NSLog(@"B");
dispatch_queue_t temp = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0);

dispatch_sync(temp, ^{
NSLog(@"3--%@",[NSThread currentThread]);
NSLog(@"C");
});

dispatch_async(temp, ^{
NSLog(@"4--%@",[NSThread currentThread]);
NSLog(@"D");
});
dispatch_async(dispatch_get_main_queue(), ^{
NSLog(@"5--%@",[NSThread currentThread]);
NSLog(@"E");
});

[self performSelector:@selector(method) withObject:nil afterDelay:0.0];
NSLog(@"F");
}

- (void)method {
NSLog(@"G");
}

/============================================================================/

答案有4个,以下为编译结果 !

答案①

// 同步+串行, 同步+并发 均打印以下结果:
B
3--<NSThread: 0x604000061f00>{number = 1, name = main}
C
F
2--<NSThread: 0x604000061f00>{number = 1, name = main}
A
5--<NSThread: 0x604000061f00>{number = 1, name = main}
E
6--<NSThread: 0x604000061f00>{number = 1, name = main}
G
4--<NSThread: 0x600000267100>{number = 3, name = (null)}
D

答案②

// 如若在同步主线程上执行,会线程阻塞
// sync_main_method 会直接崩溃!!!(答案结束)

// 以下为待验证结果
// 此结果验证一直未出现,罗列在此:
B
3--<NSThread: 0x60400007d3c0>{number = 1, name = main}
C
F
4--<NSThread: 0x60000026c500>{number = 3, name = (null)}
D
2--<NSThread: 0x60400007d3c0>{number = 1, name = main}
A
5--<NSThread: 0x60400007d3c0>{number = 1, name = main}
E
6--<NSThread: 0x60400007d3c0>{number = 1, name = main}
G

答案③

// 异步 + 主队列 执行结果:  async_main_method
B
3--<NSThread: 0x60000176d3c0>{number = 1, name = main}
C
F
6--<NSThread: 0x60000176d3c0>{number = 1, name = main}
G
2--<NSThread: 0x60000176d3c0>{number = 1, name = main}
A
5--<NSThread: 0x60000176d3c0>{number = 1, name = main}
E
4--<NSThread: 0x60000173e900>{number = 3, name = (null)}
D

答案④

// 注:由于打印结果不稳定,随机选取两个

// 异步 + 串行 执行结果: async_serial_method
B
2--<NSThread: 0x60000176d3c0>{number = 1, name = main}
3--<NSThread: 0x60000173e900>{number = 3, name = (null)}
A
C
F
5--<NSThread: 0x60000176d3c0>{number = 1, name = main}
E
4--<NSThread: 0x60000173e980>{number = 4, name = (null)}
D

另有BCAEFD,BCFAED,BACEFD ...

// 异步 + 并发 执行结果: async_concurrent_method
B
2--<NSThread: 0x60000176d3c0>{number = 1, name = main}
3--<NSThread: 0x60000173e980>{number = 4, name = (null)}
A
C
5--<NSThread: 0x60000176d3c0>{number = 1, name = main}
F
E
4--<NSThread: 0x60000173e900>{number = 3, name = (null)}
D

另有BCAFED

String function

strcpy(字符数组,字符串);     //拷贝
strcat(字符数组,字符串); //拼接
strcmp(字符串1,字符串2); //比较
strlwr(字符串); //转小写
strupr(字符串); //转大写
strlen(字符串); //算长度
strncpy(字符数组,字符串1,n); //字符串1中前n个字符拷贝到字符数组

static:

  • 静态局部变量:

①定义时不赋初值,则编译时赋初值,自动赋初值为0,只赋值一次;

②函数调用结束后任然存在,其他函数不能引用,只能本函数引用。

  • 静态函数

又称内部函数,只能本文件使用。

extern

  • 外部变量声明

声明变量的作用域扩展到此位置(本文件);

  • 外部函数声明

本文件可使用外部声明的函数(默认值);

Tips:###

用数组元素作 实参时,向形参变量传递的是数组元素的值,而用数组名做函数实参时,向形参(数组名或者指针变量)传递的是数组元素的首地址

数组名 代表数组首元素的地址,它是一个指针型常量,它的值在程序运行期间固定不变,例如:

数组 a[10] = {1,2,3,4,5,6,7,8,9,10}; a++无法实现

指针变量p指向数组a的首地址: int *p = a; 则:

for (p = a; p< a + 10; p++)
printf("%d",*p)

实参数组名代表一个固定的地址,或者说是指针常量,但形参数组名并不是一个固定的地址,而是按指针变量处理

main函数中,数组a[5] = {1,2,3,4,5}; a为数组首地址,不能自加自减
(a++, a–)因为a为常量地址(指针常量),但可以a+i这样写, a[i] = *(a+i)始终成立

子函数(自定义函数中),数组形参传的是数组首地址,不检查数组长度,系统默认当指针处理,所以数组a可自加自减,(对指针操作);

指针变量必须先赋值,后使用,这样使用极其危险:
int *p; 然后直接使用*p

通过指针引用多维数组

a[3][4]

a: 首行首地址

a+1: 序号为1的行的首地址| a+1指向a[1],或者a+1的值是a[1]的首地址

a[i] 始终等价于(恒定于) * (a + i);

Read more »