@MainActor — এটি কী, Swift অ্যাসিনক্রোনাস কোডে ব্যবহার এবং বৈশিষ্ট্য

লেখক: IT Sectr প্রকাশিত: 2026-03-19 পড়ার সময়: 8 মিনিট

@MainActor Swift ভাষায় একটি গ্লোবাল অ্যাক্টর যা প্রধান থ্রেডে কোড নির্বাহের নিশ্চয়তা দেয়। Apple Developer, 2024 অনুসারে, @MainActor UI-এর সাথে কাজ করার সময় প্রধান থ্রেডে সুইচ করাকে স্বয়ংক্রিয় করে, ডেভেলপারকে ম্যানুয়ালি DispatchQueue.main.async কল করা থেকে মুক্ত করে। অ্যানোটেশনটি Swift 5.5-এ async/await সিস্টেমের সাথে উপস্থিত হয়েছিল।

মূল পয়েন্ট

  • @MainActor — প্রধান থ্রেডে নির্বাহের নিশ্চয়তার জন্য Swift-এর গ্লোবাল অ্যাক্টর।
  • async/await সিস্টেম — ভিত্তি যার উপর @MainActor নির্মিত।
  • ক্লাস অ্যানোটেশন স্বয়ংক্রিয়ভাবে এর সব পদ্ধতি প্রধান থ্রেডে রাখে।
  • DispatchQueue.main-এর বিপরীতে, @MainActor কম্পাইলার স্তরে থ্রেড পরীক্ষা করে।
  • UI আপডেট — iOS ডেভেলপমেন্টে @MainActor ব্যবহারের প্রধান ক্ষেত্র।

@MainActor কী?

@MainActor Swift-এ একটি গ্লোবাল অ্যাক্টর যা অ্যাক্টরদের বৈশিষ্ট্যকে অ্যাপ্লিকেশনের প্রধান থ্রেডে নির্বাহের নিশ্চয়তার সাথে একত্রিত করে। এটি Swift 5.5-এ async/await এবং স্ট্রাকচার্ড কনকারেন্সির সাথে উপস্থাপিত Swift কনকারেন্সি সিস্টেমের অংশ। অ্যানোটেশনটি ডেভেলপারকে ম্যানুয়াল থ্রেড সুইচিং নিয়ে চিন্তা না করতে দেয় এবং UI ত্রুটির সংখ্যা হ্রাস করে।

Swift Concurrency-এ সংজ্ঞা এবং অবস্থান

Swift-এ অ্যাক্টর একটি রেফারেন্স টাইপ যা তার অবস্থাকে আলাদা করে এবং নিশ্চিত করে যে শুধুমাত্র একটি থ্রেড এটি পরিবর্তন করতে পারে। @MainActor একটি বিশেষ গ্লোবাল অ্যাক্টর যার নির্বাহক প্রধান থ্রেড। @MainActor দিয়ে চিহ্নিত যেকোনো কোড প্রধান থ্রেডে নির্বাহিত হয় — এমনকি যদি এটি ব্যাকগ্রাউন্ড টাস্ক থেকে কল করা হয়।

@MainActor-এর আগে, ডেভেলপাররা DispatchQueue.main.async-এর মাধ্যমে ম্যানুয়ালি প্রধান থ্রেডে সুইচ করতেন। এটি ঘন ঘন ত্রুটির উৎস ছিল: ডেভেলপাররা সুইচ করতে ভুলে যেতেন, যার ফলে প্রধান থ্রেডে UI আপডেট না হওয়ার কারণে ক্র্যাশ হতো। @MainActor টাইপ সিস্টেম স্তরে এই সমস্যার সমাধান করে।

নির্মাণের কারণ

iOS অ্যাপ্লিকেশনে বেশিরভাগ বাগের উৎস হল UI অনিরাপত্তা — ব্যাকগ্রাউন্ড থ্রেড থেকে ইন্টারফেস আপডেট করা। Apple @MainActor-কে Swift Concurrency-তে তৈরি করেছে যাতে প্রধান থ্রেডে সুইচ করা স্বয়ংক্রিয় এবং কম্পাইলার-পরীক্ষণযোগ্য হয়, যা রানটাইম ত্রুটির একটি সম্পূর্ণ শ্রেণী দূর করে।

@MainActor কীভাবে কাজ করে?

@MainActor-এর কাজের নীতি Swift Concurrency নির্বাহ সিস্টেমের উপর ভিত্তি করে। যখন একটি থ্রেড @MainActor দিয়ে চিহ্নিত ফাংশন কল করে, শিডিউলার এটি বর্তমান নির্বাহকের উপর স্থগিত করে এবং প্রধান থ্রেডে পুনরায় শুরু করে। কম্পাইলার কল সীমানা ট্র্যাক করে এবং নিরাপত্তার নিশ্চয়তা দেয়।

প্রধান থ্রেড নির্বাহক

@MainActor-এর নির্বাহ MainActor.shared দ্বারা পরিচালিত হয় — একটি নির্বাহক যা অ্যাপ্লিকেশনের প্রধান থ্রেডের সাথে সম্পর্কিত। যখন একটি অ্যাসিনক্রোনাস ফাংশন @MainActor দিয়ে চিহ্নিত হয়, এটি সর্বদা এই নির্বাহকের উপর পুনরায় শুরু হয়, মূল কাজটি কোন থ্রেডে শুরু হয়েছিল তা নির্বিশেষে।

swift
import SwiftUI

class ViewModel: ObservableObject {
    @Published var items: [String] = []

    @MainActor
    func loadData() async {
        let result = await fetchRemoteData()
        items = result  // নিরাপদভাবে, MainActor প্রধান থ্রেড নিশ্চিত করে
    }
}

অ্যাক্টর প্রসঙ্গ উত্তরাধিকার

যদি একটি ফাংশন @MainActor দিয়ে চিহ্নিত হয় এবং অন্য একটি অ্যাসিনক্রোনাস ফাংশন কল করে, এটি ডিফল্টভাবে অ্যাক্টর প্রসঙ্গ উত্তরাধিকার সূত্রে পায়। এর মানে হল যে সমস্ত নেস্টেড কলও প্রধান থ্রেডে নির্বাহিত হয়, যদি না অন্যথায় নির্দিষ্ট করা হয়। কম্পাইলার এটি ট্র্যাক করে এবং একটি অসামঞ্জস্যপূর্ণ ক্লোজার পাস করার চেষ্টা করলে ত্রুটি জারি করে।

@MainActor বনাম DispatchQueue.main

@MainActor এবং DispatchQueue.main-এর তুলনা বুঝতে সাহায্য করে কেন নতুন প্রক্রিয়াটি আরও নিরাপদ এবং সুবিধাজনক বলে বিবেচিত হয়, যদিও উভয়ই একই কাজ সমাধান করে — প্রধান থ্রেডে কোড নির্বাহ করা।

টাইপ স্তরে নিরাপত্তা

@MainActor কম্পাইলার স্তরে একটি পরীক্ষা। যদি আপনি একটি অনিরাপদ প্রসঙ্গ থেকে @MainActor ফাংশন কল করার চেষ্টা করেন, কম্পাইলার একটি সতর্কতা বা ত্রুটি জারি করবে। DispatchQueue.main.async একটি রানটাইম কল: কোড কম্পাইল হবে কিন্তু ব্যাকগ্রাউন্ড থ্রেড থেকে UI আপডেট করার চেষ্টা করলে রানটাইমে ক্র্যাশ হতে পারে।

পারফরম্যান্স এবং ওভারহেড

DispatchQueue.main.async কিউতে একটি ব্লক যোগ করে যা বিলম্বে নির্বাহিত হতে পারে। @MainActor async/await-এর সাথে অপ্রয়োজনীয় ক্লোজার তৈরি না করে সরাসরি নির্বাহক সুইচিং করে। এটি ওভারহেড হ্রাস করে এবং নির্বাহের সময়কে আরও পূর্বাভাসযোগ্য করে।

swift
// পুরানো পদ্ধতি
DispatchQueue.main.async {
    self.updateUI()
}

// @MainActor-এর সাথে নতুন পদ্ধতি
@MainActor
func updateUI() {
    // প্রধান থ্রেডে নির্বাহিত হয়
    self.label.text = "আপডেট করা হয়েছে"
}
মাপকাঠি@MainActorDispatchQueue.main
পরীক্ষাকম্পাইলাররানটাইম
সিনট্যাক্সঅ্যানোটেশন (ঘোষণামূলক)কল (আদেশমূলক)
ওভারহেডকম (নির্বাহক সুইচিং)মধ্যম (ক্লোজার + কিউ)
পরীক্ষণযোগ্যতাউচ্চ (MainActor.shared প্রতিস্থাপনযোগ্য)নিম্ন (মক করা কঠিন)

iOS প্রজেক্টে @MainActor-এর ব্যবহার

বাস্তব iOS প্রজেক্টে, @MainActor ViewModel স্তর, SwiftUI ভিউ এবং UIKit কন্ট্রোলারে ব্যবহৃত হয়। অ্যানোটেশনটি পৃথক পদ্ধতি এবং সম্পূর্ণ টাইপ উভয়ের উপর প্রয়োগ করা যেতে পারে।

ক্লাস বা স্ট্রাকচার অ্যানোটেশন

একটি ক্লাসকে @MainActor দিয়ে চিহ্নিত করে, আপনি নিশ্চিত করেন যে এর সমস্ত পদ্ধতি এবং বৈশিষ্ট্য শুধুমাত্র প্রধান থ্রেডে অ্যাক্সেসযোগ্য। এটি SwiftUI ভিউ এবং ObservableObject ক্লাসের জন্য বিশেষভাবে সুবিধাজনক: আপনি simply class-এর আগে @MainActor যোগ করেন, এবং সমস্ত @Published বৈশিষ্ট্য নিরাপদে আপডেট হয়।

swift
@MainActor
final class UserListViewModel: ObservableObject {
    @Published var users: [User] = []
    @Published var isLoading = false

    func fetchUsers() async {
        isLoading = true
        users = await api.getUsers()
        isLoading = false
    }
}

লিগেসি কোড মোড়ানো

পুরানো UIKit কোডের সাথে কাজ করার সময় যেখানে থ্রেড সুইচিং ম্যানুয়াল ছিল, আপনি স্পষ্ট সুইচিংয়ের জন্য MainActor.run ব্যবহার করতে পারেন। এটি সম্পূর্ণ কোডবেস পুনরায় লেখা ছাড়াই Swift Concurrency-এ ক্রমিক রূপান্তরের জন্য সুবিধাজনক।

swift
await MainActor.run {
    self.tableView.reloadData()
}

@MainActor-এর সীমাবদ্ধতা

এর সমস্ত সুবিধা সত্ত্বেও, @MainActor-এর বেশ কয়েকটি সীমাবদ্ধতা রয়েছে যা অ্যাপ্লিকেশন আর্কিটেকচার ডিজাইন করার সময় বিবেচনা করা গুরুত্বপূর্ণ। প্রযোজ্যতার সীমা বোঝা ভুল ব্যবহার এড়াতে সাহায্য করে।

নিবিড় ব্যবহারে পারফরম্যান্স

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

কিছু API-এর সাথে অসামঞ্জস্যতা

পুরানো কলব্যাক-ভিত্তিক API (উদাহরণস্বরূপ, async/await ছাড়া URLSession) অ্যাক্টর প্রসঙ্গ সমর্থন করে না। একীকরণের জন্য CheckedContinuation-এর সাথে একটি র্যাপার প্রয়োজন। এছাড়াও, @MainActor performSelector, target-action এবং UIKit-এর অন্যান্য নন-অ্যাসিনক্রোনাস প্যাটার্নের সাথে সামঞ্জস্যপূর্ণ নয়।

মাল্টিথ্রেডেড ডিবাগিং

@MainActor-এর সাথে অ্যাপ্লিকেশন ডিবাগ করার সময়, রেস কন্ডিশন পুনরুত্পাদন করা কঠিন কারণ কম্পাইলার তাদের অনেকগুলিকে রানটাইমের পরিবর্তে বিল্ড সময়ে প্রতিরোধ করে। তবে, এটি নিরাপত্তার একটি মিথ্যা অনুভূতি তৈরি করতে পারে: শেয়ার্ড মিউটেবল অবজেক্টের (যেমন NSCache বা শেয়ার্ড গ্লোবাল ভেরিয়েবল) সাথে ভুল কাজ এখনও সম্ভব যদি সেগুলি @MainActor দিয়ে চিহ্নিত না হয় এবং স্পষ্ট সিঙ্ক্রোনাইজেশন ছাড়া ব্যবহার করা হয়।

@MainActor-এর পরীক্ষা

@MainActor UI লজিক পরীক্ষাকে উল্লেখযোগ্যভাবে সহজ করে কারণ এটি পরীক্ষায় ম্যানুয়ালি থ্রেড সুইচ করার প্রয়োজনীয়তা দূর করে। তবে, ইউনিট টেস্ট এবং UI টেস্ট লেখার সময় বিবেচনা করার জন্য বিশেষত্ব রয়েছে।

MainActor-এর সাথে ইউনিট টেস্ট

XCTest-এ, পরীক্ষার পরিবেশ স্বয়ংক্রিয়ভাবে প্রধান থ্রেড নির্বাহক সেট আপ করে। যখন একটি পরীক্ষা পদ্ধতি প্রধান থ্রেডে চলে, @MainActor ফাংশন কল করার জন্য অতিরিক্ত সেটআপের প্রয়োজন হয় না — সেগুলি একই প্রসঙ্গে নির্বাহিত হয়। ব্যাকগ্রাউন্ড পরিস্থিতি পরীক্ষার জন্য, স্পষ্ট অগ্রাধিকার এবং নির্বাহকের সাথে Task-এর ভিতরে MainActor.run ব্যবহার করুন, আলাদাভাবে যাচাই করুন যে কোড ব্যাকগ্রাউন্ড থেকে কল করার সময় সঠিকভাবে কাজ করে।

একটি সাধারণ পদ্ধতি হল @MainActor-এর সাথে ViewModel পরীক্ষা করা, যেখানে যাচাই করা হয় যে অ্যাসিনক্রোনাস অপারেশনের পরে @Published বৈশিষ্ট্যগুলি সঠিকভাবে আপডেট হয়। অ্যাক্টর প্রসঙ্গ উত্তরাধিকারের জন্য ধন্যবাদ, পরীক্ষার ভিতরে await কল করা অতিরিক্ত DispatchQueue গ্যারান্টি বা ম্যানুয়াল প্রসঙ্গ সুইচিং ছাড়াই প্রধান থ্রেডে নির্বাহের নিশ্চয়তা দেয়, যা পরীক্ষা লেখাকে সহজ করে।

রিফ্যাক্টরিংয়ের সময় বিচ্ছিন্নতা পরীক্ষা

বিদ্যমান কোড Swift Concurrency-তে রিফ্যাক্টর করার সময়, কম্পাইলারের মাধ্যমে @MainActor বিচ্ছিন্নতা পরীক্ষা করুন: @MainActor প্রসঙ্গ থেকে @MainActor ছাড়া সিনক্রোনাস পদ্ধতির যেকোনো কল ত্রুটি হিসাবে চিহ্নিত হয়। এই বৈশিষ্ট্যটি একটি প্রকল্পকে ধীরে ধীরে async/await-এ মাইগ্রেট করার জন্য ব্যবহৃত হয়: আপনি ViewModel স্তরকে @MainActor হিসাবে চিহ্নিত করেন, এবং কম্পাইলার সমস্ত অনিরাপদ কল হাইলাইট করে যা ব্যাকগ্রাউন্ড অ্যাক্টরে সরানোর প্রয়োজন।

মকিং এবং অ্যাক্টর প্রসঙ্গ

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

অ্যাসিনক্রোনাস অপারেশনের জন্য অপেক্ষা

@MainActor কোড সিনক্রোনাসভাবে পরীক্ষা করার সময়, অ্যাসিনক্রোনাস অপারেশন সম্পূর্ণ হওয়ার জন্য অপেক্ষা করতে XCTestExpectation ব্যবহার করুন। পরীক্ষায় প্রত্যাশা সেট করুন এবং একটি ক্লোজারের ভিতরে fulfillment কল করুন যা প্রধান থ্রেডে নির্বাহিত হয়। যদি পরীক্ষা অনির্দিষ্টকালের জন্য হ্যাং হয় — সম্ভবত প্রধান থ্রেডে কল হচ্ছে না, এবং আপনার অ্যাক্টর বিচ্ছিন্নতা পরীক্ষা করা প্রয়োজন। নির্বাহ প্রসঙ্গ ডিবাগ করার জন্য, পরীক্ষা কোডের ভিতরে Thread.isMainThread চেক যোগ করা দরকারী।

প্রায়শই জিজ্ঞাসিত প্রশ্ন

পুরো ক্লাসটি @MainActor দিয়ে চিহ্নিত করা কি প্রয়োজনীয়?

না, শুধুমাত্র UI আপডেট করে এমন পদ্ধতিগুলি চিহ্নিত করা যথেষ্ট। তবে, যদি একটি ক্লাসে এই ধরনের বেশ কয়েকটি পদ্ধতি থাকে, তাহলে পুরো ক্লাসে @MainActor যোগ করা সহজ। এটি নিশ্চিত করে যে এর সমস্ত সদস্য প্রধান থ্রেডে নির্বাহিত হয় এবং কোড রক্ষণাবেক্ষণ সহজ করে।

@MainActor @globalActor থেকে কীভাবে আলাদা?

@MainActor প্রধান থ্রেডের সাথে আবদ্ধ একটি গ্লোবাল অ্যাক্টরের একটি নির্দিষ্ট উদাহরণ। @globalActor আপনার নিজস্ব গ্লোবাল অ্যাক্টর তৈরি করার জন্য একটি প্রোটোকল। উদাহরণস্বরূপ, আপনি প্রজেক্ট আর্কিটেকচারের প্রয়োজন হলে ব্যাকগ্রাউন্ড থ্রেডে কোড নির্বাহের জন্য @BackgroundActor তৈরি করতে পারেন।

@MainActor কি async/await ছাড়া ব্যবহার করা যেতে পারে?

হ্যাঁ, @MainActor-এর সাথে সিনক্রোনাস ফাংশনও প্রধান থ্রেডে নির্বাহিত হয়। তবে, @MainActor-এর প্রধান মূল্য async/await-এর সাথে প্রকাশিত হয়, যখন একটি অ্যাসিনক্রোনাস ফাংশন DispatchQueue.main-এর মাধ্যমে ম্যানুয়াল সুইচিং ছাড়াই স্বয়ংক্রিয়ভাবে প্রধান থ্রেডে পুনরায় শুরু হয়।

@MainActor টাস্ক কীভাবে বাতিল করবেন?

Task.cancel() @MainActor টাস্কের সাথে সাধারণ টাস্কের মতোই কাজ করে। একটি @MainActor টাস্ক Task.isCancelled চেক করতে পারে বা CancellationError থ্রো করতে পারে। বাতিল করার সময়, প্রধান থ্রেড ব্লক হয় না — টাস্কটি নিকটতম সাসপেনশন পয়েন্টে নির্বাহ বন্ধ করে দেয়।

যদি @MainActor ব্যাকগ্রাউন্ড থ্রেড থেকে কল করা হয় তাহলে কী হবে?

কম্পাইলার নিরাপত্তার নিশ্চয়তা দেয়: যদি আপনি একটি ব্যাকগ্রাউন্ড প্রসঙ্গ থেকে @MainActor ফাংশন কল করেন, কম্পাইলার ত্রুটি নির্দেশ করবে। অ্যাসিনক্রোনাস কলের জন্য, await দিয়ে কলিং কোড চিহ্নিত করা যথেষ্ট, এবং নির্বাহক নিজেই প্রধান থ্রেডে সুইচ করবে। সিনক্রোনাস কলের জন্য, MainActor.run-এর মাধ্যমে স্পষ্ট সুইচিং প্রয়োজন।

সারাংশ

  • @MainActor — Swift-এর গ্লোবাল অ্যাক্টর যা প্রধান থ্রেডে নির্বাহের নিশ্চয়তা দেয়।
  • কম্পাইলার পরীক্ষা UI নিরাপত্তা ত্রুটির একটি সম্পূর্ণ শ্রেণী দূর করে।
  • সম্পূর্ণ ক্লাস অ্যানোটেশন স্বয়ংক্রিয়ভাবে এর সমস্ত পদ্ধতি প্রধান থ্রেডে রাখে।
  • MainActor.run — লিগেসি কোড এবং সিনক্রোনাস প্রসঙ্গের জন্য স্পষ্ট সুইচিং।
  • DispatchQueue.main-এর বিপরীতে, @MainActor ক্লোজার তৈরি করে না এবং নির্বাহক সুইচিং ব্যবহার করে।
  • ভারী গণনা UI হ্যাং এড়াতে @MainActor-এর অধীনে করা উচিত নয়।
  • অ্যাক্টর প্রসঙ্গ উত্তরাধিকার অ্যাসিনক্রোনাস কলের চেইন সহজ করে এবং কোডকে সামঞ্জস্যপূর্ণ, পূর্বাভাসযোগ্য এবং UI-এর জন্য নিরাপদ করে।

আমরা একটি মোবাইল অ্যাপ্লিকেশন টার্নকি তৈরি করব

IT Sectr 2017 সাল থেকে স্টার্টআপ এবং ব্যবসার জন্য iOS এবং Android অ্যাপ্লিকেশন তৈরি করে। আমরা আপনাকে পরামর্শ দেব এবং সেরা সমাধান প্রস্তাব করব।

প্রকল্প নিয়ে আলোচনা করুন

আরও পড়ুন