Apple প্ল্যাটফর্মে ডেটার তালিকা নিয়ে কাজ করা

FIRDatabaseReference পান

ডেটাবেস থেকে ডেটা পড়তে বা লিখতে, আপনার FIRDatabaseReference-এর একটি ইনস্ট্যান্স প্রয়োজন:

Swift

মনে রাখবেন: এই Firebase প্রোডাক্ট অ্যাপ ক্লিপ টার্গেটে উপলভ্য নয়।
var ref: DatabaseReference!

ref = Database.database().reference()

Objective-C

মনে রাখবেন: এই Firebase প্রোডাক্ট অ্যাপ ক্লিপ টার্গেটে উপলভ্য নয়।
@property (strong, nonatomic) FIRDatabaseReference *ref;

self.ref = [[FIRDatabase database] reference];

তালিকা পড়া ও লেখা

ডেটার তালিকায় যোগ করা

মাল্টিইউজার অ্যাপ্লিকেশনে কোনও তালিকায় ডেটা যোগ করতে childByAutoId পদ্ধতি ব্যবহার করুন। নির্দিষ্ট Firebase রেফারেন্সে নতুন চাইল্ড যোগ করা হলে, childByAutoId পদ্ধতিটি প্রতিবার একটি অনন্য কী তৈরি করে। তালিকায় প্রতিটি নতুন এলিমেন্টের জন্য এইসব অটোমেটিক তৈরি হওয়া কী ব্যবহার করে, একাধিক ক্লায়েন্ট একই লোকেশনে একই সময়ে কোনও রাইট কনফ্লিক্ট ছাড়াই চাইল্ড যোগ করতে পারে। childByAutoId-এর তৈরি করা অনন্য কী টাইমস্ট্যাম্পের উপর ভিত্তি করে তৈরি হয়, তাই তালিকার আইটেমগুলি অটোমেটিক কালানুক্রমিকভাবে সাজানো হয়।

childByAutoId মেথড থেকে পাওয়া নতুন ডেটার রেফারেন্স ব্যবহার করে আপনি সন্তানের অটোমেটিক তৈরি হওয়া কী-এর ভ্যালু পেতে পারেন অথবা সন্তানের জন্য ডেটা সেট করতে পারেন। childByAutoId রেফারেন্সে getKey কল করলে অটোমেটিক জেনারেট হওয়া কী রিটার্ন করে।

আপনার ডেটা স্ট্রাকচার ফ্ল্যাটেন করার প্রসেস সহজ করতে, আপনি এইসব অটোমেটিক তৈরি হওয়া কী ব্যবহার করতে পারবেন। আরও তথ্যের জন্য, ডেটা ফ্যান-আউট উদাহরণ দেখুন।

চাইল্ড ইভেন্ট শোনা

কোনও নোডের চাইল্ডের সাথে হওয়া নির্দিষ্ট অপারেশনের প্রতিক্রিয়া হিসেবে চাইল্ড ইভেন্ট ট্রিগার করা হয়। যেমন, childByAutoId মেথডের মাধ্যমে নতুন চাইল্ড যোগ করা অথবা updateChildValues মেথডের মাধ্যমে চাইল্ড আপডেট করা।

ইভেন্টের প্রকার সাধারণ ব্যবহার
FIRDataEventTypeChildAdded আইটেমের তালিকা পাওয়া বা আইটেমের তালিকায় যোগ করা আইটেম সম্পর্কে শোনা। আগে থেকে থাকা প্রতিটি সন্তানের জন্য এই ইভেন্ট একবার করে ট্রিগার করা হয় এবং তারপরে নির্দিষ্ট পাথে নতুন সন্তান যোগ করা হলে প্রতিবার ট্রিগার করা হয়। শ্রোতাকে নতুন সন্তানের ডেটা সহ একটি স্ন্যাপশট পাঠানো হয়।
FIRDataEventTypeChildChanged তালিকায় থাকা আইটেমে কোনও পরিবর্তন হলে সেই বিষয়ে শুনুন। চাইল্ড নোডে কোনও পরিবর্তন করা হলে এই ইভেন্ট ট্রিগার হয়। এর মধ্যে চাইল্ড নোডের বংশধরদের মধ্যে করা যেকোনও পরিবর্তন অন্তর্ভুক্ত। ইভেন্ট লিসনারকে পাঠানো স্ন্যাপশটে বাচ্চার জন্য আপডেট করা ডেটা থাকে।
FIRDataEventTypeChildRemoved তালিকা থেকে কোনও আইটেম সরানো হলে সেই বিষয়ে শোনো। এই ইভেন্টটি তখন ট্রিগার হয় যখন কোনও অবিলম্বে চাইল্ডকে সরিয়ে দেওয়া হয়। কলব্যাক ব্লকে পাস করা স্ন্যাপশটে সরিয়ে দেওয়া চাইল্ডের ডেটা থাকে।
FIRDataEventTypeChildMoved ক্রমিক তালিকায় আইটেমের ক্রম পরিবর্তন হলে সেই বিষয়ে শুনুন। কোনও আপডেট যদি চাইল্ডের ক্রম পরিবর্তন করে, তাহলে এই ইভেন্ট ট্রিগার করা হয়। এটি queryOrderedByChild বা queryOrderedByValue-এর মাধ্যমে অর্ডার করা ডেটার সাথে ব্যবহার করা হয়।

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

Swift

মনে রাখবেন: এই Firebase প্রোডাক্ট অ্যাপ ক্লিপ টার্গেটে উপলভ্য নয়।
// Listen for new comments in the Firebase database
commentsRef.observe(.childAdded, with: { (snapshot) -> Void in
  self.comments.append(snapshot)
  self.tableView.insertRows(
    at: [IndexPath(row: self.comments.count - 1, section: self.kSectionComments)],
    with: UITableView.RowAnimation.automatic
  )
})
// Listen for deleted comments in the Firebase database
commentsRef.observe(.childRemoved, with: { (snapshot) -> Void in
  let index = self.indexOfMessage(snapshot)
  self.comments.remove(at: index)
  self.tableView.deleteRows(
    at: [IndexPath(row: index, section: self.kSectionComments)],
    with: UITableView.RowAnimation.automatic
  )
})

Objective-C

মনে রাখবেন: এই Firebase প্রোডাক্ট অ্যাপ ক্লিপ টার্গেটে উপলভ্য নয়।
// Listen for new comments in the Firebase database
[_commentsRef
              observeEventType:FIRDataEventTypeChildAdded
              withBlock:^(FIRDataSnapshot *snapshot) {
                [self.comments addObject:snapshot];
                [self.tableView insertRowsAtIndexPaths:@[
                  [NSIndexPath indexPathForRow:self.comments.count - 1 inSection:kSectionComments]
                ]
                                      withRowAnimation:UITableViewRowAnimationAutomatic];
              }];
// Listen for deleted comments in the Firebase database
[_commentsRef
 observeEventType:FIRDataEventTypeChildRemoved
 withBlock:^(FIRDataSnapshot *snapshot) {
   int index = [self indexOfMessage:snapshot];
   [self.comments removeObjectAtIndex:index];
   [self.tableView deleteRowsAtIndexPaths:@[[NSIndexPath indexPathForRow:index inSection:kSectionComments]]
                         withRowAnimation:UITableViewRowAnimationAutomatic];
 }];

ভ্যালু ইভেন্ট শোনা

ডেটার তালিকা পড়ার জন্য চাইল্ড ইভেন্ট শোনা সাজেস্ট করা পদ্ধতি হলেও, এমন কিছু পরিস্থিতি আছে যেখানে তালিকা রেফারেন্সে ভ্যালু ইভেন্ট শোনা কাজে লাগে।

ডেটার তালিকায় FIRDataEventTypeValue অবজারভার অ্যাটাচ করলে, ডেটার সম্পূর্ণ তালিকা একটি DataSnapshot হিসেবে রিটার্ন করবে, যা আপনি পরে লুপ করে আলাদা আলাদা চাইল্ড অ্যাক্সেস করতে পারবেন।

কোয়েরির জন্য একটিমাত্র ম্যাচ থাকলেও, স্ন্যাপশটটি একটি তালিকা হিসেবেই দেখানো হয়; এতে শুধু একটি আইটেম থাকে। আইটেম অ্যাক্সেস করতে, আপনাকে ফলাফলের উপর লুপ করতে হবে:

Swift

মনে রাখবেন: এই Firebase প্রোডাক্ট অ্যাপ ক্লিপ টার্গেটে উপলভ্য নয়।
_commentsRef.observe(.value) { snapshot in
  for child in snapshot.children {
    ...
  }
}

Objective-C

মনে রাখবেন: এই Firebase প্রোডাক্ট অ্যাপ ক্লিপ টার্গেটে উপলভ্য নয়।
[_commentsRef
              observeEventType:FIRDataEventTypeValue
              withBlock:^(FIRDataSnapshot *snapshot) {
                // Loop over children
                NSEnumerator *children = [snapshot children];
                FIRDataSnapshot *child;
                while (child = [children nextObject]) {
                  // ...
                }
              }];

অতিরিক্ত চাইল্ড যোগ করা ইভেন্ট শোনার পরিবর্তে, আপনি যখন একটি অপারেশনে কোনও তালিকার সমস্ত চাইল্ডকে ফেচ করতে চান, তখন এই প্যাটার্নটি কার্যকর হতে পারে।

ডেটা সাজানো ও ফিল্টার করা

কী, ভ্যালু বা চাইল্ডের ভ্যালু অনুসারে সাজানো ডেটা রিট্রিভ করতে, আপনি Realtime Database FIRDatabaseQuery ক্লাস ব্যবহার করতে পারেন। এছাড়াও, আপনি সাজানো ফলাফলকে নির্দিষ্ট সংখ্যক ফলাফল বা কী বা ভ্যালুর রেঞ্জে ফিল্টার করতে পারবেন।

ডেটা সাজানো

সর্ট করা ডেটা রিট্রিভ করতে, ফলাফল কীভাবে সাজানো হবে তা নির্ধারণ করতে অর্ডার-বাই পদ্ধতির মধ্যে একটি নির্দিষ্ট করে শুরু করুন:

পদ্ধতি ব্যবহার
queryOrderedByKey চাইল্ড কী অনুযায়ী ফলাফল সাজান।
queryOrderedByValue চাইল্ড ভ্যালু অনুযায়ী ফলাফল সাজান।
queryOrderedByChild নির্দিষ্ট চাইল্ড কী বা নেস্টেড চাইল্ড পাথের ভ্যালু অনুযায়ী ফলাফল সাজান।

আপনি একবারে শুধুমাত্র একটি অর্ডার-বাই পদ্ধতি ব্যবহার করতে পারবেন। একই কোয়েরিতে একাধিকবার order-by মেথড কল করলে সমস্যা হয়।

নিচের উদাহরণে দেখানো হয়েছে যে কীভাবে কোনও ব্যবহারকারীর তারকার সংখ্যা অনুসারে সাজানো সেরা পোস্টের তালিকা পাওয়া যায়:

Swift

মনে রাখবেন: এই Firebase প্রোডাক্ট অ্যাপ ক্লিপ টার্গেটে উপলভ্য নয়।
// My top posts by number of stars
let myTopPostsQuery = ref.child("user-posts").child(getUid()).queryOrdered(byChild: "starCount")

Objective-C

মনে রাখবেন: এই Firebase প্রোডাক্ট অ্যাপ ক্লিপ টার্গেটে উপলভ্য নয়।
// My top posts by number of stars
FIRDatabaseQuery *myTopPostsQuery = [[[self.ref child:@"user-posts"]
                                      child:[super getUid]]
                                     queryOrderedByChild:@"starCount"];

এই কোয়েরি ব্যবহারকারীর পোস্টগুলি ডেটাবেসে থাকা পাথ থেকে তার ব্যবহারকারীর আইডির ভিত্তিতে পুনরুদ্ধার করে, প্রতিটি পোস্ট কতগুলি স্টার পেয়েছে সেই অনুযায়ী সাজানো হয়। ইনডেক্স কী হিসেবে আইডি ব্যবহার করার এই টেকনিককে ডেটা ফ্যান-আউট বলা হয়, আপনি আপনার ডেটাবেস স্ট্রাকচার করুন লিঙ্কে গিয়ে এই বিষয়ে আরও জানতে পারবেন।

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

"posts": {
  "ts-functions": {
    "metrics": {
      "views" : 1200000,
      "likes" : 251000,
      "shares": 1200,
    },
    "title" : "Why you should use TypeScript for writing Cloud Functions",
    "author": "Doug",
  },
  "android-arch-3": {
    "metrics": {
      "views" : 900000,
      "likes" : 117000,
      "shares": 144,
    },
    "title" : "Using Android Architecture Components with Firebase Realtime Database (Part 3)",
    "author": "Doug",
  }
},

এই ক্ষেত্রে, আমাদের queryOrderedByChild কলে নেস্টেড চাইল্ডের আপেক্ষিক পাথ নির্দিষ্ট করে, আমরা metrics কী-এর অধীনে নেস্ট করা মান অনুসারে আমাদের তালিকা এলিমেন্ট অর্ডার করতে পারি।

Swift

মনে রাখবেন: এই Firebase প্রোডাক্ট অ্যাপ ক্লিপ টার্গেটে উপলভ্য নয়।
 
let postsByMostPopular = ref.child("posts").queryOrdered(byChild: "metrics/views")

Objective-C

মনে রাখবেন: এই Firebase প্রোডাক্ট অ্যাপ ক্লিপ টার্গেটে উপলভ্য নয়।
 
FIRDatabaseQuery *postsByMostPopular = [[ref child:@"posts"] queryOrderedByChild:@"metrics/views"];

অন্যান্য ডেটা কীভাবে সাজানো হয় সেই সম্পর্কে আরও জানতে, কোয়েরি ডেটা কীভাবে সাজানো হয় দেখুন।

ডেটা ফিল্টার করা

ডেটা ফিল্টার করতে, কোয়েরি তৈরি করার সময় আপনি যেকোনও সীমা বা রেঞ্জ পদ্ধতিকে অর্ডার-বাই পদ্ধতির সাথে একত্রিত করতে পারবেন।

পদ্ধতি ব্যবহার
queryLimitedToFirst ফলাফলের সাজানো তালিকার শুরু থেকে রিটার্ন করার জন্য আইটেমের সর্বাধিক সংখ্যা সেট করে।
queryLimitedToLast ফলাফলের সাজানো তালিকার শেষ থেকে রিটার্ন করার জন্য আইটেমের সর্বাধিক সংখ্যা সেট করে।
queryStartingAtValue বেছে নেওয়া অর্ডার-বাই পদ্ধতির উপর নির্ভর করে, নির্দিষ্ট কী বা ভ্যালুর থেকে বড় বা সমান আইটেম রিটার্ন করে।
queryStartingAfterValue বেছে নেওয়া অর্ডার-বাই পদ্ধতি অনুযায়ী, নির্দিষ্ট কী বা ভ্যালুর থেকে বেশি আইটেম ফেরত দিন।
queryEndingAtValue বেছে নেওয়া অর্ডার-বাই পদ্ধতির উপর নির্ভর করে, নির্দিষ্ট কী বা ভ্যালুর থেকে কম বা সমান আইটেম রিটার্ন করে।
queryEndingBeforeValue বেছে নেওয়া অর্ডার-বাই পদ্ধতির উপর নির্ভর করে, নির্দিষ্ট কী বা ভ্যালুর থেকে কম আইটেম রিটার্ন করে।
queryEqualToValue বেছে নেওয়া অর্ডার-বাই পদ্ধতির উপর নির্ভর করে, নির্দিষ্ট কী বা ভ্যালুর সমান আইটেম ফেরত দেয়।

'সাজাও' পদ্ধতির মতো নয়, আপনি একাধিক সীমা বা রেঞ্জ ফাংশন একত্রিত করতে পারবেন। যেমন, আপনি queryStartingAtValue ও queryEndingAtValue পদ্ধতি একসাথে ব্যবহার করে ফলাফলকে নির্দিষ্ট রেঞ্জের মধ্যে সীমাবদ্ধ রাখতে পারেন।

ফলাফলের সংখ্যা সীমিত করুন

নির্দিষ্ট কলব্যাকের জন্য সিঙ্ক করা যাবে এমন বাচ্চাদের সর্বাধিক সংখ্যা সেট করতে আপনি queryLimitedToFirst এবং queryLimitedToLast পদ্ধতি ব্যবহার করতে পারবেন। যেমন, আপনি যদি queryLimitedToFirst ব্যবহার করে ১০০টি কলের সীমা সেট করেন, তাহলে আপনি প্রথমে সর্বাধিক ১০০টি FIRDataEventTypeChildAdded কলব্যাক পাবেন। আপনার Firebase ডেটাবেসে ১০০টির কম আইটেম স্টোর করা থাকলে, প্রতিটি আইটেমের জন্য একটি FIRDataEventTypeChildAdded কলব্যাক ফায়ার হয়।

আইটেম পরিবর্তিত হওয়ার সাথে সাথে, আপনি FIRDataEventTypeChildAdded কোয়েরিতে যোগ করা আইটেমের জন্য কলব্যাক এবং FIRDataEventTypeChildRemoved কোয়েরি থেকে বাদ দেওয়া আইটেমের জন্য কলব্যাক পান, যাতে মোট সংখ্যা ১০০ থাকে।

নিচের উদাহরণে দেখানো হয়েছে যে কীভাবে একটি ব্লগিং অ্যাপ সব ব্যবহারকারীর ১০০টি সবচেয়ে সাম্প্রতিক পোস্টের তালিকা পেতে পারে:

Swift

মনে রাখবেন: এই Firebase প্রোডাক্ট অ্যাপ ক্লিপ টার্গেটে উপলভ্য নয়।
// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys
let recentPostsQuery = (ref?.child("posts").queryLimited(toFirst: 100))!

Objective-C

মনে রাখবেন: এই Firebase প্রোডাক্ট অ্যাপ ক্লিপ টার্গেটে উপলভ্য নয়।
// Last 100 posts, these are automatically the 100 most recent
// due to sorting by push() keys
FIRDatabaseQuery *recentPostsQuery = [[self.ref child:@"posts"] queryLimitedToFirst:100];

কী বা ভ্যালু অনুযায়ী ফিল্টার করা

কোয়েরির জন্য আরবিট্রারি শুরু, শেষ ও সমতুল্য পয়েন্ট বেছে নিতে আপনি queryStartingAtValue, queryStartingAfterValue, queryEndingAtValue, queryEndingBeforeValue ও queryEqualToValue ব্যবহার করতে পারবেন। ডেটা পেজিনেট করা বা বাচ্চাদের সাথে আইটেম খোঁজার জন্য এটি উপযোগী হতে পারে, যার একটি নির্দিষ্ট ভ্যালু আছে।

কোয়েরি ডেটা কীভাবে সাজানো হয়

এই বিভাগে, FIRDatabaseQuery ক্লাসে প্রতিটি অর্ডার-বাই পদ্ধতি অনুসারে কীভাবে ডেটা সাজানো হয় তা ব্যাখ্যা করা হয়েছে।

queryOrderedByKey

আপনার ডেটা সাজাতে queryOrderedByKey ব্যবহার করার সময়, ডেটা কী অনুসারে ক্রমবর্ধমান ক্রমে রিটার্ন করা হয়।

  1. যেসব বাচ্চার কী, ৩২-বিট পূর্ণসংখ্যা হিসেবে পার্স করা যায়, তাদের প্রথমে দেখানো হয় এবং ক্রমবর্ধমান ক্রমে সাজানো হয়।
  2. যেসব বাচ্চার কী হিসেবে স্ট্রিং ভ্যালু আছে, তাদের নাম এর পরে আসবে, অভিধান অনুযায়ী ছোট থেকে বড় ক্রমানুসারে সাজানো হবে।

queryOrderedByValue

queryOrderedByValue ব্যবহার করার সময়, বাচ্চাদের তাদের ভ্যালু অনুযায়ী সাজানো হয়। queryOrderedByChild-এর মতো একই ক্রম নির্ধারণের মাপকাঠি এখানেও প্রযোজ্য, তবে এখানে নির্দিষ্ট চাইল্ড কী-এর ভ্যালুর পরিবর্তে নোডের ভ্যালু ব্যবহার করা হয়।

queryOrderedByChild

queryOrderedByChild ব্যবহার করার সময়, নির্দিষ্ট চাইল্ড কী থাকা ডেটা নিম্নলিখিত ক্রমে সাজানো হয়:

  1. নির্দিষ্ট চাইল্ড কী-এর জন্য nil ভ্যালু সহ বাচ্চারা প্রথমে আসে।
  2. নির্দিষ্ট চাইল্ড কী-এর জন্য false ভ্যালু সহ বাচ্চারা এর পরে আসবে। একাধিক সন্তানের ভ্যালু false হলে, তাদের কী অনুযায়ী আক্ষরিকভাবে সাজানো হয়।
  3. নির্দিষ্ট চাইল্ড কী-এর জন্য true ভ্যালু সহ বাচ্চারা এর পরে আসবে। একাধিক চাইল্ডের ভ্যালু true হলে, সেগুলিকে কী অনুযায়ী লেক্সিকোগ্রাফিক অর্ডারে সাজানো হয়।
  4. এর পরে সংখ্যাসূচক মান সহ নামগুলি ছোট থেকে বড় ক্রমানুসারে সাজানো হয়। যদি নির্দিষ্ট চাইল্ড নোডের জন্য একাধিক চাইল্ডের একই সংখ্যাসূচক ভ্যালু থাকে, তাহলে সেগুলি কী অনুসারে সাজানো হয়।
  5. স্ট্রিং, সংখ্যার পরে আসে এবং ছোট থেকে বড় ক্রমানুসারে লেক্সিকোগ্রাফিক্যালি সাজানো থাকে। একাধিক সন্তানের জন্য নির্দিষ্ট করা child নোডের ভ্যালু একই হলে, সেগুলি কী অনুযায়ী লেক্সিকোগ্রাফিক ক্রমে সাজানো হয়।
  6. অবজেক্টগুলি শেষে আসে এবং কী অনুযায়ী ছোট থেকে বড় ক্রমানুসারে লেক্সিকোগ্রাফিক পদ্ধতিতে সাজানো হয়।

লিসনার আলাদা করা

আপনি কোনও ViewController ছেড়ে গেলে, পর্যবেক্ষকরা অটোমেটিক ডেটা সিঙ্ক করা বন্ধ করেন না। কোনও পর্যবেক্ষককে সঠিকভাবে সরানো না হলে, এটি লোকাল মেমরিতে ডেটা সিঙ্ক করা চালিয়ে যায় এবং ইভেন্ট হ্যান্ডলার ক্লোজারে ক্যাপচার করা যেকোনও অবজেক্ট ধরে রাখে, যা মেমরি লিকেজ ঘটাতে পারে। পর্যবেক্ষকের আর প্রয়োজন না হলে, সংশ্লিষ্ট FIRDatabaseHandle পাস করে removeObserverWithHandle মেথড ব্যবহার করে সেটি সরিয়ে দিন।

আপনি কোনও রেফারেন্সে কলব্যাক ব্লক যোগ করলে, একটি FIRDatabaseHandle রিটার্ন করা হয়। কলব্যাক ব্লক সরিয়ে দেওয়ার জন্য এইসব হ্যান্ডেল ব্যবহার করা যেতে পারে।

কোনও ডেটাবেস রেফারেন্সে একাধিক লিসনার যোগ করা হলে, কোনও ইভেন্ট তৈরি হলে প্রতিটি লিসনারকে কল করা হয়। সেই লোকেশনে ডেটা সিঙ্ক করা বন্ধ করতে, আপনাকে removeAllObservers মেথড কল করে লোকেশনে থাকা সব পর্যবেক্ষককে সরিয়ে দিতে হবে।

লিসনারে removeObserverWithHandle বা removeAllObservers কল করলে, এর চাইল্ড নোডে রেজিস্টার করা লিসনার অটোমেটিক সরিয়ে দেওয়া হয় না; আপনাকে অবশ্যই সেইসব রেফারেন্স বা হ্যান্ডেল ট্র্যাক করতে হবে তবেই সেগুলি সরানো যাবে।

পরবর্তী ধাপ