1.UIButton和UITableView的层级结构。
2.Foundation对象和Core Foundation对象通过什么关键字进行转换,这几个关键字都有什么区别。
3.多线程安全的几种解决办法。
4.什么情况下会发生内存泄露和内存溢出。
5.iOS json解析数据会发生内存泄露吗,如果会,怎么解决。
6.socket如何进行通信。
1.UIButton和UITableView的层级结构:
UIButton > UIControl > UIView > UIResponder > NSObject
UITableView > UIScrollView > UIView > UIResponder > NSObject
2.Foundation对象和Core Foundation对象通过什么关键字进行转换,这几个关键字都有什么区别。
__bridge只做类型转换,但是不修改对象(内存)管理权;
__bridge_retained(也可以使用CFBridgingRetain)将Objective-C的对象转换为Core Foundation的对象,同时将对象(内存)的管理权交给我们,后续需要使用CFRelease或者相关方法来释放对象;
__bridge_transfer(也可以使用CFBridgingRelease)将Core Foundation的对象转换为Objective-C的对象,同时将对象(内存)的管理权交给ARC。
3.多线程安全的几种解决办法。
@interface ViewController ()
@property (nonatomic,assign) int leftTicketCount;
@property (nonatomic,strong) NSThread *thread1;
@property (nonatomic,strong) NSThread *thread2;
@property (nonatomic,strong) NSThread *thread3;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
/*
多线程的安全隐患
资源共享
1块资源可能会被多个线程共享,也就是多个线程可能会访问同一块资源
比如多个线程访问同一个对象、同一个变量、同一个文件
当多个线程访问同一块资源时,很容易引发数据错乱和数据安全问题
*/
//默认有20张票
self.leftTicketCount =20;
//开启多个线程模拟售票员售票
self.thread1 = [[NSThreadalloc] initWithTarget:selfselector:@selector(sellTickets)object:nil];
self.thread1.name =@"售票员A";
self.thread2 = [[NSThreadalloc] initWithTarget:selfselector:@selector(sellTickets)object:nil];
self.thread2.name =@"售票员B";
self.thread3 = [[NSThreadalloc] initWithTarget:selfselector:@selector(sellTickets)object:nil];
self.thread3.name =@"售票员C";
}
- (void)sellTickets {
while (1) {
//互斥锁:优点:能有效防止因多线程抢夺资源造成的数据安全问题。缺点:需要消耗大量CPU资源。
//互斥锁使用前提:多线程使用同一块资源。互斥锁使用的是线程同步技术,多条线程按顺序执行任务。
@synchronized(self) {//只能加一把锁
//加了这句话后打印为
/*
2016-03-02 14:50:02.826 多线程安全问题[855:50219] <NSThread: 0x7f9441592b40>{number = 2, name =售票员A} 卖了一张票,还剩余19张票
2016-03-02 14:50:02.829 多线程安全问题[855:50220] <NSThread: 0x7f9441516f90>{number = 3, name =售票员B} 卖了一张票,还剩余18张票
2016-03-02 14:50:02.832 多线程安全问题[855:50221] <NSThread: 0x7f94415965a0>{number = 4, name =售票员C} 卖了一张票,还剩余17张票
2016-03-02 14:50:02.835 多线程安全问题[855:50219] <NSThread: 0x7f9441592b40>{number = 2, name =售票员A} 卖了一张票,还剩余16张票
2016-03-02 14:50:02.838 多线程安全问题[855:50220] <NSThread: 0x7f9441516f90>{number = 3, name =售票员B} 卖了一张票,还剩余15张票
2016-03-02 14:50:02.840 多线程安全问题[855:50221] <NSThread: 0x7f94415965a0>{number = 4, name =售票员C} 卖了一张票,还剩余14张票
*/
//1.先检查票数
int count =self.leftTicketCount;
if (count >0) {
//暂停
[NSThreadsleepForTimeInterval:0.002];
//票数减1
self.leftTicketCount = count-1;
//获取当前线程
NSThread *current = [NSThreadcurrentThread];
NSLog(@"%@ 卖了一张票,还剩余%d张票", current,self.leftTicketCount);
//这样打印为
/*
2016-03-02 14:44:38.757 多线程安全问题[809:47089] <NSThread: 0x7fff0851d8a0>{number = 3, name =售票员B} 卖了一张票,还剩余19张票
2016-03-02 14:44:38.757 多线程安全问题[809:47090] <NSThread: 0x7fff0851f0f0>{number = 4, name =售票员C} 卖了一张票,还剩余19张票
2016-03-02 14:44:38.757 多线程安全问题[809:47087] <NSThread: 0x7fff08502c30>{number = 2, name =售票员A} 卖了一张票,还剩余19张票
2016-03-02 14:44:38.760 多线程安全问题[809:47089] <NSThread: 0x7fff0851d8a0>{number = 3, name =售票员B} 卖了一张票,还剩余18张票
2016-03-02 14:44:38.760 多线程安全问题[809:47090] <NSThread: 0x7fff0851f0f0>{number = 4, name =售票员C} 卖了一张票,还剩余18张票
2016-03-02 14:44:38.760 多线程安全问题[809:47087] <NSThread: 0x7fff08502c30>{number = 2, name =售票员A} 卖了一张票,还剩余18张票
*/
} else {
//退出线程
[NSThreadexit];
}
}
}
}
- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event {
//开启线程
[self.thread1start];
[self.thread2start];
[self.thread3start];
}
OC在定义属性时有atomic和nonatomic
atomic 原子属性,为setter方法加锁。
nonatomic 非原子属性,不为setter方法加锁。
对比:atomic线程安全,但要消耗大量CPU资源。 nonatomic线程不安全,适合内存小的移动设备。
iOS开发建议:所有属性都使用nonatomic,尽量避免多个线程抢夺同一块资源,尽量将加锁、资源抢夺的业务逻辑放到服务器端处理。
4.什么情况下会发生内存泄露和内存溢出。
内存泄露是指程序在运行过程中动态申请的内存空间不再使用后没有及时释放,从而很可能导致应用程序内存无线增长。更广义的内存泄露包括未对系统的资源的及时释放,比如句柄等。
内存溢出即用户在对其数据缓冲区操作时,超过了其缓冲区的边界;尤其是对缓冲区写操作时,缓冲区的溢出很可能导致程序的异常。
1.内存泄露是说程序逻辑问题,造成申请的内存无法释放.这样的话无论多少内存,早晚都会被占用光的.
最简单的例子就是死循环了.由于程序判断错误导经常发生此事
2.内存泄漏是指在堆上分配的内存没有被释放,从而失去对其控制。这样会造成程序能使用的内存越来越少,导致系统运行速度减慢,严重情况会使程序当掉。
3.关于内存溢出有点出入。比如说你申请了一个integer,但给它存了long才能存下的数,那就是内存溢出。
举个现实中的例子
4.比如有一个桶,装满了水.你丢个苹果进去。桶的水正常。
如果你放个大石头。水就出溢出,内存溢出也就是这个原理
区别:内存溢出,提供的内存不够;内存泄漏,无法再提供内存资源
6.socket如何进行通信。
首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的。其实TCP/IP协议族已经帮我们解决了这个问题,网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。这样利用三元组(ip地址,协议,端口)就可以标识网络的进程了,网络中的进程通信就可以利用这个标志与其它进程进行交互。
使用TCP/IP协议的应用程序通常采用应用编程接口:UNIX BSD的套接字(socket)和UNIX System V的TLI(已经被淘汰),来实现网络进程之间的通信。就目前而言,几乎所有的应用程序都是采用socket,而现在又是网络时代,网络中进程通信是无处不在,这就是我为什么说“一切皆socket”。