# iOS SDK-এ ফিচার ফ্ল্যাগ

`Pushwoosh.configure.featureFlags` আপনার iOS অ্যাপকে সেই [ফিচার ফ্ল্যাগগুলো](/bn/product/audience-data-and-segmentation/feature-flags/) দেয়, যেগুলো কন্ট্রোল প্যানেলে অ্যাপ্লিকেশনের জন্য কনফিগার করা হয়েছে। Pushwoosh বর্তমান ডিভাইস এবং ব্যবহারকারীর জন্য সার্ভারে ফ্ল্যাগের নিয়মগুলো মূল্যায়ন করে, এবং SDK ফলাফল ফেরত দেয়: এই ডিভাইসের জন্য ফ্ল্যাগটি চালু আছে কি না এবং কোন প্রপার্টি মানগুলো প্রযোজ্য।

<Aside type="tip" title="বিটা ফিচার">
ফিচার ফ্ল্যাগ বিটা পর্যায়ে রয়েছে এবং শুধুমাত্র সেই প্ল্যানগুলোতে উপলব্ধ যেগুলোতে এটি অন্তর্ভুক্ত। অন্য প্ল্যানগুলোতে সার্ভার কোনো ফ্ল্যাগ ফেরত দেয় না, তাই প্রতিটি ফ্ল্যাগ সেই ডিফল্ট মানে ফিরে যায় যা আপনি কোডে পাস করেন।
</Aside>

## পূর্বশর্ত

* Pushwoosh iOS SDK 7.2.10 বা তার পরের সংস্করণ, যা [iOS SDK ওভারভিউ](/bn/developer/pushwoosh-sdk/ios-sdk/)-তে বর্ণিত পদ্ধতিতে ইন্টিগ্রেট করা হয়েছে। ফিচার ফ্ল্যাগ আবশ্যক `PushwooshFramework` এবং `PushwooshCore` মডিউলের মধ্যেই আসে, তাই আপনাকে অন্য কোনো মডিউল যোগ করতে হবে না। এগুলো iOS অ্যাপের ভেতরেই কাজ করে। অ্যাপ এক্সটেনশন, যেমন Notification Service Extension, কখনোই ফ্ল্যাগ অনুরোধ করে না।
* **Audience** → **Feature Flags**-এ তৈরি করা অন্তত একটি ফ্ল্যাগ। আপনার এর **Key** এবং এর প্রপার্টিগুলোর কী ও টাইপ প্রয়োজন। কীগুলো ঠিক সেখানে যেভাবে দেখা যায় সেভাবেই ব্যবহার করুন, অক্ষরের কেস সহ। উদাহরণস্বরূপ, `get("New_Checkout")` `new_checkout` কী-যুক্ত ফ্ল্যাগ খুঁজে পায় না।
* অ্যাপটি যদি কোনো রিভার্স প্রক্সির মাধ্যমে SDK অনুরোধ পাঠায়, তাহলে তার URL অবশ্যই `json/1.3/` দিয়ে শেষ হতে হবে। অন্যথায় SDK ফ্ল্যাগ অনুরোধ করে না, এবং প্রতিটি ফ্ল্যাগ আপনার ডিফল্ট মানে ফিরে যায়।

## একটি ফ্ল্যাগ পড়ুন

সবসময় একটি ডিফল্ট মান পাস করুন। SDK-এর কাছে ডিভাইসের জন্য ফ্ল্যাগ না আসা পর্যন্ত এটি প্রযোজ্য থাকে, এবং যখনই ফ্ল্যাগটি বিদ্যমান থাকে না, আর্কাইভ করা থাকে, বা প্ল্যানে ফিচার ফ্ল্যাগ অন্তর্ভুক্ত থাকে না।

```swift
import PushwooshFramework

let flags = Pushwoosh.configure.featureFlags

if let checkout = flags.get("new_checkout"), checkout.isEnabled {
    showNewCheckout(
        buttonColor: checkout.string(forProperty: "button_color", default: "blue") ?? "blue",
        maxItems: Int(checkout.number(forProperty: "max_items", default: 3))
    )
} else {
    showOldCheckout()
}
```

শুধু ফ্ল্যাগটি চালু আছে কি না তা যাচাই করতে `isEnabled` ব্যবহার করুন:

```swift
let isNewCheckout = Pushwoosh.configure.featureFlags.isEnabled("new_checkout", default: false)
```

Objective-C-তে `[PushwooshConfig featureFlags]` কল করুন।

## একটি ফ্ল্যাগ কী ফেরত দেয়

`get(_:)` একটি `PWFeatureFlag` অবজেক্ট ফেরত দেয়, অথবা `nil` ফেরত দেয় যখন SDK-এর কাছে এখনও ডিভাইসের জন্য ফ্ল্যাগ নেই বা ফ্ল্যাগটি উত্তরে নেই। আর্কাইভ করা ফ্ল্যাগ উত্তরে থাকে না। `get` শুধু সংরক্ষিত ফ্ল্যাগগুলো পড়ে এবং কখনোই নেটওয়ার্কের জন্য অপেক্ষা করে না। অবজেক্টটিতে এই প্রপার্টিগুলো রয়েছে:

| প্রপার্টি | টাইপ | বিবরণ |
| :---- | :---- | :---- |
| `key` | String | ফ্ল্যাগের কী। |
| `isEnabled` | Bool | এই ডিভাইসের জন্য ফ্ল্যাগটি চালু আছে কি না। |
| `ruleId` | String | যে নিয়ম ফলাফল নির্ধারণ করেছে, উদাহরণস্বরূপ `r_1a2b3c4d`। কোনো নিয়ম ডিভাইসের সাথে না মিললে `default`, এবং ফ্ল্যাগটি কিল (kill) করা হলে একটি খালি স্ট্রিং। |

প্রপার্টির টাইপের সাথে মেলে এমন মেথড দিয়ে প্রপার্টির মান পড়ুন। ফ্ল্যাগটি বন্ধ থাকলে প্রপার্টিগুলো কন্ট্রোল প্যানেলে সেট করা ডিফল্ট মানগুলো ধারণ করে।

| মেথড | ফেরত দেয় |
| :---- | :---- |
| `string(forProperty:default:)` | একটি **String** প্রপার্টির মান, অথবা আপনার ডিফল্ট মান। |
| `number(forProperty:default:)` | একটি **Number** প্রপার্টির মান `Double` হিসেবে, অথবা আপনার ডিফল্ট মান। |
| `bool(forProperty:default:)` | একটি **Boolean** প্রপার্টির মান, অথবা আপনার ডিফল্ট মান। |
| `jsonObject(forProperty:)` | অবজেক্ট ধারণকারী একটি **JSON** প্রপার্টির মান, ডিকশনারি হিসেবে, অথবা `nil`। |
| `jsonArray(forProperty:)` | অ্যারে ধারণকারী একটি **JSON** প্রপার্টির মান, অথবা `nil`। |

প্রপার্টিটি অনুপস্থিত থাকলে বা অন্য টাইপের মান ধারণ করলে প্রতিটি মেথড আপনার ডিফল্ট মান ফেরত দেয়, আর JSON মেথডগুলো `nil` ফেরত দেয়।

`get(_:)` `nil` ফেরত দিলে `isEnabled(_:default:)` ডিফল্ট মান ফেরত দেয়।

<span id="keep-flags-up-to-date" />

## ফ্ল্যাগগুলো হালনাগাদ রাখুন

SDK সর্বশেষ উত্তরটি ডিভাইসে সর্বোচ্চ 24 ঘণ্টা সংরক্ষণ করে। সংরক্ষিত ফ্ল্যাগগুলো শুধুমাত্র সেই User ID এবং অ্যাপের সেই Application Code-এর জন্য বৈধ, যেগুলোর জন্য সেগুলো অনুরোধ করা হয়েছিল। SDK সেগুলো রিফ্রেশ করে:

* একটি সেশন শুরু হলে, অর্থাৎ যখন অ্যাপটি প্রথমবার সক্রিয় হয় বা ব্যাকগ্রাউন্ডে অন্তত 30 মিনিট থাকার পরে;
* অ্যাপ ফোরগ্রাউন্ডে থাকা অবস্থায় প্রতি ঘণ্টায়;
* ডিভাইসটি পুশ নোটিফিকেশনের জন্য রেজিস্টার হওয়ার পরে, যদি আগের অনুরোধটি রেজিস্ট্রেশনের আগে পাঠানো হয়ে থাকে;
* `setUserId` দিয়ে User ID পরিবর্তনের ঠিক পরে। আগের ব্যবহারকারীর সংরক্ষিত ফ্ল্যাগগুলো বাতিল করা হয়, তাই নতুন ব্যবহারকারী কখনোই সেগুলো দেখেন না।

নতুন মানে সাড়া দিতে `PWFeatureFlagsUpdateListener` গ্রহণকারী একটি listener যোগ করুন। কোনো ফ্ল্যাগ পরিবর্তন করা রিফ্রেশের পরে মূল থ্রেডে এর `featureFlagsDidUpdate()` কল করা হয়। SDK listener-গুলোকে দুর্বল (weak) রেফারেন্সে রাখে। আপনার listener-এর একটি শক্তিশালী (strong) রেফারেন্স রাখুন, নইলে এটি রিলিজ হয়ে যাবে এবং কখনোই কল হবে না:

```swift
final class CheckoutViewController: UIViewController, PWFeatureFlagsUpdateListener {
    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        Pushwoosh.configure.featureFlags.addUpdateListener(self)
    }

    override func viewWillDisappear(_ animated: Bool) {
        Pushwoosh.configure.featureFlags.removeUpdateListener(self)
        super.viewWillDisappear(animated)
    }

    func featureFlagsDidUpdate() {
        render()
    }
}
```

নিজে ফ্ল্যাগ অনুরোধ করতে, উদাহরণস্বরূপ এমন কোনো অ্যাকশনের পরে যা ব্যবহারকারীকে অন্য একটি সেগমেন্টে নিয়ে যেতে পারে, `refresh(completion:)` কল করুন। সংরক্ষিত ফ্ল্যাগগুলো বৈধ থাকা অবস্থায় এটি প্রতি 5 মিনিটে সর্বোচ্চ একটি অনুরোধ পাঠায় এবং সেই সময়সীমার মধ্যে সংরক্ষিত ফ্ল্যাগ থেকে উত্তর দেয়। completion মূল থ্রেডে চলে:

```swift
Pushwoosh.configure.featureFlags.refresh { error in
    if let error = error as NSError? {
        let status = error.code
        // the stored flags, or your defaults, stay in effect
    }
    render()
}
```

ব্যর্থ হলে error-এর ডোমেন হয় `PWFeatureFlagsErrorDomain`, এবং এর `code` হলো HTTP স্ট্যাটাস। অনুরোধটি কোনো HTTP উত্তর না পেলে বা পাঠানো না হলে কোডটি `0` হয়, এবং সার্ভার উত্তর দিলেও উত্তরটি ব্যবহার করা না গেলে `200` হয়।

5 মিনিটের সীমা ছাড়া রিফ্রেশ পরীক্ষা করতে `Info.plist`-এ Boolean কী `Pushwoosh_FEATURE_FLAGS_DISABLE_THROTTLE`-কে `YES`-এ সেট করুন।

Pushwoosh সময়মতো ডিভাইসের সেগমেন্টগুলো মেলাতে না পারলে একটি আংশিক উত্তর ফেরত দেয়। SDK এটি ডিভাইসে সংরক্ষণ করে না, এবং পরবর্তী রিফ্রেশ সম্পূর্ণ উত্তর নিয়ে আসে।

কন্ট্রোল প্যানেলে কোনো ফ্ল্যাগ কিল (kill) করা হলে, পরবর্তী রিফ্রেশে ডিভাইসগুলো সেটি ডিফল্ট প্রপার্টি মান সহ বন্ধ অবস্থায় পায়। SDK সার্ভারে পৌঁছাতে না পারলে, সংরক্ষিত ফ্ল্যাগগুলো 24 ঘণ্টা পুরোনো না হওয়া পর্যন্ত সেগুলো ব্যবহার করতে থাকে, এবং তারপরে আপনার ডিফল্ট মানগুলো ব্যবহার করে।

<span id="log-impressions" />

## ইম্প্রেশন লগ করুন

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

```swift
let flags = Pushwoosh.configure.featureFlags
let isOn = flags.isEnabled("new_checkout", default: false)
flags.logImpression("new_checkout")
if isOn {
    showNewCheckout()
} else {
    showOldCheckout()
}
```

SDK এই অ্যাট্রিবিউটগুলো সহ `PW_FeatureFlagImpression` ইভেন্ট পাঠায়:

| অ্যাট্রিবিউট | টাইপ | মান |
| :---- | :---- | :---- |
| `flag_key` | string | ফ্ল্যাগের কী। |
| `rule_id` | string | যে নিয়ম ফলাফল নির্ধারণ করেছে, `ruleId`-এর মতো। |
| `enabled` | boolean | ফ্ল্যাগটি চালু ছিল কি না। |

আপনাকে আগে থেকে ইভেন্টটি তৈরি করতে হবে না, কারণ প্রথম ইম্প্রেশন আসার পরে Pushwoosh এই অ্যাট্রিবিউটগুলো সহ `PW_FeatureFlagImpression`-কে **Audience** → **Events**-এ যোগ করে। SDK একটি সেশনে প্রতিটি ফ্ল্যাগ, নিয়ম এবং অবস্থার জন্য একটি করে ইম্প্রেশন পাঠায়, এবং কী-এর জন্য কোনো ফ্ল্যাগ না থাকলে কিছুই পাঠায় না। পাঠানো ব্যর্থ হলে, ফ্ল্যাগটির জন্য পরবর্তী `logImpression` কল এটি আবার পাঠায়।

ইম্প্রেশনের মাধ্যমে মার্কেটাররা ফিচারটিতে পৌঁছানো ব্যবহারকারীদের একটি সেগমেন্টও তৈরি করতে পারেন: [ফিচার ফ্ল্যাগ শর্তের](/bn/product/audience-data-and-segmentation/feature-flags/#find-users-who-reached-a-feature) **ফিচারটি দেখেছে (৩০ দিন)** অবস্থা।

## মেথড রেফারেন্স

`Pushwoosh.configure.featureFlags`-এ এই মেথডগুলো রয়েছে:

| মেথড | বিবরণ |
| :---- | :---- |
| `get(_:)` | কী-এর জন্য `PWFeatureFlag` অথবা `nil` ফেরত দেয়। শুধু সংরক্ষিত ফ্ল্যাগগুলো পড়ে। |
| `isEnabled(_:default:)` | ফ্ল্যাগটি চালু আছে কি না তা ফেরত দেয়, অথবা কোনো ফ্ল্যাগ না থাকলে ডিফল্ট মান। |
| `refresh(completion:)` | ফ্ল্যাগ অনুরোধ করে, সংরক্ষিত ফ্ল্যাগগুলো বৈধ থাকা অবস্থায় প্রতি 5 মিনিটে একবারে সীমিত। completion `nil` অথবা `PWFeatureFlagsErrorDomain`-এর একটি error পায়, এবং completion নিজে `nil` হতে পারে। |
| `addUpdateListener(_:)` | কোনো ফ্ল্যাগ পরিবর্তন করা প্রতিটি রিফ্রেশের পরে listener-এর `featureFlagsDidUpdate()` কল করে। listener-কে দুর্বল রেফারেন্সে রাখা হয়। |
| `removeUpdateListener(_:)` | `addUpdateListener(_:)` দিয়ে যোগ করা একটি listener সরিয়ে দেয়। |
| `logImpression(_:)` | ফ্ল্যাগের বর্তমান নিয়ম ও অবস্থার জন্য একটি `PW_FeatureFlagImpression` ইভেন্ট পাঠায়। |