একটি NSUserDephaults হিসাবে একটি অ-সম্পত্তি-তালিকা অবজেক্ট সেট করার চেষ্টা করুন


196

আমি ভেবেছিলাম যে আমি জানতাম কী কারণে এই ত্রুটি ঘটছে, তবে আমি কী ভুল করেছি তা বুঝতে পারি না can't

আমি যে পুরো ত্রুটি বার্তাটি পাচ্ছি তা এখানে:

একটি অ-সম্পত্তি-তালিকা অবজেক্ট সেট করার চেষ্টা করুন (
   "<বিসি_পারসন: 0x8f3c140>"
) কী ব্যক্তি ডেটাআরয়ের জন্য একটি এনএসউসারডেফল্টস মান হিসাবে

আমার একটি Personক্লাস রয়েছে যা আমি মনে করি NSCodingপ্রোটোকল অনুসারে কাজ করছি , যেখানে আমার ব্যক্তি শ্রেণিতে এই দুটি পদ্ধতি রয়েছে:

- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject:self.personsName forKey:@"BCPersonsName"];
    [coder encodeObject:self.personsBills forKey:@"BCPersonsBillsArray"];
}

- (id)initWithCoder:(NSCoder *)coder {
    self = [super init];
    if (self) {
        self.personsName = [coder decodeObjectForKey:@"BCPersonsName"];
        self.personsBills = [coder decodeObjectForKey:@"BCPersonsBillsArray"];
    }
    return self;
}

App এর মধ্যে এক পর্যায়ে NSStringBC_PersonClassসেট করা থাকে, এবং আমি একটি আছে DataSaveবর্গ আমি মনে করি যে আমার মধ্যে বৈশিষ্ট্য এনকোডিং হ্যান্ডলিং করা হয় BC_PersonClass। আমি DataSaveক্লাস থেকে কোডটি ব্যবহার করছি :

- (void)savePersonArrayData:(BC_Person *)personObject
{
   // NSLog(@"name of the person %@", personObject.personsName);

    [mutableDataArray addObject:personObject];

    // set the temp array to the mutableData array
    tempMuteArray = [NSMutableArray arrayWithArray:mutableDataArray];

    // save the person object as nsData
    NSData *personEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:personObject];

    // first add the person object to the mutable array
    [tempMuteArray addObject:personEncodedObject];

    // NSLog(@"Objects in the array %lu", (unsigned long)mutableDataArray.count);

    // now we set that data array to the mutable array for saving
    dataArray = [[NSArray alloc] initWithArray:mutableDataArray];
    //dataArray = [NSArray arrayWithArray:mutableDataArray];

    // save the object to NS User Defaults
    NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
    [userData setObject:dataArray forKey:@"personDataArray"];
    [userData synchronize];
}

আমি আশা করি আপনাকে ধারণা দেওয়ার জন্য এটি যথেষ্ট কোড যা হে আমি যা করার চেষ্টা করছি। আবার আমি জানি আমার সমস্যাটি কীভাবে আমি আমার বিসি_পারসন ক্লাসে আমার সম্পত্তিগুলি এনকোড করছি, তার সাথে আমি কী ভুল করছি তা ঠিক বুঝতে পারি না।

সাহায্যের জন্য ধন্যবাদ!


আশ্চর্য কীভাবে আমরা এটি সম্পত্তি তালিকার অবজেক্ট কিনা তা যাচাই করতে পারি
onmyway133

that I think is conforming to the NSCoding protocolএটির জন্য ইউনিট টেস্টিং যুক্ত করা খুব সহজ এবং সত্যই এটি মূল্যবান।
rr1g0

করণীয় হ'ল আপনার প্যারামিটারগুলি পরীক্ষা করা I আমি জানতে পারলাম যে আমি একটি স্ট্রিং যুক্ত করছি যা একটি সংখ্যা ছিল that's সুতরাং এটি ব্যবহার করা উচিত নয়, তাই সমস্যা ছিল।
রাজাল

উত্তর:


272

আপনার পোস্ট করা কোডটি কাস্টম অবজেক্টগুলির একটি অ্যারে এতে সংরক্ষণ করার চেষ্টা করে NSUserDefaults। আপনি এটা করতে পারবেন না। বাস্তবায়নকারী NSCodingপদ্ধতি সাহায্য করে না। আপনি শুধুমাত্র ভালো জিনিস সংরক্ষণ করতে পারেন NSArray, NSDictionary, NSString, NSData, NSNumber, এবং NSDateNSUserDefaults

তোমার বস্তুর রূপান্তর করতে হবে NSData(যেমন আপনি কোড কিছু আছে) এবং দোকান যে NSDataমধ্যে NSUserDefaults। এমনকি আপনি একটি সংরক্ষণ করতে পারেন NSArrayএর NSDataযদি আপনি প্রয়োজন।

আপনি যখন অ্যারেটি পড়েন তখন আপনাকে NSDataআপনার BC_Personঅবজেক্টগুলি ফিরে পেতে আর্কাইভ করা দরকার ।

সম্ভবত আপনি এটি চান:

- (void)savePersonArrayData:(BC_Person *)personObject {
    [mutableDataArray addObject:personObject];

    NSMutableArray *archiveArray = [NSMutableArray arrayWithCapacity:mutableDataArray.count];
    for (BC_Person *personObject in mutableDataArray) { 
        NSData *personEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:personObject];
        [archiveArray addObject:personEncodedObject];
    }

    NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
    [userData setObject:archiveArray forKey:@"personDataArray"];
}

একটি প্রশ্ন আমার আছে। আমি যদি ব্যক্তির এনকোডডবজেক্টটিকে কোনও অ্যারে যুক্ত করতে এবং তারপরে অ্যারেরটি ব্যবহারকারী ডেটাতে রেখে দিতে চাইতাম ... আমি কি কেবল প্রতিস্থাপন করতে পারতাম: [আর্কাইভআরে অ্যাডবজেক্ট: personEncodedObject]; একটি এনএসআরির সাহায্যে অ্যাডবজেক্ট যুক্ত করুন: personEncodedObject সেই অ্যারেতে এবং তারপরে ইউজারডাটাতে সংরক্ষণ করবেন? আমি যদি বলছি তা যদি আপনি অনুসরণ করেন
আইসকোমো

তাই না? আমি মনে করি আপনি টাইপটি তৈরি করেছেন যেহেতু আপনি একই লাইনের কোডের সাথে একটি লাইন কোড প্রতিস্থাপন করতে চান। আমার কোডটি ব্যবহারকারী ডিফল্টগুলিতে এনকোডযুক্ত বস্তুর অ্যারে রাখে।
rmaddy

আমি অনুমান করেছি যে আমি হারিয়েছি কারণ আমি ভেবেছিলাম আপনি কেবল এনএসআরাই ব্যবহারকারীর ডেফাল্টগুলির সাথে ব্যবহার করতে পারবেন তবে আমি আপনার উদাহরণে দেখতে পাচ্ছি আপনি এনএসমিটেবল অ্যারে ব্যবহার করছেন। হয়তো আমি কিছু বুঝতে পারছি না ...
আইসকোমো

2
NSMutableArrayপ্রসারিত NSArray। এটি NSMutableArrayযে কোনও পদ্ধতিতে প্রত্যাশা করে তা পাস করার জন্য এটি পুরোপুরি ঠিক NSArray। মনে রাখবেন যে আসলে সঞ্চিত অ্যারে NSUserDefaultsআপনি যখন এটি পড়বেন তখন তা পরিবর্তনযোগ্য হবে।
rmaddy

1
পারফরম্যান্সে এটি কি ব্যয় করে? উদাহরণস্বরূপ, যদি এটি একটি লুপের মধ্য দিয়ে চলছে এবং একটি কাস্টম শ্রেণীর অবজেক্টকে বহুবার পপুলেট করে চলেছে তবে এনএসডাটাতে এটির পরিবর্তন করে প্রতিটিকে অ্যারেতে যুক্ত করার আগে, অ্যারেতে সাধারণ ডাটা টাইপগুলি পাস করার চেয়ে আরও বড় কোনও পারফরম্যান্স ইস্যু থাকতে পারে?
রব 85

66

অ্যারে দিয়ে চালানো এবং নিজেকে এনএসডিটাতে জিনিসগুলি এনকোড করা আমার পক্ষে অপব্যয়যুক্ত বলে মনে হচ্ছে। আপনার ত্রুটি BC_Person is a non-property-list objectআপনাকে বলছে যে ফ্রেমওয়ার্কটি আপনার ব্যক্তির অবজেক্টটি কীভাবে সিরিয়ালাইজ করতে হয় তা জানে না।

সুতরাং আপনার যা প্রয়োজন তা হ'ল এটি নিশ্চিত করা যে আপনার ব্যক্তি অবজেক্টটি এনএসকোডিংয়ের সাথে সঙ্গতিপূর্ণ তবে আপনি কেবল আপনার কাস্টম অবজেক্টগুলির অ্যারেটিকে এনএসডিটাতে রূপান্তর করতে পারবেন এবং এটি ডিফল্টে সঞ্চয় করতে পারবেন। এখানে একটি খেলার মাঠ:

সম্পাদনা করুন : NSUserDefaultsলিখনটি Xcode 7 এ ভাঙা হয়েছে যাতে খেলার মাঠ ডেটাতে আর্কাইভ করে এবং পিছনে আউটপুট প্রিন্ট করে। ইউজারডেফল্টস পদক্ষেপটি পরবর্তী সময়ে স্থির হয়ে গেলে অন্তর্ভুক্ত করা হয়

//: Playground - noun: a place where people can play

import Foundation

class Person: NSObject, NSCoding {
    let surname: String
    let firstname: String

    required init(firstname:String, surname:String) {
        self.firstname = firstname
        self.surname = surname
        super.init()
    }

    //MARK: - NSCoding -
    required init(coder aDecoder: NSCoder) {
        surname = aDecoder.decodeObjectForKey("surname") as! String
        firstname = aDecoder.decodeObjectForKey("firstname") as! String
    }

    func encodeWithCoder(aCoder: NSCoder) {
        aCoder.encodeObject(firstname, forKey: "firstname")
        aCoder.encodeObject(surname, forKey: "surname")
    }
}

//: ### Now lets define a function to convert our array to NSData

func archivePeople(people:[Person]) -> NSData {
    let archivedObject = NSKeyedArchiver.archivedDataWithRootObject(people as NSArray)
    return archivedObject
}

//: ### Create some people

let people = [Person(firstname: "johnny", surname:"appleseed"),Person(firstname: "peter", surname: "mill")]

//: ### Archive our people to NSData

let peopleData = archivePeople(people)

if let unarchivedPeople = NSKeyedUnarchiver.unarchiveObjectWithData(peopleData) as? [Person] {
    for person in unarchivedPeople {
        print("\(person.firstname), you have been unarchived")
    }
} else {
    print("Failed to unarchive people")
}

//: ### Lets try use NSUserDefaults
let UserDefaultsPeopleKey = "peoplekey"
func savePeople(people:[Person]) {
    let archivedObject = archivePeople(people)
    let defaults = NSUserDefaults.standardUserDefaults()
    defaults.setObject(archivedObject, forKey: UserDefaultsPeopleKey)
    defaults.synchronize()
}

func retrievePeople() -> [Person]? {
    if let unarchivedObject = NSUserDefaults.standardUserDefaults().objectForKey(UserDefaultsPeopleKey) as? NSData {
        return NSKeyedUnarchiver.unarchiveObjectWithData(unarchivedObject) as? [Person]
    }
    return nil
}

if let retrievedPeople = retrievePeople() {
    for person in retrievedPeople {
        print("\(person.firstname), you have been unarchived")
    }
} else {
    print("Writing to UserDefaults is still broken in playgrounds")
}

এবং ভোইলা, আপনি এনএসউজারডেফাল্টসে কাস্টম অবজেক্টগুলির একটি অ্যারে সঞ্চয় করেছেন


এই উত্তরটি শক্ত! আমার এনএসকোডারের সাথে আমার জিনিসগুলি মেনে চলছিল তবে তারা যে অ্যারেটি সঞ্চিত ছিল সেগুলি সম্পর্কে আমি ভুলে গিয়েছিলাম Thanks ধন্যবাদ, আমাকে অনেক ঘন্টা বাঁচিয়েছে!
মিকেল হেলম্যান

1
@ ড্যানিয়েল, আমি স্রেফ আপনার কোডটি খেলার মাঠের এক্সকোড into.৩ এর মতোই আটকালাম এবং এটি "লেট রিট্রিভড পিপলস: [ব্যক্তি] = পুনরুদ্ধারকারী ()!" তে একটি ত্রুটি দিচ্ছে! -> EXC_BAD_INSTRUCTION (কোড = EXC_I386_INVOP, সাবকোড = 0x0)। আমার কী সমন্বয় করা দরকার? ধন্যবাদ
রকহামার

1
@ রকহ্যামার দেখে মনে হচ্ছে এনএসউজারডেফাল্টস খেলার মাঠগুলিতে কাজ করছে না যেহেতু এক্সকোড: :( শীঘ্রই আপডেট হবে
ড্যানিয়েল গালাসকো

1
@ ড্যানিয়েল, কোনও সমস্যা নেই আমি এগিয়ে গিয়েছিলাম এবং আমার প্রকল্পে আপনার কোড inোকানো এবং এটি একটি কবজ মত কাজ করে! আমার অবজেক্ট ক্লাসে 3 টি স্ট্রিং টাইপের পাশাপাশি একটি এনএসডিট রয়েছে। আমার ডিকোড ফ্যাঙ্কে স্ট্রিংয়ের জন্য কেবল এনএসডিটকে স্থান দেওয়া দরকার। ধন্যবাদ
রকহামার

সুইফট 3 এর জন্য:func encode(with aCoder: NSCoder)
অচিন্ত্য অশোক

51

বাঁচাতে:

NSUserDefaults *currentDefaults = [NSUserDefaults standardUserDefaults];
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:yourObject];
[currentDefaults setObject:data forKey:@"yourKeyName"];

পেতে:

NSData *data = [currentDefaults objectForKey:@"yourKeyName"];
yourObjectType * token = [NSKeyedUnarchiver unarchiveObjectWithData:data];

সরানোর জন্য

[currentDefaults removeObjectForKey:@"yourKeyName"];

34

সুইফট 3 সমাধান

সাধারণ ইউটিলিটি ক্লাস

class ArchiveUtil {

    private static let PeopleKey = "PeopleKey"

    private static func archivePeople(people : [Human]) -> NSData {

        return NSKeyedArchiver.archivedData(withRootObject: people as NSArray) as NSData
    }

    static func loadPeople() -> [Human]? {

        if let unarchivedObject = UserDefaults.standard.object(forKey: PeopleKey) as? Data {

            return NSKeyedUnarchiver.unarchiveObject(with: unarchivedObject as Data) as? [Human]
        }

        return nil
    }

    static func savePeople(people : [Human]?) {

        let archivedObject = archivePeople(people: people!)
        UserDefaults.standard.set(archivedObject, forKey: PeopleKey)
        UserDefaults.standard.synchronize()
    }

}

মডেল ক্লাস

class Human: NSObject, NSCoding {

    var name:String?
    var age:Int?

    required init(n:String, a:Int) {

        name = n
        age = a
    }


    required init(coder aDecoder: NSCoder) {

        name = aDecoder.decodeObject(forKey: "name") as? String
        age = aDecoder.decodeInteger(forKey: "age")
    }


    public func encode(with aCoder: NSCoder) {

        aCoder.encode(name, forKey: "name")
        aCoder.encode(age, forKey: "age")

    }
}

কিভাবে ফোন করবেন

var people = [Human]()

people.append(Human(n: "Sazzad", a: 21))
people.append(Human(n: "Hissain", a: 22))
people.append(Human(n: "Khan", a: 23))

ArchiveUtil.savePeople(people: people)

let others = ArchiveUtil.loadPeople()

for human in others! {

    print("name = \(human.name!), age = \(human.age!)")
}

1
নিস! : ডি সেরা সুইফ্ট অভিযোজন +1
গ্যাবো কুয়াদ্রোস কারডেনাস

developer.apple.com/documentation/foundation/userdefaults/... ... "এই পদ্ধতি অপ্রয়োজনীয় এবং ব্যবহার করা উচিত নয়।" এলএল ... আপেলের কেউ টিম খেলোয়াড় নয়।
Nerdy Bunz

12

সুইফট- 4 এক্সকোড 9.1

এই কোড চেষ্টা করুন

আপনি এনএসউজারডেফল্টে ম্যাপার সঞ্চয় করতে পারবেন না, আপনি কেবল এনএসডিটা, এনএসএসটিং, এনএসএনম্বার, এনএসডিট, এনএসআরে বা এনএসডি অভিধান সংরক্ষণ করতে পারবেন।

let myData = NSKeyedArchiver.archivedData(withRootObject: myJson)
UserDefaults.standard.set(myData, forKey: "userJson")

let recovedUserJsonData = UserDefaults.standard.object(forKey: "userJson")
let recovedUserJson = NSKeyedUnarchiver.unarchiveObject(with: recovedUserJsonData)

8
এই জন্য আপনাকে ধন্যবাদ. এনএসকিয়েডআরচিভার.আরকিভাইডডাটা (সাথে রূটবজেক্ট :) আইওএস 12 এ একটি নতুন পদ্ধতিতে অবনতি হয়েছে যা ত্রুটি ছুঁড়ে ফেলেছে। আপনার কোড সম্ভবত একটি আপডেট? :)
মারসি

10

প্রথমে, rmaddy এর উত্তর (উপরে) সঠিক: বাস্তবায়ন NSCodingসাহায্য করে না। যাইহোক, আপনাকে NSCodingব্যবহার করার জন্য NSKeyedArchiverএবং এটি সমস্ত প্রয়োগ করতে হবে, সুতরাং এটি কেবল আরও একটি ধাপ ... এর মাধ্যমে রূপান্তর করা NSData

উদাহরণ পদ্ধতি

- (NSUserDefaults *) defaults {
    return [NSUserDefaults standardUserDefaults];
}

- (void) persistObj:(id)value forKey:(NSString *)key {
    [self.defaults setObject:value  forKey:key];
    [self.defaults synchronize];
}

- (void) persistObjAsData:(id)encodableObject forKey:(NSString *)key {
    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:encodableObject];
    [self persistObj:data forKey:key];
}    

- (id) objectFromDataWithKey:(NSString*)key {
    NSData *data = [self.defaults objectForKey:key];
    return [NSKeyedUnarchiver unarchiveObjectWithData:data];
}

তাই আপনি যদি আপনার মোড়ানো পারেন NSCodingএকটি বস্তু NSArrayবা NSDictionaryবা যাই হোক না কেন ...


6

একটি অভিধান সংরক্ষণ করার চেষ্টা করে আমার এই সমস্যা হয়েছিল NSUserDefaults। দেখা যাচ্ছে এটি সংরক্ষণ করবে না কারণ এতে NSNullমান রয়েছে। সুতরাং আমি কেবল একটি শব্দ পরিবর্তনীয় অভিধানে অনুলিপিটি সংরক্ষণ করে নালগুলি সরিয়ে ফেললামNSUserDefaults

NSMutableDictionary* dictionary = [NSMutableDictionary dictionaryWithDictionary:dictionary_trying_to_save];
[dictionary removeObjectForKey:@"NullKey"];
[[NSUserDefaults standardUserDefaults] setObject:dictionary forKey:@"key"];

এই ক্ষেত্রে আমি জানতাম কোন কীগুলি NSNullমান হতে পারে ।


4

সুইফট 5: Codable প্রোটোকলের পরিবর্তে ব্যবহার করা যেতে পারে NSKeyedArchiever

struct User: Codable {
    let id: String
    let mail: String
    let fullName: String
}

পছন্দের দ্বিতীয় struct হয় UserDefaults মান বস্তুর চারপাশে কাস্টম মোড়কের হয়।

struct Pref {
    static let keyUser = "Pref.User"
    static var user: User? {
        get {
            if let data = UserDefaults.standard.object(forKey: keyUser) as? Data {
                do {
                    return try JSONDecoder().decode(User.self, from: data)
                } catch {
                    print("Error while decoding user data")
                }
            }
            return nil
        }
        set {
            if let newValue = newValue {
                do {
                    let data = try JSONEncoder().encode(newValue)
                    UserDefaults.standard.set(data, forKey: keyUser)
                } catch {
                    print("Error while encoding user data")
                }
            } else {
                UserDefaults.standard.removeObject(forKey: keyUser)
            }
        }
    }
}

সুতরাং আপনি এটি এইভাবে ব্যবহার করতে পারেন:

Pref.user?.name = "John"

if let user = Pref.user {...

1
if let data = UserDefaults.standard.data(forKey: keyUser) {এবং Btw থেকে কাস্ট Userকরার Userঅর্থহীন ঠিক হয়return try JSONDecoder().decode(User.self, from: data)
লিও Dabus

4

সঙ্গে সুইফট@propertyWrapper

এতে Codableঅবজেক্টটি সংরক্ষণ করুনUserDefault

@propertyWrapper
    struct UserDefault<T: Codable> {
        let key: String
        let defaultValue: T

        init(_ key: String, defaultValue: T) {
            self.key = key
            self.defaultValue = defaultValue
        }

        var wrappedValue: T {
            get {

                if let data = UserDefaults.standard.object(forKey: key) as? Data,
                    let user = try? JSONDecoder().decode(T.self, from: data) {
                    return user

                }

                return  defaultValue
            }
            set {
                if let encoded = try? JSONEncoder().encode(newValue) {
                    UserDefaults.standard.set(encoded, forKey: key)
                }
            }
        }
    }




enum GlobalSettings {

    @UserDefault("user", defaultValue: User(name:"",pass:"")) static var user: User
}

উদাহরণস্বরূপ ব্যবহারকারী মডেল কোডিং নিশ্চিত করুন confirm

struct User:Codable {
    let name:String
    let pass:String
}

এটি কিভাবে ব্যবহার করতে

//Set value 
 GlobalSettings.user = User(name: "Ahmed", pass: "Ahmed")

//GetValue
print(GlobalSettings.user)

এটি সেরা মডেল উত্তর। স্ট্যাকার, এই উত্তরটি সঠিকভাবে স্কেলযোগ্য able
স্টিফান ভাসিলজেভিক

3

https://developer.apple.com/reference/foundation/userdefaults

একটি ডিফল্ট অবজেক্ট অবশ্যই প্রপার্টি তালিকা হতে পারে — সেটি হ'ল (বা সংগ্রহের জন্য উদাহরণগুলির সংমিশ্রণ): এনএসডাটা, এনএসএসটিং, এনএসএনম্বার, এনএসডিট, এনএসআরাই, বা এনএসডি অভিধানে।

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


3

সুইফট 5 খুব সহজ উপায়

//MARK:- First you need to encoded your arr or what ever object you want to save in UserDefaults
//in my case i want to save Picture (NMutableArray) in the User Defaults in
//in this array some objects are UIImage & Strings

//first i have to encoded the NMutableArray 
let encodedData = NSKeyedArchiver.archivedData(withRootObject: yourArrayName)
//MARK:- Array save in UserDefaults
defaults.set(encodedData, forKey: "YourKeyName")

//MARK:- When you want to retreive data from UserDefaults
let decoded  = defaults.object(forKey: "YourKeyName") as! Data
yourArrayName = NSKeyedUnarchiver.unarchiveObject(with: decoded) as! NSMutableArray

//MARK: Enjoy this arrry "yourArrayName"

এটি কেবল কোডিং স্ট্রাক্টের জন্য
কিশোর কুমার

আমি পেয়েছি: 'আর্কাইভডাটা (রূটবজেক্ট :) সহ :) ম্যাকোস 10.14 এ অবচয় করা হয়েছিল: ব্যবহার করুন + সংরক্ষণাগারভুক্ত ডেটাউইথরूटঅবজেক্ট: প্রয়োজনীয়সিকিউর কোডিং: ত্রুটি: পরিবর্তে
বহুসংখ্যার
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.