局部变量能否和全局变量重名?


能,局部会屏蔽全局。要用全局变量,需要使用"::",局部变量可以与全局变量同名,在函数内引用这个变量时,会用到同名的局部变量,而不会用到全局变量。对于有些编译器而言,在同一个函数内可以定义多个同名的局部变量,比如在两个循环体内都定义一个同名的局部变量,而那个局部变量的作用域就在那个循环体内

设计模式是什么?你知道哪些设计模式,并简要叙述?


设计模式是一种编码经验,就是用比较成熟的逻辑去处理某一种类型的事情。
1)MVC模式:Model View Control,把模型 视图 控制器 层进行解耦合编写。
2)MVVM模式:Model View ViewModel 把模型 视图 业务逻辑 层进行解耦和编写。
3)单例模式:通过static关键词,声明全局变量。在整个进程运行期间只会被赋值一次。
4)观察者模式:KVO是典型的通知模式,观察某个属性的状态,状态发生变化时通知观察者。
5)委托模式:代理+协议的组合。实现1对1的反向传值操作。
6)工厂模式:通过一个类方法,批量的根据已有模板生产对象。


MVC 和 MVVM 的区别


1)MVVM是对胖模型进行的拆分,其本质是给控制器减负,将一些弱业务逻辑放到VM中去处理。
2)MVC是一切设计的基础,所有新的设计模式都是基于MVC进行的改进。


KVC的底层实现?


当一个对象调用setValue方法时,方法内部会做以下操作:
1)检查是否存在相应的key的set方法,如果存在,就调用set方法。
2)如果set方法不存在,就会查找与key相同名称并且带下划线的成员变量,如果有,则直接给成员变量属性赋值。
3)如果没有找到_key,就会查找相同名称的属性key,如果有就直接赋值。
4)如果还没有找到,则调用valueForUndefinedKey:和setValue:forUndefinedKey:方法。
这些方法的默认实现都是抛出异常,我们可以根据需要重写它们。


iOS 时间选择器 三方 仿ios时间选择器_ios 时间选择器

iOS 时间选择器 三方 仿ios时间选择器_ios 时间选择器_02

iOS 时间选择器 三方 仿ios时间选择器_ios 时间选择器_03

Runtime实现的机制是什么,怎么用,一般用于干嘛?


1)使用时需要导入的头文件
2)Runtime 运行时机制,它是一套C语言库。
3)实际上我们编写的所有OC代码,最终都是转成了runtime库的东西。
比如:
类转成了 Runtime 库里面的结构体等数据类型,
方法转成了 Runtime 库里面的C语言函数,
平时调方法都是转成了 objc_msgSend 函数(所以说OC有个消息发送机制)
// OC是动态语言,每个方法在运行时会被动态转为消息发送,即:objc_msgSend(receiver, selector)。
// [stu show]; 在objc动态编译时,会被转意为:objc_msgSend(stu, @selector(show));
4)因此,可以说 Runtime 是OC的底层实现,是OC的幕后执行者。


什么是 Method Swizzle(黑魔法),什么情况下会使用?


1)在没有一个类的实现源码的情况下,想改变其中一个方法的实现,除了继承它重写、和借助类别重名方法暴力抢先之外,还有更加灵活的方法 Method Swizzle。
2)Method Swizzle 指的是改变一个已存在的选择器对应的实现的过程。OC中方法的调用能够在运行时通过改变,通过改变类的调度表中选择器到最终函数间的映射关系。
3)在OC中调用一个方法,其实是向一个对象发送消息,查找消息的唯一依据是selector的名字。利用OC的动态特性,可以实现在运行时偷换selector对应的方法实现。
4)每个类都有一个方法列表,存放着selector的名字和方法实现的映射关系。IMP有点类似函数指针,指向具体的方法实现。
5)我们可以利用 method_exchangeImplementations 来交换2个方法中的IMP。
6)我们可以利用 class_replaceMethod 来修改类。
7)我们可以利用 method_setImplementation 来直接设置某个方法的IMP。
8)归根结底,都是偷换了selector的IMP。


折半查找(二分查找)

/**
 * 折半查找:优化查找时间(不用遍历全部数据)
 *
 * 折半查找的原理:
 * 1> 数组必须是有序的
 * 2> 必须已知min和max(知道范围)
 * 3> 动态计算mid的值,取出mid对应的值进行比较
 * 4> 如果mid对应的值大于要查找的值,那么max要变小为mid-1
 * 5> 如果mid对应的值小于要查找的值,那么min要变大为mid+1
 *
 */ 

// 已知一个有序数组, 和一个key, 要求从数组中找到key对应的索引位置 
int findKey(int *arr, int length, int key) {
 int min = 0, max = length - 1, mid;
 while (min <= max) {
 mid = (min + max) / 2; //计算中间值
 if (key > arr[mid]) {
 min = mid + 1;
 } else if (key < arr[mid]) {
 max = mid - 1;
 } else {
 return mid;
 }
 }
 return -1;
}

```


     建筑大师柯布西耶说:建筑即精神。通往伟大建筑的征程,从来不是一蹴而就。臻于极致的探索,专注细节的执着,每一步皆是对自我的超越,也是成就“作品”的必经之途。

冒泡排序

/** 
 * 【冒泡排序】:相邻元素两两比较,比较完一趟,最值出现在末尾
 * 第1趟:依次比较相邻的两个数,不断交换(小数放前,大数放后)逐个推进,最值最后出现在第n个元素位置
 * 第2趟:依次比较相邻的两个数,不断交换(小数放前,大数放后)逐个推进,最值最后出现在第n-1个元素位置
 * …… ……
 * 第n-1趟:依次比较相邻的两个数,不断交换(小数放前,大数放后)逐个推进,最值最后出现在第2个元素位置 
 */
void bublleSort(int *arr, int length) {
 for(int i = 0; i < length - 1; i++) { //趟数
 for(int j = 0; j < length - i - 1; j++) { //比较次数
 if(arr[j] > arr[j+1]) {
 int temp = arr[j];
 arr[j] = arr[j+1];
 arr[j+1] = temp;
 }
 } 
 }
}


模拟栈操作

/**
 * 栈是一种数据结构,特点:先进后出
 * 练习:使用全局变量模拟栈的操作
 */
#include 
#include 
#include 
//保护全局变量:在全局变量前加static后,这个全局变量就只能在本文件中使用
static int data[1024];//栈最多能保存1024个数据
static int count = 0;//目前已经放了多少个数(相当于栈顶位置)
//数据入栈 push
void push(int x){
 assert(!full());//防止数组越界
 data[count++] = x;
}
//数据出栈 pop
int pop(){
 assert(!empty());
 return data[--count];
}
//查看栈顶元素 top
int top(){
 assert(!empty());
 return data[count-1];
}
//查询栈满 full
bool full() {
 if(count >= 1024) {
 return 1;
 }
 return 0; 
}
//查询栈空 empty
bool empty() {
 if(count <= 0) {
 return 1;
 }
 return 0;
}
int main(){
 //入栈
 for (int i = 1; i <= 10; i++) {
 push(i);
 }
 //出栈
 while(!empty()){
 printf("%d ", top()); //栈顶元素
 pop(); //出栈
 }
 printf("\n");
 return 0;
}


不用中间变量,用两种方法交换A和B的值

// 1.中间变量
void swap(int a, int b) {
 int temp = a;
 a = b;
 b = temp;
}

// 2.加法
void swap(int a, int b) {
 a = a + b;
 b = a - b;
 a = a - b;
}

// 3.异或(相同为0,不同为1. 可以理解为不进位加法)
void swap(int a, int b) {
 a = a ^ b;
 b = a ^ b;
 a = a ^ b;
}
```