方法的系統(tǒng)適配
- 以日歷類為例:NSCalendar對象的創(chuàng)建有幾種方法,但是那些新的方法是支持高版本系統(tǒng)的,也就是說,在低版本系統(tǒng)中是沒有這些方法的,那么如果要滿足在不同的系統(tǒng)中調(diào)用不同的方法,需要做一個方法的適配,如下
NSCalendar *calendar = nil;
if ([NSCalendar respondsToSelector:@selector(calendarWithIdentifier:)]) {
calendar = [NSCalendar calendarWithIdentifier:NSCalendarIdentifierGregorian];
} else {
calendar = [NSCalendar currentCalendar];
}
respondsToSelector和instancesRespondToSelector
respondsToSelector:方法的作用:判斷左邊對象能否調(diào)用右邊的方法
instancesRespondToSelector:方法的作用:判斷左邊類的實例對象能否調(diào)用右邊的方法
[@"jack" respondsToSelector:@selector(length)] // 判斷是否有-length這個對象方法
[@"jack" length]
[NSString respondsToSelector:@selector(length)] // 判斷是否有+length這個類方法
[NSString length]
[NSString instancesRespondToSelector:@selector(length)] // 判斷是否有-length這個對象方法
[@"" length]
比較系統(tǒng)版本
//獲取當(dāng)前系統(tǒng)的版本
NSString *version = [UIDevice currentDevice].systemVersion;
/*
NSOrderedAscending 升序(右邊 > 左邊)
NSOrderedSame 相等、相同
NSOrderedDescending 降序(右邊 < 左邊)
*/
//方式一
if ([version compare:@"8.0"] != NSOrderedAscending) { // iOS系統(tǒng)版本 >= 8.0
}
//方式二
if (version.doubleValue >= 8.0) { // iOS系統(tǒng)版本 >= 8.0
}
//比較Foundation框架的版本號
if (NSFoundationVersionNumber >= NSFoundationVersionNumber_iOS_8_0) { // iOS系統(tǒng)版本 >= 8.0
}
//其他一
if ([@"" respondsToSelector:@selector(boundingRectWithSize:options:attributes:context:)]) { // iOS系統(tǒng)版本 >= 7.0
}
//其他二
if (NSClassFromString(@"UIAlertController")) { // iOS系統(tǒng)版本 >= 8.0
}
"==" "isEqualToString" "isEqual"的區(qū)別
"=="是比較兩個對象的內(nèi)存地址
"isEqualToString"計較的是兩個字符串的內(nèi)容
"isEqual"默認(rèn)情況下是比較兩個對象的內(nèi)存地址,但是有一些系統(tǒng)自帶的類(比如Foundation中的NSString)重寫了這個方法,改變了這個方法的判斷規(guī)則(一般改為比較兩個對象的內(nèi)容,不是內(nèi)存地址)
Foundation中的一般規(guī)則:如果系統(tǒng)中的某個類重寫了isEqual這個方法改變其判斷規(guī)則,那么這個類會提供一個isEqualToXXX方法用來提示開發(fā)者isEqual被重寫過了,例如: NSString中重寫了isEqual,將這個方法的判斷規(guī)則由判斷兩個對象的內(nèi)存地址改為比較兩個對象的內(nèi)容,并且提供一個isEqualToString方法
NSString *string1 = @"jack";
NSString *string2 = [NSString stringWithFormat:@"jack"];
NSLog(@"string1 == string2 -> %zd", string1 == string2); // 0
NSLog(@"[string1 isEqualToString:string2] -> %zd", [string1 isEqualToString:string2]); // 1
NSLog(@"[string1 isEqual:string2] -> %zd", [string1 isEqual:string2]); // 1
NSString *string1 = @"jack";
NSString *string2 = @"jack";
NSLog(@"%p %p", string1, string2);
NSLog(@"string1 == string2 -> %zd", string1 == string2); // 1
NSLog(@"[string1 isEqualToString:string2] -> %zd", [string1 isEqualToString:string2]); // 1
NSLog(@"[string1 isEqual:string2] -> %zd", [string1 isEqual:string2]); // 1
重寫自定義類的isEqual方法(以Person類為例)
/*
一旦重寫了isEqual:方法顶籽,最好重寫hash方法凤藏,而且要遵守以下原則:
1.isEqual:返回YES的2個對象,hash值一定要一樣
2.hash值一樣的2個對象,isEqual:返回不一定是YES
*/
- (NSUInteger)hash
{
return self.age + self.no + self.name.hash ;
}
- (BOOL)isEqual:(XMGPerson *)object
{
return [self isEqualToPerson:object];
}
- (BOOL)isEqualToPerson:(XMGPerson *)person
{
// 如果是完全相同的對象抚官,就省去后面的判斷
if (self == person) return YES;
// 如果object的類型不對猜旬,就不需要比較
if (![person isKindOfClass:self.class]) return NO;
// 基本數(shù)據(jù)類型
BOOL result = (self.age == person.age && self.no == person.no);
if (result == NO) return result;
// 對象類型
if (self.name || person.name) {
if (![self.name isEqual:person.name]) return NO;
}
if (self.car || person.car) {
if (![self.car isEqual:person.car]) return NO;
}
return YES;
}
XMGPerson *p1 = [[XMGPerson alloc] init];
p1.age = 20;
p1.no = 30;
NSString *string1 = [NSString stringWithFormat:@"222"];
NSString *string2 = @"222";
NSArray *array = @[@"111", @"333", string2, string1];
NSLog(@"%zd", [array containsObject:p1]);
NSLog(@"%zd", [array indexOfObject:string1]);
[array containsObject:]和[array indexOfObject:]的底層實現(xiàn)思路
- (BOOL)containsObject:(id)anObject
{
if (anObject == nil) return NO;
for (id obj in self) {
if ([anObject isEqual:obj]) return YES;
}
return NO;
}
- (NSUInteger)indexOfObject:(id)anObject
{
if (anObject == nil) return NSNotFound;
NSUInteger index = 0;
for (id obj in self) {
if ([anObject isEqual:obj]) return index;
index++;
}
return NSNotFound;
}