1. 程式人生 > >OC中自定義類的NSCopying實現的注意事項(isEqual & hash實現)

OC中自定義類的NSCopying實現的注意事項(isEqual & hash實現)

在OC中,如果自定義類,則要考慮賦值、持久化儲存、儲存到其它容器中等各種情況的物件複製和比較,下面是一個比較全面的自定義例子,在此僅作記錄:

自定義類:

KeyValuePairs.h:

#import <Foundation/Foundation.h>

@interface KeyValuePairs: NSObject <NSCopying>
@property (nonatomic,strong)NSString *identifier;
@property (nonatomic,strong)NSString *name;

@end

KeyValuePairs.m:
#import "KeyValuePairs.h"

@implementation KeyValuePairs

- (id)copyWithZone:(NSZone *)zone
{
    KeyValuePairs *kvp = [[[self class] allocWithZone:zone] init];
    kvp.identifier = self.identifier;
    kvp.name = self.name;
    return kvp;
}

- (BOOL)isEqualToKeyValuePairs:(KeyValuePairs *)kvp{
    if (!kvp) {
        return NO;
    }
    BOOL haveEqualName = (!self.name && !kvp.name) || [self.name isEqualToString:kvp.name];
    BOOL haveEqualIdentifier = (!self.identifier && !kvp.identifier) || [self.identifier isEqualToString:kvp.identifier];
    
    return haveEqualName && haveEqualIdentifier;
}

#pragma mark -NSObject
-(BOOL)isEqual:(id)object{
    if (self == object) {
        return YES;
    }
    if (![object isKindOfClass:[KeyValuePairs class]]) {
        return NO;
    }
    return [self isEqualToKeyValuePairs:(KeyValuePairs *)object];
}

- (NSUInteger)hash {
    return [self.name hash] ^ [self.identifier hash];
}

@end
測試:
    NSMutableDictionary *namesWillUpdateDic = [[NSMutableDictionary alloc] init];
    NSMutableArray *names = [[NSMutableArray alloc] init];
    for (int i = 0; i<1000; i++) {
        NSString *name = [NSString stringWithFormat:@"%d_zhangsan",i];
        NSString *identifier = [NSString stringWithFormat:@"%d_identifier",i];
        NSString *strObj = [NSString stringWithFormat:@"%d_strObj",i];
        KeyValuePairs *kvp = [[KeyValuePairs alloc] init];
        kvp.identifier = identifier;
        kvp.name = name;
        [namesWillUpdateDic setObject:strObj forKey:kvp];
        [names addObject:kvp];
    }
    
    for (int j = 0; j<1000; j++) {
        int index = arc4random()%1000;
        KeyValuePairs *kvp = [names objectAtIndex:index];
        NSString *strObj = [namesWillUpdateDic objectForKey:kvp];
        NSString *msg = [NSString stringWithFormat:@"index:%d,identifier:%@,email:%@,strObj:%@",index,kvp.identifier,kvp.name,strObj];
        NSLog(@"%@",msg);
    }


注意:

1、如果自定義類不實現NSCopying則無法進行持久化儲存(到檔案)、或錯誤賦值

2、如果自定義類不重寫isEqual則預設使用記憶體地址比較兩個物件,可能會出現意想不到的結果

3、isEqual和hash方法要同時重寫,否則isEqual方法判斷將不正確

相關推薦

OC定義NSCopying實現注意事項(isEqual & hash實現)

在OC中,如果自定義類,則要考慮賦值、持久化儲存、儲存到其它容器中等各種情況的物件複製和比較,下面是一個比較全面的自定義例子,在此僅作記錄: 自定義類: KeyValuePairs.h: #import <Foundation/Foundation.h> @

OC定義init方法

dag 一個 主函數 his 括號 聲明 實現 初學 沒有初始化 ---恢復內容開始--- 我們知道,在函數中實例化一個對象,大多數會同時進行初始化,如 Person *p =[ [Person alloc]init]; 此時已經進行了初始化,使用init方法,那麽我們能不

Swift定義==比較方法未被呼叫的分析和解決

在專案中自定義了2個類:A和B,其中A含有B的例項變數. 在這2個類中都定義了==比較方法,按照正常來說:比較A,必然比較B.因為需要比較A中型別為B的例項變數. 但實際執行中發現,兩個字面上完全一樣的A例項物件,比較竟然不相等!!! 在A的==方法中下斷點,發

TabLayout item 的定義 & 使用 Fragment 的注意事項

採用預設模式: 自定義 item 後(tabitem): 在 Fragment 採用 TabLayout + ViewPager 佈局: public class OrderFragment extends Fragment { private T

.Net定義作為Dictionary的key詳解

在定義資料結構時,Dictionary提供了快速查詢資料的功能,另外Dictionary< TKey, TValue >屬於key-value鍵值對資料結構,提供了泛型的靈活性,是資料結構的一個利器,但是目前擁有的string,int,bool

python定義

python中常用的自定類方法: 1.可以定義類和函式,然後自己通過類直接賦值,程式碼如下: 2.可以藉助MethodType實現,程式碼如下: 3.可以藉助type實現,程式碼如下: dir() 函式不帶引數時,返回當前範圍內的變數、方法和定義的型別列表;帶引數時,返回引數的屬性

JavaScript定義寫法與呼叫例子

最快入門 類的寫法如下: IntroducerService = function() {     //自身的指標     var me = this;     //公有變數     me.test = "myTest";         // 公有方法     me

獲取實現了某介面的所有,並返回該類定義的方法的方法名

準備階段:   定義介面和實現介面的類。 interface IMyInterface { void Write(); } /// <summary> /// 實現類1 /// </summary>

C#定義操作主窗體控制元件,通過委託實現

主窗體中包含一個標籤label1和一個按鈕button1 程式碼如下: public void ChangeLabel(string text) { label1.Text = text; } private void button1_Click(o

Object-C定義實現協議

如果嘗試使用自定義類(例如,人類(person類)、地址簿類(myBook類)、分數類(Fraction類))中的copy方法,如 myBook = [myBook mutableCopy]; person = [Person copy];等類似的操作,將會收到一條異

python:定義迭代行為的實現

#!/usr/bin/env python # -*- coding: utf-8 -*- # @author : cat # @date : 2017/6/23. class

c#(winform)定義ListItem方便ComboBox添加Item項

urn left over string his 定義 return box item 1.定義ListItem類 public class ListItem { private string _key = string.Empty;

Lambda語句創建定義型時,也可指定某種特定型,方法是在new與{}之間寫上型名稱

特定 pan sel lambda語句 lam {} where distinct select 如: var fc =...ChildFath = fc.Select(c => new Child_Father { child = c.child, father =

工作總結 Rezor 裏面的一些小知識----定義型 放在標簽值 會直接跳過去

直接 技術 例如 images 定義變量 png 索引 log blog 0 的時候不報錯 1 的時候 報錯了 原因 是 imagesname[i] 索引超出了 為什麽在 上面 報錯呢? 不在這裏報錯呢? 說明了 Rezor 對於 自定義的變量 放在標

laravel5.4定義ajax請求響應

accep 是把 post pos 放置 source 接收 尋找 但是 本人小白在it界混跡一年之久暫時沒有什麽成績只是把所以到的和大家分享一下,在工作和學習的過程中一直追求美觀,但是對於我來說畢竟實力有限,每當遇到一些返回或者是網站或者項目中的返回給用戶的友好提示的時

Idea_學習_03_IDEA使定義型的文件進行代碼高亮識別

segment tar register 定義 類型 自定義類 pos edi ref 如果你只是想用xml的編輯模式來編輯*.screen文件的話,可以在 Settings->Editor->File Types 中,在Recognized File Ty

C# 有關控件、定義事件的委托鏈的獲取、移除操作

ons class 單擊 spa inf += finish ati pre 直接來代碼吧,這樣幹脆直接,也不耽誤我午休了。一切盡在源碼中。 public class ControlEventTool { /// <summary>

java定義型 作為HashMap的Key值 (Pair<V,K>為例)

由於 con als void hash system 進行 原型 自定義 由於是自定義類型,所以HashMap中的equals()函數和hashCode()函數都需要自定義覆蓋。 不然內容相同的對象對應的hashCode會不同,無法發揮算法的正常功能,覆蓋equals函

資料結構與演算法----定義函式與資料成員

近期在梳理知識,做一個小結,希望自己能多多使用 在標頭檔案中: enum sign {plus, minus}; class Accruency { public: Accruency(sign s = plus, unsigned long d = 0, unsigned in

spring定義@AutoWired標識的元素注入為null

最近在做專案的時候,發現程式執行的時候有一個nullpointer exception,一臉懵逼因為感覺程式沒什麼邏輯。後來發現是因為new出來的component不會自動注入它的元素。 現象:@Component修飾的自定義普通類中@Autowired屬性為null 原因:如果是通過new例項化的物件,