অ্যাপল প্ল্যাটফর্মে ডেটা পড়ুন এবং লিখুন

(ঐচ্ছিক) ফায়ারবেস স্থানীয় এমুলেটর স্যুটের সাথে প্রোটোটাইপ এবং পরীক্ষা করুন

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

একটি রিয়েলটাইম ডাটাবেস এমুলেটর হল স্থানীয় এমুলেটর স্যুটের অংশ, যা আপনার অ্যাপকে আপনার অনুকরণ করা ডাটাবেস সামগ্রী এবং কনফিগারেশনের সাথে ইন্টারঅ্যাক্ট করতে সক্ষম করে, সেইসাথে ঐচ্ছিকভাবে আপনার অনুকরণ করা প্রকল্প সংস্থানগুলি (ফাংশন, অন্যান্য ডেটাবেস এবং নিরাপত্তা নিয়ম)।

রিয়েলটাইম ডেটাবেস এমুলেটর ব্যবহার করার জন্য মাত্র কয়েকটি ধাপ জড়িত:

  1. এমুলেটরের সাথে সংযোগ করতে আপনার অ্যাপের পরীক্ষা কনফিগারে কোডের একটি লাইন যোগ করা হচ্ছে।
  2. আপনার স্থানীয় প্রকল্প ডিরেক্টরি রুট, দৌড়ানো থেকে firebase emulators:start
  3. যথারীতি রিয়েলটাইম ডেটাবেস প্ল্যাটফর্ম SDK ব্যবহার করে বা রিয়েলটাইম ডেটাবেস REST API ব্যবহার করে আপনার অ্যাপের প্রোটোটাইপ কোড থেকে কল করা।

বিস্তারিত রিয়েলটাইম ডাটাবেস এবং ক্লাউড কার্যাবলী জড়িত, walkthrough পাওয়া যায়। এছাড়াও আপনি কটাক্ষপাত থাকা উচিত স্থানীয় এমুলেটর সুইট ভূমিকা

একটি FIRDatabaseReference পান

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

সুইফট

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
var ref: DatabaseReference!

ref = Database.database().reference()

উদ্দেশ্য গ

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
@property (strong, nonatomic) FIRDatabaseReference *ref;

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

ডেটা লিখুন

এই দস্তাবেজটি ফায়ারবেস ডেটা পড়ার এবং লেখার মৌলিক বিষয়গুলি কভার করে৷

Firebase তথ্য একটি লেখা হয় Database রেফারেন্স এবং রেফারেন্স একটি অ্যাসিঙ্ক্রোনাস শ্রোতা যুক্ত করে উদ্ধার করা হয়। শ্রোতা ডেটার প্রাথমিক অবস্থার জন্য একবার ট্রিগার হয় এবং আবার যে কোনো সময় ডেটা পরিবর্তন হয়।

মৌলিক লেখার ক্রিয়াকলাপ

মৌলিক লেখার অপারেশন জন্য, আপনি ব্যবহার করতে পারেন setValue , একটি নির্দিষ্ট রেফারেন্স এ ডেটা সংরক্ষণ যে পথ যে কোনো বিদ্যমান তথ্য প্রতিস্থাপন। আপনি এই পদ্ধতিটি ব্যবহার করতে পারেন:

  • নিম্নরূপ উপলব্ধ JSON প্রকারের সাথে সঙ্গতিপূর্ণ পাস প্রকার:
    • NSString
    • NSNumber
    • NSDictionary
    • NSArray

উদাহরণস্বরূপ, আপনার সাথে একটি ব্যবহারকারী যোগ করতে পারেন setValue নিম্নরূপ:

সুইফট

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
self.ref.child("users").child(user.uid).setValue(["username": username])

উদ্দেশ্য গ

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
[[[self.ref child:@"users"] child:authResult.user.uid]
    setValue:@{@"username": username}];

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

সুইফট

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
self.ref.child("users/\(user.uid)/username").setValue(username)

উদ্দেশ্য গ

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
[[[[_ref child:@"users"] child:user.uid] child:@"username"] setValue:username];

ডেটা পড়ুন

মান ইভেন্টের জন্য শুনে ডেটা পড়ুন

একটি পাথ এ ডেটা পড়তে এবং পরিবর্তন শোনার জন্য, ব্যবহার observeEventType:withBlock এর FIRDatabaseReference পালন করা FIRDataEventTypeValue ইভেন্ট নেই।

ইভেন্টের ধরণ সাধারণ ব্যবহার
FIRDataEventTypeValue একটি পথের সম্পূর্ণ বিষয়বস্তুর পরিবর্তনের জন্য পড়ুন এবং শুনুন।

আপনি ব্যবহার করতে পারেন FIRDataEventTypeValue , একজন প্রদত্ত পথ এ ডেটা পড়তে ঘটনা যেমন ইভেন্টের জন্য নির্ধারিত সময়ে বিদ্যমান। এই পদ্ধতিটি একবার ট্রিগার করা হয় যখন শ্রোতা সংযুক্ত থাকে এবং আবার প্রতিবার ডেটা, যেকোন শিশু সহ, পরিবর্তন হয়। ঘটনা কলব্যাক একটি পাস করা হয়েছে snapshot শিশু ডেটা সহ যে অবস্থানে সমস্ত ডেটা, রয়েছে। যদি কোন তথ্য নেই, স্ন্যাপশট ফিরে আসবে false আপনি কল যখন exists() এবং nil যখন আপনি তার পড়া value সম্পত্তি।

নিম্নলিখিত উদাহরণটি একটি সামাজিক ব্লগিং অ্যাপ্লিকেশন প্রদর্শন করে যা ডাটাবেস থেকে একটি পোস্টের বিবরণ পুনরুদ্ধার করে:

সুইফট

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
refHandle = postRef.observe(DataEventType.value, with: { snapshot in
  // ...
})

উদ্দেশ্য গ

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
_refHandle = [_postRef observeEventType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
  NSDictionary *postDict = snapshot.value;
  // ...
}];

শ্রোতা একটি পায় FIRDataSnapshot যে তার মধ্যে ইভেন্টের জন্য নির্ধারিত সময়ে ডাটাবেসের মধ্যে নির্দিষ্ট অবস্থানে তথ্য ধারণ value সম্পত্তি। আপনি যেমন উপযুক্ত নেটিভ টাইপ, এর মান ধার্য করতে পারেন NSDictionary । কোন তথ্য অবস্থানে উপস্থিত থাকলে value হয় nil

একবার ডেটা পড়ুন

getData() ব্যবহার করে একবার পড়ুন

আপনার অ্যাপ অনলাইন হোক বা অফলাইন হোক ডাটাবেস সার্ভারের সাথে মিথস্ক্রিয়া পরিচালনা করার জন্য SDK ডিজাইন করা হয়েছে।

সাধারণত, ব্যাকএন্ড থেকে ডেটার আপডেটের বিজ্ঞপ্তি পেতে ডেটা পড়ার জন্য আপনার উপরে বর্ণিত মান ইভেন্ট কৌশলগুলি ব্যবহার করা উচিত। এই কৌশলগুলি আপনার ব্যবহার এবং বিলিং হ্রাস করে এবং আপনার ব্যবহারকারীদের অনলাইন এবং অফলাইনে যাওয়ার সাথে সাথে সেরা অভিজ্ঞতা দেওয়ার জন্য অপ্টিমাইজ করা হয়েছে৷

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

নিম্নলিখিত উদাহরণটি দেখায় যে ডাটাবেস থেকে একবার ব্যবহারকারীর সর্বজনীন-মুখী ব্যবহারকারীর নাম পুনরুদ্ধার করা:

সুইফট

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
ref.child("users/\(uid)/username").getData(completion:  { error, snapshot in
  guard error == nil else {
    print(error!.localizedDescription)
    return;
  }
  let userName = snapshot.value as? String ?? "Unknown";
});

উদ্দেশ্য গ

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
NSString *userPath = [NSString stringWithFormat:@"users/%@/username", uid];
[[ref child:userPath] getDataWithCompletionBlock:^(NSError * _Nullable error, FIRDataSnapshot * _Nonnull snapshot) {
  if (error) {
    NSLog(@"Received an error %@", error);
    return;
  }
  NSString *userName = snapshot.value;
}];

অপ্রয়োজনীয় ব্যবহার getData() ব্যান্ডউইথ ব্যবহার বাড়াতে এবং কর্মক্ষমতা ক্ষতি, যা উপরে দেখানো একটি রিয়েলটাইম শ্রোতা ব্যবহার করে প্রতিরোধ করা যায় হতে পারে।

পর্যবেক্ষকের সাথে একবার ডেটা পড়ুন

কিছু ক্ষেত্রে আপনি সার্ভারে একটি আপডেট করা মান পরীক্ষা করার পরিবর্তে স্থানীয় ক্যাশে থেকে মান অবিলম্বে ফেরত দিতে চাইতে পারেন। সেসব ক্ষেত্রে আপনি ব্যবহার করতে পারেন observeSingleEventOfType অবিলম্বে স্থানীয় ডিস্ক ক্যাশে থেকে ডেটা জন্য।

এটি এমন ডেটার জন্য উপযোগী যেগুলি শুধুমাত্র একবার লোড করতে হবে এবং ঘন ঘন পরিবর্তন হবে বলে আশা করা হয় না বা সক্রিয় শোনার প্রয়োজন হয় না। উদাহরণস্বরূপ, পূর্ববর্তী উদাহরণগুলিতে ব্লগিং অ্যাপটি ব্যবহারকারীর প্রোফাইল লোড করতে এই পদ্ধতিটি ব্যবহার করে যখন তারা একটি নতুন পোস্ট লিখতে শুরু করে:

সুইফট

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
let userID = Auth.auth().currentUser?.uid
ref.child("users").child(userID!).observeSingleEvent(of: .value, with: { snapshot in
  // Get user value
  let value = snapshot.value as? NSDictionary
  let username = value?["username"] as? String ?? ""
  let user = User(username: username)

  // ...
}) { error in
  print(error.localizedDescription)
}

উদ্দেশ্য গ

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
NSString *userID = [FIRAuth auth].currentUser.uid;
[[[_ref child:@"users"] child:userID] observeSingleEventOfType:FIRDataEventTypeValue withBlock:^(FIRDataSnapshot * _Nonnull snapshot) {
  // Get user value
  User *user = [[User alloc] initWithUsername:snapshot.value[@"username"]];

  // ...
} withCancelBlock:^(NSError * _Nonnull error) {
  NSLog(@"%@", error.localizedDescription);
}];

ডেটা আপডেট করা বা মুছে ফেলা

নির্দিষ্ট ক্ষেত্র আপডেট করুন

একযোগে অন্যান্য শিশু নোড মুছে যাওয়ার ছাড়া একটি নোডের নির্দিষ্ট শিশুদের লিখতে, ব্যবহার updateChildValues পদ্ধতি।

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

সুইফট

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
guard let key = ref.child("posts").childByAutoId().key else { return }
let post = ["uid": userID,
            "author": username,
            "title": title,
            "body": body]
let childUpdates = ["/posts/\(key)": post,
                    "/user-posts/\(userID)/\(key)/": post]
ref.updateChildValues(childUpdates)

উদ্দেশ্য গ

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
NSString *key = [[_ref child:@"posts"] childByAutoId].key;
NSDictionary *post = @{@"uid": userID,
                       @"author": username,
                       @"title": title,
                       @"body": body};
NSDictionary *childUpdates = @{[@"/posts/" stringByAppendingString:key]: post,
                               [NSString stringWithFormat:@"/user-posts/%@/%@/", userID, key]: post};
[_ref updateChildValues:childUpdates];

এই উদাহরণটিতে ব্যবহার childByAutoId এ থাকা সমস্ত ব্যবহারকারীর জন্য পোস্ট ধারণকারী নোড একটি পোস্ট তৈরি করতে /posts/$postid এবং একই সঙ্গে কী পুনরুদ্ধার getKey() কী তারপর ব্যবহারকারীর পোস্টে একটি দ্বিতীয় এন্ট্রি তৈরি করতে ব্যবহার করা যেতে পারে /user-posts/$userid/$postid

এই পাথ ব্যবহার করে, আপনি একটি একক কলের সাথে তাদেরকে JSON গাছ একাধিক অবস্থানে যুগপত আপডেট সম্পাদন করতে পারবেন updateChildValues যেমন কিভাবে এই উদাহরণে উভয় স্থানে নতুন পোস্ট তৈরি করে যেমন। এইভাবে করা যুগপত আপডেটগুলি পরমাণু: হয় সমস্ত আপডেট সফল হয় বা সমস্ত আপডেট ব্যর্থ হয়।

একটি সমাপ্তি ব্লক যোগ করুন

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

সুইফট

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
ref.child("users").child(user.uid).setValue(["username": username]) {
  (error:Error?, ref:DatabaseReference) in
  if let error = error {
    print("Data could not be saved: \(error).")
  } else {
    print("Data saved successfully!")
  }
}

উদ্দেশ্য গ

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
[[[_ref child:@"users"] child:user.uid] setValue:@{@"username": username} withCompletionBlock:^(NSError *error, FIRDatabaseReference *ref) {
  if (error) {
    NSLog(@"Data could not be saved: %@", error);
  } else {
    NSLog(@"Data saved successfully.");
  }
}];

ডেটা মুছুন

ডিলিট ডেটাতে সহজ উপায় কল হয় removeValue যে তথ্য অবস্থানে একটি রেফারেন্সে।

এছাড়াও আপনি নির্দিষ্ট করে মুছে দিতে পারেন nil যেমন অন্য লেখ অপারেশন জন্য মান হিসাবে setValue বা updateChildValues । আপনার সাথে এই কৌশল ব্যবহার করতে পারেন updateChildValues একটি একক API কল একাধিক শিশু মুছে দিন।

শ্রোতাদের বিচ্ছিন্ন করুন

পর্যবেক্ষকদের স্বয়ংক্রিয়ভাবে যখন আপনি একটি ছেড়ে ডেটা সিঙ্ক করা বন্ধ করেন না ViewController । যদি একটি পর্যবেক্ষক সঠিকভাবে সরানো না হয়, তবে এটি স্থানীয় মেমরিতে ডেটা সিঙ্ক করতে থাকে। একটি পর্যবেক্ষক আর প্রয়োজন থাকে, তখন তা যুক্ত ক্ষণস্থায়ী দ্বারা অপসারণ FIRDatabaseHandle করার removeObserverWithHandle পদ্ধতি।

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

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

কলিং removeObserverWithHandle বা removeAllObservers একটি শ্রোতা স্বয়ংক্রিয়ভাবে তার সন্তানের নোড নিবন্ধিত শ্রোতাকে মুছে যায় না করুন; সেগুলি অপসারণ করার জন্য আপনাকে অবশ্যই সেই রেফারেন্স বা হ্যান্ডেলগুলির ট্র্যাক রাখতে হবে।

লেনদেন হিসাবে ডেটা সংরক্ষণ করুন

যখন ডেটা আছে যা বৃদ্ধিজনিত কাউন্টারে যেমন সমবর্তী পরিবর্তন, দ্বারা ক্ষতিগ্রস্ত হতে পারে সঙ্গে কাজ, আপনি একটি ব্যবহার করতে পারেন লেনদেন অপারেশন । আপনি এই অপারেশনটিকে দুটি আর্গুমেন্ট দেন: একটি আপডেট ফাংশন এবং একটি ঐচ্ছিক সমাপ্তি কলব্যাক৷ আপডেট ফাংশন একটি যুক্তি হিসাবে ডেটার বর্তমান অবস্থা নেয় এবং আপনি লিখতে চান এমন নতুন পছন্দসই অবস্থা প্রদান করে।

উদাহরণস্বরূপ, সোশ্যাল ব্লগিং অ্যাপের উদাহরণে, আপনি ব্যবহারকারীদের পোস্ট স্টার এবং আনস্টার করার অনুমতি দিতে পারেন এবং একটি পোস্ট কতগুলি স্টার পেয়েছে তার ট্র্যাক রাখতে পারেন:

সুইফট

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
ref.runTransactionBlock({ (currentData: MutableData) -> TransactionResult in
  if var post = currentData.value as? [String: AnyObject],
    let uid = Auth.auth().currentUser?.uid {
    var stars: [String: Bool]
    stars = post["stars"] as? [String: Bool] ?? [:]
    var starCount = post["starCount"] as? Int ?? 0
    if let _ = stars[uid] {
      // Unstar the post and remove self from stars
      starCount -= 1
      stars.removeValue(forKey: uid)
    } else {
      // Star the post and add self to stars
      starCount += 1
      stars[uid] = true
    }
    post["starCount"] = starCount as AnyObject?
    post["stars"] = stars as AnyObject?

    // Set value and report transaction success
    currentData.value = post

    return TransactionResult.success(withValue: currentData)
  }
  return TransactionResult.success(withValue: currentData)
}) { error, committed, snapshot in
  if let error = error {
    print(error.localizedDescription)
  }
}

উদ্দেশ্য গ

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
[ref runTransactionBlock:^FIRTransactionResult * _Nonnull(FIRMutableData * _Nonnull currentData) {
  NSMutableDictionary *post = currentData.value;
  if (!post || [post isEqual:[NSNull null]]) {
    return [FIRTransactionResult successWithValue:currentData];
  }

  NSMutableDictionary *stars = post[@"stars"];
  if (!stars) {
    stars = [[NSMutableDictionary alloc] initWithCapacity:1];
  }
  NSString *uid = [FIRAuth auth].currentUser.uid;
  int starCount = [post[@"starCount"] intValue];
  if (stars[uid]) {
    // Unstar the post and remove self from stars
    starCount--;
    [stars removeObjectForKey:uid];
  } else {
    // Star the post and add self to stars
    starCount++;
    stars[uid] = @YES;
  }
  post[@"stars"] = stars;
  post[@"starCount"] = @(starCount);

  // Set value and report transaction success
  currentData.value = post;
  return [FIRTransactionResult successWithValue:currentData];
} andCompletionBlock:^(NSError * _Nullable error,
                       BOOL committed,
                       FIRDataSnapshot * _Nullable snapshot) {
  // Transaction completed
  if (error) {
    NSLog(@"%@", error.localizedDescription);
  }
}];

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

পারমাণবিক সার্ভার-সাইড বৃদ্ধি

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

সুইফট

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
let updates = [
  "posts/\(postID)/stars/\(userID)": true,
  "posts/\(postID)/starCount": ServerValue.increment(1),
  "user-posts/\(postID)/stars/\(userID)": true,
  "user-posts/\(postID)/starCount": ServerValue.increment(1)
] as [String : Any]
Database.database().reference().updateChildValues(updates);

উদ্দেশ্য গ

দ্রষ্টব্য: এই Firebase পণ্য অ্যাপ ক্লিপ লক্ষ্যে পাওয়া যায় না।
NSDictionary *updates = @{[NSString stringWithFormat: @"posts/%@/stars/%@", postID, userID]: @TRUE,
                        [NSString stringWithFormat: @"posts/%@/starCount", postID]: [FIRServerValue increment:@1],
                        [NSString stringWithFormat: @"user-posts/%@/stars/%@", postID, userID]: @TRUE,
                        [NSString stringWithFormat: @"user-posts/%@/starCount", postID]: [FIRServerValue increment:@1]};
[[[FIRDatabase database] reference] updateChildValues:updates];

এই কোড একটি লেনদেন অপারেশন ব্যবহার করে না, তাই এটি স্বয়ংক্রিয়ভাবে পুনরায় চালানো হয় না যদি একটি বিরোধপূর্ণ আপডেট থাকে। যাইহোক, যেহেতু ইনক্রিমেন্ট অপারেশন সরাসরি ডাটাবেস সার্ভারে ঘটে, তাই বিরোধের কোন সুযোগ নেই।

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

অফলাইনে ডেটা নিয়ে কাজ করুন

যদি কোনো ক্লায়েন্ট তার নেটওয়ার্ক সংযোগ হারিয়ে ফেলে, তাহলে আপনার অ্যাপ সঠিকভাবে কাজ করতে থাকবে।

ফায়ারবেস ডাটাবেসের সাথে সংযুক্ত প্রতিটি ক্লায়েন্ট যেকোনো সক্রিয় ডেটার নিজস্ব অভ্যন্তরীণ সংস্করণ বজায় রাখে। যখন ডেটা লেখা হয়, এটি প্রথমে এই স্থানীয় সংস্করণে লেখা হয়। ফায়ারবেস ক্লায়েন্ট তারপর সেই ডেটাটিকে দূরবর্তী ডাটাবেস সার্ভারের সাথে এবং অন্যান্য ক্লায়েন্টদের সাথে "সর্বোত্তম প্রচেষ্টা" ভিত্তিতে সিঙ্ক্রোনাইজ করে।

ফলস্বরূপ, সার্ভারে কোনো ডেটা লেখার আগে, সমস্ত ডাটাবেসে লিখিত স্থানীয় ঘটনাগুলিকে অবিলম্বে ট্রিগার করে। এর মানে নেটওয়ার্ক লেটেন্সি বা সংযোগ নির্বিশেষে আপনার অ্যাপ প্রতিক্রিয়াশীল থাকে।

একবার সংযোগ পুনঃস্থাপিত হলে, আপনার অ্যাপ ইভেন্টের উপযুক্ত সেট পায় যাতে ক্লায়েন্ট বর্তমান সার্ভারের অবস্থার সাথে সিঙ্ক করে, কোনো কাস্টম কোড না লিখেই।

আমরা অফলাইনে আচরণ সম্পর্কে আরো আলোচনা করব আরও জানুন সম্পর্কে অনলাইন ও অফলাইন ক্ষমতা

পরবর্তী পদক্ষেপ