এনএসএস স্ট্রিং সম্পত্তি: অনুলিপি বা সংরক্ষণ?


331

ধরা যাক আমার কাছে একটি শ্রেণীর নাম SomeClassরয়েছে যার সাথে একটি stringসম্পত্তির নাম রয়েছে:

@interface SomeClass : NSObject
{
    NSString* name;
}

@property (nonatomic, retain) NSString* name;

@end

আমি বুঝতে পারি যে নামটি এমন একটি NSMutableStringক্ষেত্রে অর্পণ করা হতে পারে যার ফলে এটি ভুল আচরণের দিকে পরিচালিত করতে পারে।

  • স্ট্রিংগুলিতে সাধারণভাবে, এর পরিবর্তে বৈশিষ্ট্যটি ব্যবহার করা কি সবসময় ভাল ধারণা ?copyretain
  • কোনও "অনুলিপি" সম্পত্তি কি এই জাতীয় "রক্ষণাবেক্ষণ" সম্পত্তি থেকে কম দক্ষ?

6
ফলোআপ প্রশ্ন: nameমুক্তি দেওয়া উচিত deallocবা না?
চিতান

7
@ চেতন হ্যাঁ এটি করা উচিত!
জন

উত্তর:


440

যার বৈশিষ্ট্য NSCopyingপ্রোটোকলের সাথে সঙ্গতিপূর্ণ এমন এক অপরিবর্তনীয় মান শ্রেণীর বৈশিষ্ট্যগুলির জন্য , আপনার প্রায়শই copyআপনার @propertyঘোষণায় নির্দিষ্ট করা উচিত । উল্লেখ retainকরা এমন একটি বিষয় যা আপনি প্রায়শই এমন পরিস্থিতিতে চান না।

আপনি কেন এটি করতে চান তা এখানে:

NSMutableString *someName = [NSMutableString stringWithString:@"Chris"];

Person *p = [[[Person alloc] init] autorelease];
p.name = someName;

[someName setString:@"Debajit"];

বর্তমান মূল্য Person.nameসম্পত্তি সম্পত্তি ঘোষিত হয় কিনা তার উপর নির্ভর করে ভিন্ন হবে retainবা copy- এটা হতে হবে @"Debajit"যদি সম্পত্তি চিহ্নিত করা হয় retain, কিন্তু @"Chris"সম্পত্তি চিহ্নিত করা হয় যদি copy

যেহেতু প্রায় সব ক্ষেত্রেই আপনি কোনও জিনিসের পেছনের পেছনের বৈশিষ্ট্যগুলিকে পরিবর্তন করতে বাধা দিতে চান , আপনার বৈশিষ্ট্যগুলি প্রতিনিধিত্ব করে চিহ্নিত করা উচিত copy। (এবং আপনি যদি সেটার ব্যবহার না করে নিজে নিজে লিখেন তবে আপনাকে এটির পরিবর্তে @synthesizeব্যবহারের কথা মনে রাখা উচিত ))copyretain


61
এই উত্তরটি কিছু বিভ্রান্তির কারণ হতে পারে (দেখুন রবনেপিয়ের.ট . / ব্লগ / ইমপ্লিমেন্টিং -সনকপিওং ৪৯৯৯ # কমেন্ট -১২১২ )। আপনি এনএসএসস্ট্রিং সম্পর্কে একেবারে সঠিক, তবে আমি বিশ্বাস করি আপনি বিষয়টিকে কিছুটা সাধারণ করেছেন। এনএসএসটিংয়ের অনুলিপি করার কারণটি হ'ল এটির একটি সাধারণ মিউটেবল সাবক্লাস (এনএস মিউটেবল স্ট্রিং) রয়েছে। যে ক্লাসগুলির একটি মিউটেবল সাবক্লাস নেই (বিশেষত যে ক্লাসগুলি আপনি নিজেরাই লেখেন), সময় এবং স্মৃতিশক্তি নষ্ট না করার জন্য সাধারণত অনুলিপি না রেখে সেগুলি ধরে রাখা ভাল।
রব নেপিয়ার

63
আপনার যুক্তি ভুল। সময় / মেমোরির ভিত্তিতে অনুলিপি করা বা ধরে রাখতে হবে কিনা সে বিষয়ে আপনার দৃ the় সংকল্প করা উচিত নয়, আপনার পছন্দসই শব্দার্থবিদ্যার ভিত্তিতে এটি নির্ধারণ করা উচিত। এজন্য আমি আমার উত্তরে "অপরিবর্তনীয় মান শ্রেণি" শব্দটি বিশেষভাবে ব্যবহার করেছি। এটি কোনও বিষয় নয় যে কোনও শ্রেণীর পারস্পরিক পরিবর্তনযোগ্য সাবক্লাস রয়েছে, বা নিজেই পরিবর্তনযোগ্য।
ক্রিস হ্যানসন

10
এটি লজ্জার বিষয় যে ওবজ-সি প্রকারভেদে অপরিবর্তনীয়তা প্রয়োগ করতে পারে না। এটি সি ++ এর ট্রানজিটিভ কনস্টের অভাবের মতো। ব্যক্তিগতভাবে আমি কাজ করি যেন স্ট্রিংগুলি সর্বদা অস্থাবর। আমার যদি কখনও পরিবর্তনীয় স্ট্রিং ব্যবহার করার প্রয়োজন হয় তবে আমি পরে পরিবর্তন করতে পারলে আমি কখনই কোনও পরিবর্তনযোগ্য রেফারেন্স দেব না। আমি কোডের গন্ধ হিসাবে আলাদা কিছু বিবেচনা করব। ফলস্বরূপ - আমার কোডে (যে আমি একা কাজ করি) আমি আমার সমস্ত স্ট্রিং ধরে রাখি। আমি যদি কোনও দলের অংশ হিসাবে কাজ করতাম তবে আমি জিনিসগুলিকে অন্যভাবে দেখতে পারি।
ফিল্ডসওয়ার্ড

5
@ ফিল ন্যাশ: আপনি একা যে প্রকল্পগুলিতে কাজ করেন এবং অন্যদের সাথে ভাগ করেন এমন প্রকল্পগুলির জন্য বিভিন্ন স্টাইল ব্যবহার করা আমি কোড গন্ধ হিসাবে বিবেচনা করব। প্রতিটি ভাষা / ফ্রেমওয়ার্কে সাধারণ নিয়ম বা শৈলী রয়েছে যা বিকাশকারীরা সম্মত হন। বেসরকারী প্রকল্পগুলিতে এগুলি উপেক্ষা করা ভুল বলে মনে হচ্ছে। এবং আপনার যুক্তির জন্য "আমার কোডে, আমি পরিবর্তনীয় স্ট্রিংগুলি ফিরিয়ে দিচ্ছি না": এটি আপনার নিজের স্ট্রিংয়ের জন্য কাজ করতে পারে তবে ফ্রেমওয়ার্কগুলি থেকে আপনি যে স্ট্রিংগুলি পেয়েছেন সে সম্পর্কে আপনি কখনই জানেন না।
নিকোলাই রুহে

7
@ নিকোলাই আমি কেবল NSMutableStringক্ষণস্থায়ী "স্ট্রিং বিল্ডার" প্রকার (যা থেকে আমি অবিলম্বে একটি অপরিবর্তনীয় অনুলিপি গ্রহণ করি) ব্যতীত ব্যবহার করি না । আমি তাদেরকে বুদ্ধিমান ধরণের হতে পছন্দ করব - তবে আমি আসল স্ট্রিংটি পরিবর্তনযোগ্য না হলে অনুলিপিটি যে অনুলিপিটি বজায় রাখতে পারে তা আমার বেশিরভাগ উদ্বেগকে প্রশমিত করতে দেয়।
ফিল্ডসওয়ার্ড

120

অনুলিপি এনএসএসস্ট্রিংয়ের জন্য ব্যবহার করা উচিত। যদি এটি পরিবর্তনীয় হয় তবে এটি অনুলিপি করা হয়। যদি এটি না হয়, তবে এটি ঠিক ধরে রাখা হয়। ঠিক কোন অ্যাপে আপনি চাইলে শব্দার্থক শব্দগুলি (টাইপটি সর্বোত্তমভাবে করতে দিন)।


1
আমি এখনও বিচক্ষণ ও অপরিবর্তনীয় ফর্মগুলিকে বুদ্ধিমান হতে পছন্দ করব, তবে আমি বুঝতে পারি না যে অনুলিপিটি যদি মূল স্ট্রিংটি পরিবর্তনযোগ্য না হয় তবে এটি ধরে রাখা যেতে পারে - যা বেশিরভাগ পথ। ধন্যবাদ।
ফিল্ডসওয়ার্ড

25
NSStringঘোষিত সম্পত্তি উল্লেখ করার জন্য +1 যেভাবেই copyহবে retain(যদি তা পরিবর্তনযোগ্য তবে অবশ্যই)। অন্য উদাহরণ আমি মনে করতে পারেন NSNumber
ম্যাটম

এই উত্তর এবং নীচে @ জিবিওয়াই দ্বারা ভোট দেওয়াতে পার্থক্য কী?
গ্যারি লিন

67

স্ট্রিংগুলিতে সাধারণভাবে, অনুলিপিটি বজায় রাখার পরিবর্তে অনুলিপিটি ব্যবহার করা কি সবসময় ভাল ধারণা?

হ্যাঁ - সাধারণভাবে সর্বদা অনুলিপি ব্যবহার করুন।

এটি হ'ল কারণ আপনার এনএসএসটিং সম্পত্তিটি একটি এনএসএসটিং উদাহরণ বা একটি এনএস মিউটেবল স্ট্রিং উদাহরণটি পাস হতে পারে এবং অতএব আমরা সত্যই নির্ধারণ করতে পারি না যে পাস করা মান একটি পরিবর্তনযোগ্য বা পরিবর্তনযোগ্য বস্তু কিনা।

কোনও "অনুলিপি" সম্পত্তি কি এই জাতীয় "রক্ষণাবেক্ষণ" সম্পত্তি থেকে কম দক্ষ?

  • যদি আপনার সম্পত্তিটি কোনও এনএসএস স্ট্রিং উদাহরণটি পাস করা হয় তবে উত্তরটি " না " - অনুলিপি রাখা ধরে রাখার চেয়ে কম দক্ষ নয়।
    (এটি কম দক্ষ নয় কারণ এনএসএসস্ট্রিং আসলে একটি অনুলিপি সম্পাদন করতে না পারার পক্ষে যথেষ্ট স্মার্ট))

  • যদি আপনার সম্পত্তিটি NSMutableString উদাহরণ পাস করে তবে উত্তরটি হ্যাঁ " হ্যাঁ " - অনুলিপি ধরে রাখার চেয়ে কম দক্ষ।
    (এটি কম দক্ষ কারণ একটি আসল মেমরি বরাদ্দ এবং অনুলিপি অবশ্যই ঘটতে পারে তবে এটি সম্ভবত একটি আকাঙ্ক্ষিত জিনিস))

  • সাধারণত "অনুলিপি করা" সম্পত্তি বললে কম দক্ষ হওয়ার সম্ভাবনা থাকে - তবে NSCopyingপ্রোটোকল ব্যবহারের মাধ্যমে এমন একটি শ্রেণি প্রয়োগ করা সম্ভব যা "ঠিক তত দক্ষ" যেমন অনুলিপিকরণ করা যায় তেমন অনুলিপি করা যায়। এনএসএসস্ট্রিং এর উদাহরণ এটির একটি উদাহরণ।

সাধারণত (শুধু এনএসএসস্ট্রিংয়ের জন্য নয়), আমি কখন "রক্ষণাবেক্ষণ" না করে "অনুলিপি" ব্যবহার করব?

copyসতর্কতা ছাড়াই আপনি যখন সম্পত্তিটির অভ্যন্তরীণ স্থিতি পরিবর্তন করতে চান না তখন আপনার সর্বদা ব্যবহার করা উচিত । এমনকি অপরিবর্তনীয় বস্তুর জন্য - সঠিকভাবে লিখিত অপরিবর্তনীয় বস্তুগুলি অনুলিপি দক্ষতার সাথে পরিচালনা করবে (অপরিবর্তনীয়তা সম্পর্কিত পরবর্তী বিভাগটি দেখুন NSCopying)।

retainবস্তুগুলির কার্য সম্পাদনের কারণ থাকতে পারে , তবে এটি একটি রক্ষণাবেক্ষণ ওভারহেড সহ আসে - আপনার কোডের বাইরে অভ্যন্তরীণ অবস্থার পরিবর্তনের সম্ভাবনা আপনাকে অবশ্যই পরিচালনা করতে হবে। যেমন তারা বলে - শেষটি অনুকূলিত করুন।

তবে, আমি আমার ক্লাসটি অপরিবর্তনীয় বলে লিখলাম - আমি কি কেবল এটি "ধরে রাখতে" পারি না?

না - ব্যবহার copy। যদি আপনার ক্লাসটি সত্যই অপরিবর্তনীয় তবে NSCopyingআপনার ক্লাসটি copyব্যবহার করার সময় নিজেই ফিরে আসার জন্য প্রোটোকলটি প্রয়োগ করা ভাল অনুশীলন । আপনি যদি এটি করেন:

  • আপনার শ্রেণীর অন্যান্য ব্যবহারকারীরা যখন তারা ব্যবহার করবেন তখন পারফরম্যান্স সুবিধাগুলি অর্জন করবে copy
  • copyটীকা আপনার নিজের কোড আরো রক্ষণীয় তোলে - copyটীকা ইঙ্গিত করে যে আপনি কি সত্যিই এই বস্তু রাষ্ট্র অন্যত্র পরিবর্তন সম্পর্কে চিন্তা করতে হবে না।

39

আমি এই সাধারণ নিয়মটি অনুসরণ করার চেষ্টা করি:

  • আমি যখন আমার সম্পত্তিতে এটি অর্পণ করি তখন সময়ে কি আমি অবজেক্টটির মান ধরে রাখতে চাই ? কপি ব্যবহার করুন ।

  • আমি কি বস্তুটি ধরে রাখতে চাই এবং এর অভ্যন্তরীণ মানগুলি বর্তমানে কী বা ভবিষ্যতে কী হবে তা আমি যত্ন করি না ? শক্তিশালী (ধরে রাখা) ব্যবহার করুন ।

উদাহরণস্বরূপ: আমি কি "লিসা মিলার" ( অনুলিপি ) নামটি ধরে রাখতে চাই বা লিসা মিলার ( শক্তিশালী ) ব্যক্তির কাছে ধরে রাখতে চাই ? তার নাম পরে "লিসা স্মিথ" এ পরিবর্তিত হতে পারে তবে তিনি এখনও একই ব্যক্তি হবেন।


14

এই উদাহরণের মাধ্যমে অনুলিপি এবং ধরে রাখার মতো ব্যাখ্যা করা যেতে পারে:

NSMutableString *someName = [NSMutableString stringWithString:@"Chris"];

Person *p = [[[Person alloc] init] autorelease];
p.name = someName;

[someName setString:@"Debajit"];

সম্পত্তিটি যদি কপির মতো হয় তবে,

[Person name]স্ট্রিংয়ের জন্য একটি নতুন অনুলিপি তৈরি করা হবে যা স্ট্রিংয়ের বিষয়বস্তু ধারণ করবে someNamesomeNameস্ট্রিংয়ে এখন কোনও ক্রিয়াকলাপের কোনও প্রভাব পড়বে না [Person name]

[Person name]এবং someNameস্ট্রিংগুলির বিভিন্ন মেমরি ঠিকানা থাকবে।

তবে ধরে রাখার ক্ষেত্রে,

উভয়ই [Person name]কোনও নাম স্ট্রিংয়ের মতো একই মেমরি ঠিকানা রাখে, কেবল কোনও নাম স্ট্রিংয়ের ধরে রাখা গণনাটি 1 দ্বারা বাড়ানো হবে।

সুতরাং কোনও নাম স্ট্রিংয়ের যে কোনও পরিবর্তন স্ট্রিংয়ের মধ্যে প্রতিফলিত হবে [Person name]


3

নিশ্চয় কোনও সম্পত্তি ঘোষণায় 'অনুলিপি' স্থাপন করা কোনও বস্তু-কেন্দ্রিক পরিবেশের ব্যবহারের মুখে উড়ে যায় যেখানে স্তূপে থাকা বস্তুগুলিকে রেফারেন্স দ্বারা প্রেরণ করা হয় - আপনি এখানে পাবেন এমন একটি সুবিধা হ'ল কোনও অবজেক্ট পরিবর্তন করার সময় object বস্তুর সমস্ত রেফারেন্স সর্বশেষ পরিবর্তনগুলি দেখুন। অনেকগুলি ভাষা 'রেফ' বা অনুরূপ কীওয়ার্ড সরবরাহ করে যা মানের ধরণের (যেমন স্ট্যাকের কাঠামোগুলি) একই আচরণ থেকে উপকৃত হতে দেয়। ব্যক্তিগতভাবে, আমি অনুলিপি করে অনুলিপি ব্যবহার করতাম এবং যদি আমি মনে করি যে সম্পত্তিটির মূল্য এটি অর্পণ করা বস্তুটির পরিবর্তন থেকে রক্ষা করা উচিত, তবে আমি নিয়োগের সময় সেই বস্তুর অনুলিপি পদ্ধতিতে কল করতে পারি, যেমন:

p.name = [someName copy];

অবশ্যই, সেই সম্পত্তি সম্বলিত অবজেক্টটি ডিজাইন করার সময়, কেবলমাত্র আপনিই জানতে পারবেন যে নকশাটি এমন একটি প্যাটার্ন থেকে কার্যকরী হয় যেখানে অ্যাসাইনমেন্টগুলি অনুলিপিগুলি নিয়ে থাকে - কোকোভিথলভ.কমের নিম্নলিখিত কথাগুলি রয়েছে:

"যখন সেটার প্যারামিটারটি পরিবর্তনযোগ্য হতে পারে তবে আপনার কোনও অনুলিপি অ্যাকসেসর ব্যবহার করা উচিত তবে সতর্কতা ব্যতীত কোনও সম্পত্তির অভ্যন্তরীণ অবস্থা থাকতে পারে না " - সুতরাং আপনি অপ্রত্যাশিতভাবে পরিবর্তনের জন্য মানটি দাঁড়াতে পারবেন কিনা সে বিষয়ে রায় আপনার নিজের। এই দৃশ্যটি কল্পনা করুন:

//person object has details of an individual you're assigning to a contact list.

Contact *contact = [[[Contact alloc] init] autorelease];
contact.name = person.name;

//person changes name
[[person name] setString:@"new name"];
//now both person.name and contact.name are in sync.

এই ক্ষেত্রে, অনুলিপি ব্যবহার না করে, আমাদের যোগাযোগের বস্তুটি স্বয়ংক্রিয়ভাবে নতুন মানটি নিয়ে যায়; যদিও আমরা এটি ব্যবহার করি, তবে আমাদের ম্যানুয়ালি তা নিশ্চিত করতে হবে যে পরিবর্তনগুলি সনাক্ত হয়েছে এবং সিঙ্ক হয়েছে। এক্ষেত্রে, শব্দার্থবিদ্যা বজায় রাখা পছন্দসই হতে পারে; অন্যটিতে, অনুলিপি আরও উপযুক্ত হতে পারে।


1
@interface TTItem : NSObject    
@property (nonatomic, copy) NSString *name;
@end

{
    TTItem *item = [[TTItem alloc] init];    
    NSString *test1 = [NSString stringWithFormat:@"%d / %@", 1, @"Go go go"];  
    item.name = test1;  
    NSLog(@"-item.name: point = %p, content = %@; test1 = %p", item.name, item.name, test1);  
    test1 = [NSString stringWithFormat:@"%d / %@", 2, @"Back back back"];  
    NSLog(@"+item.name: point = %p, content = %@, test1 = %p", item.name, item.name, test1);
}

Log:  
    -item.name: point = 0x9a805a0, content = 1 / Go go go; test1 = 0x9a805a0  
    +item.name: point = 0x9a805a0, content = 1 / Go go go, test1 = 0x9a84660

0

এনএসএস স্ট্রিং সম্পত্তি ঘোষণার জন্য আপনার সর্বদা অনুলিপি ব্যবহার করা উচিত

@property (nonatomic, copy) NSString* name;

এটি অপরিবর্তনীয় স্ট্রিংটি ফেরত দেয় (পরিবর্তনীয় স্ট্রিংটি কেটে যাওয়ার ক্ষেত্রে) বা একটি ধরে রেখেছে স্ট্রিং ফেরত দেয় (অপরিবর্তনীয় স্ট্রিং পাস হয়ে গেলে) এই বিষয়ে আরও তথ্যের জন্য আপনার এগুলি পড়তে হবে

এনএসকোপিং প্রোটোকল রেফারেন্স

শ্রেণি এবং এর বিষয়বস্তু অপরিবর্তনীয় থাকাকালীন নতুন অনুলিপি তৈরির পরিবর্তে মূলটি ধরে রেখে এনএসকোপি প্রয়োগ করুন

মান অবজেক্টস

সুতরাং, আমাদের অপরিবর্তনীয় সংস্করণের জন্য আমরা কেবল এটি করতে পারি:

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}

-1

যেহেতু নাম একটি (অপরিবর্তনীয়) NSString, তাই আপনি অন্যকে নামটিতে সেট করে রাখলে অনুলিপি করা বা ধরে রাখা কোনও তাত্পর্য রাখে না NSString। অন্য কথায়, অনুলিপি ঠিক ধরে রাখার মতো আচরণ করে, রেফারেন্স গণনা এক এক করে বাড়িয়ে তোলে। আমি মনে করি এটি অপরিবর্তনীয় শ্রেণীর জন্য একটি স্বয়ংক্রিয় অপ্টিমাইজেশন, যেহেতু তারা পরিবর্তনযোগ্য এবং ক্লোন করার দরকার নেই। কিন্তু যখন কোনও NSMutalbeString mstrনাম সেট করা থাকে, mstrততক্ষণের লিখিত সামগ্রীটি সঠিকতার জন্য অনুলিপি করা হবে।


1
আপনি প্রকৃত প্রকারের সাথে ঘোষিত প্রকারটিকে বিভ্রান্ত করছেন। আপনি যদি কোনও "রক্ষণাবেক্ষণ" সম্পত্তি ব্যবহার করেন এবং কোনও এনএসমুটেবল স্ট্রিং বরাদ্দ করেন তবে সেই এনএস মিউটেবল স্ট্রিং ধরে রাখা হবে, তবে এখনও সংশোধন করা যায়। আপনি যদি "অনুলিপি" ব্যবহার করেন, আপনি কোনও এনএসমিটেবল স্ট্রিং বরাদ্দ করলে একটি অপরিবর্তনীয় অনুলিপি তৈরি করা হবে; তারপরে সম্পত্তিটির "অনুলিপি" কেবল ধরে রাখা হবে, কারণ পরিবর্তনীয় স্ট্রিংয়ের অনুলিপি নিজেই পরিবর্তনযোগ্য।
gnasher729

1
আপনি এখানে কিছু গুরুত্বপূর্ণ তথ্য অনুপস্থিত, আপনি যদি কোনও রক্ষণশীল ভেরিয়েবল থেকে আগত কোনও অবজেক্ট ব্যবহার করেন, যখন সেই ভেরিয়েবলটি পরিবর্তিত হয়, তবে আপনার অবজেক্টটিও যদি এটি অনুলিপি করা ভেরিয়েবল থেকে আসে, আপনার অবজেক্টের ভেরিয়েবলের বর্তমান মান থাকবে যা পরিবর্তন হবে না
ব্রায়ান পি

-1

যদি স্ট্রিংটি খুব বড় হয় তবে অনুলিপি কার্য সম্পাদনকে প্রভাবিত করবে এবং বড় স্ট্রিংয়ের দুটি অনুলিপি আরও মেমরি ব্যবহার করবে।

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.