1、请简述什么是主键、什么是外键
主键:
一张表(关系)的一个列(睡醒)或多个列可以作为主键,但是前提是让这个列作为主键,这个列就能保证该列下的各行(元素)的值不能相同,比如说你用姓名属性做主键的话,那么这个主键就不一定可以,如果有两个人是同样的名字的话,就不嗯那个做到该属性下的各个元祖数据的值不同,如果用阿拉伯数字做主键就是一个很好的选择。
外键:
一张表(关系)的列(属性)他同时保存在表1和表2中,他不是表1的主键,而是表2的主键,就可以书他是表1的外键。
那什么时候选键呢:能唯一标识(关系)中行(元组)的列(属性),则成该属性为候选键,也成候选关键字或候选码;由此来看候选键可以不只一个。
2、请简述你理解的内存管理。
创建对象并使用后需要释放,否则会出现内存泄露,内存管理跟非手动内存管理MRC和自动内存管理ARC。
(1)在手动内存管理机制下,如果使用alloc,copy(MutabelCopy),retain一个对象时,在使用完毕需要向该对象发送release,或者autorelease消息来释放这个对象,其他方法创建的对象不需要管理内存。
(2)在自动内存管理机制下,系统维护的自动释放池会自动处理。
3、如何实现流媒体格式的视频播放,边缓边存?
(1)需要在视频播放器和服务器之间添加一层类似代理的机制,视频播放器不再直接访问服务器,而是访问代理对象,代理对象去访问服务器获得数据,之后返回给视频播放器,同时代理对象根据一定的策略缓存数据。
(2)AVURLAsset中的resourceLoader可以实现这个机制,resourceLoader的delegate就是上述的代理对象。
(3)视频播放器在开始播放之前首先检测是本地cache中是否有此视频,如果没有才通过代理获得数据,如果有,则直接播放本地cache中的视频即可。
4、请简述weak和assgin有什么区别?
assign这是指针赋值,不对引用计数操作,使用之后,如果没有设置为nil,可能就会产生野指针;而weak一旦不进行使用后,永远不会使用了,就不会产生野指针。
在ARC模式下编程时,指针变量一定要用weak修饰,只有基本数据类型和结构体需要用assgin,例如delegate,一定要用weak修饰
Objective-C数据类型可以分为:
基本数据类型、对象类型和id类型。
(1)基本数据类型有:int、float、double和char类型。
(2)对象类型就是类或协议所声明的指针类型,例如:NSAutoreleasePool * pool,其中NSAutoreleasePool是一个类,NSAutoreleasePool *是它指针类型。
(3)id类型可以表示任何类型,一般只是表示对象类型,不表示基本数据类型。
5、如何实现ARC和MRC的混合编程?
<1> 尝试使用Xcode的转换工具(失败率比较高)
<2> 在编译选项中,为MRC的程序添加-fno-objc-arc标记,表明在编译时,该文件使用MRC编译
备注:
(1) 演示中使用的RegexKitLite还需要导入libicucore.dylib动态库
(2) 如果要在MRC项目中添加ARC的文件,可以使用 -fobjc-arc 标记即可
<3> 将MRC的第三方库直接编译成静态库使用
注意:在编译静态库时,不能添加动态库引用
说明:RegexKitLite是对NSString添加的正则表达式分类
在项目中,如果使用的静态库中包含分类,则需要在Other Link Flag中添加 -ObjC选项
Xcode 项目中我们可以使用 ARC 和MRC的混合模式。
(1)如果你的项目使用的MRC模式,则为 ARC 模式的代码文件加入 -fobjc-arc 标签。
(2)如果你的项目使用的是 ARC 模式,则为MRC 模式的代码文件加入 -fno-objc-arc 标签。
添加标签的方法:
打开:你的target -> Build Phases -> Compile Sources.
双击对应的 *.m 文件
在弹出窗口中输入上面提到的标签 -fobjc-arc / -fno-objc-arc
点击 done 保存
6、Object-C中是否支持多继承?
Object-C不支持多继承,由于消息机制查找发生在运行时而非编译时,很难解决多个基类可能导致的二义性问题。不过我们可以找到如下集中间接实现多继承目的的方法:消息转发机制、delegate和protocol、类别。
一、消息转发:
当向someObject发送某消息,但runtime system在当前类和父类中都找不到对应方法的实现时,runtime system并不会立即报错是程序崩溃,而是依次执行下列步骤:
20130524164518623.jpg分别简述一下流程:
(1)动态方法解析:向当前类发送resolveInstanceMethod:信号,检查是否动态向该类添加方法。
(2)快速消息转发:检查该类是否实现了 forwardingTargetForSelector: 方法,若实现了则调用这个方法。若该方法返回值对象非nil或非self,则向该返回对象重新发送消息。
(3)标准消息转发:runtime发送methodSignatureForSelector:消息获取Selector对应的方法签名。返回值非空则通过forwardInvocation:转发消息,返回值为空则向当前对象发送doesNotRecognizeSelector:消息,程序崩溃退出。
顾名思义,我们可以利用上述过程中的(2)、(3)两种方式来完成消息转发。
快速消息转发
快速消息转发的实现方法很简单,只需要重写 - (id)forwardingTargetForSelector:(SEL)aSelector 方法即可。
我来举个简单的例子,比如现有2个类:Teacher 和 Doctor,Doctor可以做手术(operate方法)。
@interface Doctor : NSObject
- (void)operate;
@end
通过快速消息转发,可以很轻松的让teacher调用doctor的方法做手术。Teacher类需要实现将消息转发给Doctor:
- (id)forwardingTargetForSelector:(SEL)aSelector
{
Doctor *doctor = [[Doctor alloc]init];
if ([doctor respondsToSelector:aSelector]) {
return doctor;
}
return nil;
}
#######虽然消息可以动态转发传递,但是编辑器的静态检查是绕不过的,那么问题来了,既然Teacher类没有实现operate方法又该如何声明呢?到目前为止,我只想到下面2种方法:
声明方法1 —— 类别
@interface Teacher (DoctorMethod)
- (void)operate;
@end
声明方法2 ———— 导入头文件、调用时强转类型
Teacher类头文件需要包含Doctor头文件,告诉编译器去Doctor.h中可以找到operator方法的声明,并且在调用时强转类型。
Teacher *teacher = [[Teacher alloc]init];
[(Doctor *)teacher operate];
标准消息转发
标准消息转发需要重写 methodSignatureForSelector: 和 forwardInvocation: 两个方法即可。发流程如图所示:
20130524165504839.jpg重写方法:
- (NSMethodSignature *)methodSignatureForSelector:(SEL)aSelector
{
NSMethodSignature* signature = [super methodSignatureForSelector:aSelector];
if (signature==nil) {
signature = [someObj methodSignatureForSelector:aSelector];
}
NSUInteger argCount = [signature numberOfArguments];
for (NSInteger i=0 ; i<argCount ; i++) {
}
return signature;
}
- (void)forwardInvocation:(NSInvocation *)anInvocation
{
SEL seletor = [anInvocation selector];
if ([someObj respondsToSelector:seletor]) {
[anInvocation invokeWithTarget:someObj];
}
}
两种消息转发方式的比较
(1)快速消息转发:简单、快速、但仅能转发给一个对象。
(2)标准消息转发:稍复杂、较慢、但转发操作实现可控,可以实现多对象转发。
二、delegate和protocol
委托是Objective-C中最常用的一种回调机制。用法我觉得没什么好说的,总结一下该机制特点:委托协助主体完成操作任务,将需要定制化的操作预留给委托对象来自定义实现,类似子类化主体。除此之外,可以用作事件监听。
三、类别
个人认为类别是Objective-C设计的一大精髓,也是我爱上Objective-C的最大理由。类别是个强大的东西,它既可以为类添加方法,也可以添加实例。一定有不少人不认同,想提醒我:类别的局限性之一就是无法向类中添加新的实例变量。 背书真心毁人,听我举个例子慢慢说。 重新再来个Teacher类:
@interface Teacher : NSObject
{
NSUInteger age;
}
@end
光有个年龄还不能满足对teacher的描述,我想加个profession实例来存teacher的专业。直观的想法是子类化Teacher,其实也可以用类别。
你需要了解一下 runtime 编程知识,关注一下 objc_setAssociatedObject 和 objc_getAssociatedObject 。
//
// Teacher+Profession.m
//
#import "Teacher+Profession.h"
#import <objc/runtime.h>
const char *ProfessionType = "NSString *";
@implementation Teacher (Profession)
-(void)setProf:(NSString*)prof
{
objc_setAssociatedObject(self, ProfessionType, prof, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
-(NSString *)prof
{
NSString *pro = objc_getAssociatedObject(self, ProfessionType);
return pro;
}
@end
网友评论