干嘛用的?为什么是<NSObject> 不是继承与NSObject?
查看 NSObject.h发现 苹果有一个<NSObject> 协议
cocoa框架中的基类不止NSObject一个,还有NSProxy这样的类存在
两者都实现了< NSObject >协议
@protocol NSObject
- (BOOL)isEqual:(id)object;
@property (readonly) NSUInteger hash;
@property (readonly) Class superclass;
- (Class)class OBJC_SWIFT_UNAVAILABLE("use 'type(of: anObject)' instead");
- (instancetype)self;
- (id)performSelector:(SEL)aSelector;
- (id)performSelector:(SEL)aSelector withObject:(id)object;
- (id)performSelector:(SEL)aSelector withObject:(id)object1 withObject:(id)object2;
- (BOOL)isProxy;
- (BOOL)isKindOfClass:(Class)aClass;
- (BOOL)isMemberOfClass:(Class)aClass;
- (BOOL)conformsToProtocol:(Protocol *)aProtocol;
- (BOOL)respondsToSelector:(SEL)aSelector;
- (instancetype)retain OBJC_ARC_UNAVAILABLE;
- (oneway void)release OBJC_ARC_UNAVAILABLE;
- (instancetype)autorelease OBJC_ARC_UNAVAILABLE;
- (NSUInteger)retainCount OBJC_ARC_UNAVAILABLE;
- (struct _NSZone *)zone OBJC_ARC_UNAVAILABLE;
@property (readonly, copy) NSString *description;
@optional
@property (readonly, copy) NSString *debugDescription;
@end
hash
hash(散列函数):通过一定算法变换成固定长度的输出(long 或者字符串)
常用的hash函数:MD4 MD5 SHA1 CRC32
不少程序(网站)用MD5或SHA1来加密密码,加密强度固然不错,但二者都有不少的计算量。在空间占用方面,MD5有32位,即使是简化缩短的,也有16位,而有些所谓的简化缩短,事实上是在32位结果的基础上加了一道截短的程序,进一步降低了性能。SHA1更是有40位之多。对于有大量用户、密码的程序(网站)来说,在这个环节上寻求更优的方案是很有意义的。CRC32的计算结果只有8位,对于绝大多数应用来说,强度也完全足够。
那么苹果的hash有什么用呢?
1.一个对象在用作key值时,其 hash 方法会被调用,用以生成一个唯一标识符,NSDictionary 需要根据唯一 key 值(根据 hash 算法生成的值)查找对象, NSSet 需要根据 hash 值来确保过滤掉重复的对象
2.weak修饰的对象写入内存 会写入一张hash表里面
iOS中hash值遵循的原则
1.如果两个对象相同,那么它们的hashCode值一定要相同;
2.如果两个对象的hashCode相同,它们并不一定相同 。
3.当对象作为以hash值决定对象位置的collection时,必须保证该对象的hash值不发生改变
== 与 isEqual的区别?
== 比较对象的地址, (严格意义上的一样)
isEqual 比较对象(属性的值是否一样)
UIColor *color1 = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0];
UIColor *color2 = [UIColor colorWithRed:0.5 green:0.5 blue:0.5 alpha:1.0];
color1 == color2 ---> 输出的是NO
[color1 isEqual:color2] ---> 输出的是YES
所以自定义的对象如果使用 isEqual 输出的是NO 所以有时候我们需要重写isEqual
- (BOOL)isEqual:(id)object {
if (self == object) {
return YES;
}
if (![object isKindOfClass:[Person class]]) {
return NO;
}
return [self isEqualToPerson:(Person *)object];
}
- (BOOL)isEqualToPerson:(Person *)person {
if (!person) {
return NO;
}
BOOL haveEqualNames = (!self.name && !person.name) || [self.name isEqualToString:person.name];
BOOL haveEqualBirthdays = (!self.birthday && !person.birthday) || [self.birthday isEqualToDate:person.birthday];
return haveEqualNames && haveEqualBirthdays;
}
如果重写isEqual方法,一定要重写hash方法。??
让person遵循NSCopying协议 将person作为key会有什么发生呢?
Person *person1 = [Person personWithName:@"Joe" age:@"32"];
Person *person2 = [Person personWithName:@"Joe" age:@"32"];
Person *person3 = [Person personWithName:@"Joe" age:@"33"];
NSMutableDictionary *dict = [[NSMutableDictionary alloc] init];
[dict setObject:@"1" forKey:person1];
[dict setObject:@"2" forKey:person2];
[dict setObject:@"3" forKey:person3];
NSLog(@"dict count: %ld", dict.count);
由于我们重载了 equal 方法,person1 和 person2 应该是相同对象,理论上 dict 的 count 应该是 2。 但是输出的值却是 3. 说明他们的hash值是不一样的 所以有时候需要我们重写- (NSUInteger)hash {}方法
- (NSUInteger)hash {
return [self.name hash] ^ [self.age hash];
}
Objective-c中 isEqual ,isEqualToString , == 三者的区别
iOS开发 之 不要告诉我你真的懂isEqual与hash!
解读Objective-C中的[NSString hash]方法
诺,又发现协议可以定义属性
NSProxy
总的来说,NSProxy是一个虚类,你可以通过继承它,并重写这两个方法以实现消息转发到另一个实例
Objective-C却不支持这样一个强大的特性。不过NSProxy可以帮我们在某种程度上(这只是一个模拟的多继承,并不是完全的多继承)
实际使用场景 例如有很多的controller。点击按钮的时候数据传过来需要做大量的判断才可以知道需要跳转到哪一个controller 这时候就可以使用NSProxy来实现
继承与NSProxy 的类必须实现
- (void)forwardInvocation:(NSInvocation *)anInvocation;
- (NSMethodSignature *)methodSignatureForSelector:(SEL)sel;
实现NSProxy类及可以调用A类方法 又可以调用B类方法
TDDealerProxy *dealerProxy = [TDDealerProxy dealerProxy];
[dealerProxy purchaseBookWithTitle:@"Swift 100 Tips"];
[dealerProxy purchaseClothesWithSize:TDClothesSizeMedium];