setNeedsDisplay(): পদ্ধতির সারমর্ম এবং iOS-এ পুনরায় অঙ্কনের প্রক্রিয়া

লেখক: IT Sectr প্রকাশিত: 2026-07-20 পড়ার সময়: 6 মিনিট

setNeedsDisplay() UIView-এর একটি ইনস্ট্যান্স মেথড যা ভিউকে পুনরায় অঙ্কনের প্রয়োজন হিসাবে চিহ্নিত করে। সরাসরি draw(_:) কল করার বিপরীতে, setNeedsDisplay() শুধুমাত্র ভিউ-এর জন্য dirty ফ্ল্যাগ সেট করে এবং অবিলম্বে নিয়ন্ত্রণ ফেরত দেয়। সিস্টেম এই অনুরোধটি নিকটতম রেন্ডারিং চক্রে প্রক্রিয়া করে, যা একাধিক কলকে একটি ড্র অপারেশনে একত্রিত করতে দেয়। Apple ডকুমেন্টেশন (2025) অনুসারে, setNeedsDisplay()-এর মাধ্যমে বিলম্বিত পুনরায় অঙ্কনই কাস্টম UIView-এর বিষয়বস্তু আপডেট করার একমাত্র সঠিক উপায়।

মূল বিষয়

  • setNeedsDisplay() — UIView-এর জন্য একটি বিলম্বিত পুনরায় অঙ্কন অনুরোধ, draw(_:) কে সিঙ্ক্রোনাসভাবে কল করে না
  • dirty ফ্ল্যাগ — একটি অভ্যন্তরীণ ভিউ ফ্ল্যাগ যা setNeedsDisplay() দ্বারা সেট করা হয় এবং draw(_:) এর পরে মুছে ফেলা হয়
  • setNeedsDisplay(_:) — শুধুমাত্র নির্দিষ্ট অঞ্চলের আংশিক পুনরায় অঙ্কনের জন্য CGRect সহ একটি ওভারলোড
  • displayIfNeeded() — বাধ্যতামূলক সিঙ্ক্রোনাস পুনরায় অঙ্কন, তাৎক্ষণিক আপডেটের জন্য ব্যবহৃত হয়
  • রেন্ডারিং চক্র — সিস্টেম run loop-এর শেষে dirty ভিউ প্রক্রিয়া করে, একাধিক অনুরোধকে এক পাসে একত্রিত করে

setNeedsDisplay() কী

setNeedsDisplay() একটি UIView মেথড যা সিস্টেমকে সংকেত দেয় যে ভিউ-এর বিষয়বস্তু পুরানো হয়ে গেছে এবং পুনরায় রেন্ডার করার প্রয়োজন। মেথডটি কোনো প্যারামিটার নেয় না এবং void রিটার্ন করে। কল করার পরে, ভিউটি dirty হিসাবে চিহ্নিত হয়, এবং নিকটতম ড্র চক্রে সিস্টেম এই ভিউ-এর জন্য draw(_:) কল করে।

মূল বৈশিষ্ট্য হল অ্যাসিঙ্ক্রোনাসিটি। একই ভিউ-এর জন্য ধারাবাহিকভাবে একাধিক setNeedsDisplay() কল draw(_:) এর একাধিক কলের ফলে হবে না — সিস্টেম সেগুলিকে একটি অপারেশনে একত্রিত করে। এটি পারফরম্যান্সের জন্য অত্যন্ত গুরুত্বপূর্ণ: যদি কোনো ভিউ প্রপার্টি প্রতি ফ্রেমে একাধিকবার পরিবর্তিত হয়, তবে draw(_:) শুধুমাত্র একবার কল হয়।

বিলম্বিত পুনরায় অঙ্কন কীভাবে কাজ করে

বিলম্বিত পুনরায় অঙ্কন প্রক্রিয়াটি UIKit রেন্ডারিং চক্রের উপর ভিত্তি করে। যখন setNeedsDisplay() কল করা হয়, সিস্টেম অভ্যন্তরীণ ফ্ল্যাগ layer.needsDisplay true-তে সেট করে। বর্তমান run loop-এর শেষে, সিস্টেম সমস্ত dirty লেয়ারের মধ্য দিয়ে যায় এবং প্রতিটির জন্য draw(_:) কল করে।

Run loop এবং রেন্ডারিং ধাপ

UIKit run loop-এ একটি আপডেট পর্যায় অন্তর্ভুক্ত রয়েছে যার সময় dirty ভিউ প্রক্রিয়া করা হয়। এই পর্যায়ে, প্রয়োজন হলে layoutSubviews() কল করা হয়, তারপর সমস্ত চিহ্নিত ভিউ-এর জন্য draw(_:) কল করা হয়। অঙ্কন সম্পূর্ণ হওয়ার পরে, ফলাফল কম্পোজিটিং-এর জন্য Core Animation-এর মাধ্যমে GPU-তে পাঠানো হয়।

swift
class ProgressView: UIView {
    var progress: CGFloat = 0 {
        didSet {
            setNeedsDisplay()
        }
    }

    override func draw(_ rect: CGRect) {
        super.draw(rect)
        guard let ctx = UIGraphicsGetCurrentContext() else { return }

        // পৃষ্ঠভূমি
        ctx.setFillColor(UIColor.lightGray.cgColor)
        ctx.fill(rect)

        // অগ্রগতি বার
        let fillRect = CGRect(x: rect.minX, y: rect.minY,
                              width: rect.width * progress, height: rect.height)
        ctx.setFillColor(UIColor.systemGreen.cgColor)
        ctx.fill(fillRect)
    }
}

এই উদাহরণে, progressView progress আপডেট করে, এবং প্রতিটি সেটার স্বয়ংক্রিয়ভাবে setNeedsDisplay() কল করে। সিস্টেম run loop-এর শেষ পর্যন্ত অপেক্ষা করে এবং প্রকৃত progress মান সহ draw(_:) কল করে। যদি progress প্রতি ফ্রেমে তিনবার পরিবর্তিত হয়, তবে draw(_:) শুধুমাত্র একবার সম্পাদিত হয় — শেষ মান দিয়ে।

setNeedsDisplay() বনাম setNeedsDisplay(_:)

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

বৈশিষ্ট্যsetNeedsDisplay()setNeedsDisplay(_:)
প্যারামিটারকোনোটি নয়CGRect — পুনরায় অঙ্কন এলাকা
পুনরায় অঙ্কন এলাকাসম্পূর্ণ ভিউ boundsশুধুমাত্র নির্দিষ্ট আয়তক্ষেত্র
পারফরম্যান্সবড় ভিউ-এর জন্য কমআংশিক পরিবর্তনের জন্য বেশি
draw(_:) এ rect প্যারামিটারসম্পূর্ণ boundsনির্দিষ্ট আয়তক্ষেত্র
কখন ব্যবহার করবেনসম্পূর্ণ বিষয়বস্তু পরিবর্তনবিন্দুগত পরিবর্তন (কার্সার, হাইলাইট)

জটিল গ্রাফিক্সের জন্য, প্রথমে পুরো দৃশ্যটি অফস্ক্রিন কনটেক্সটে আঁকার পরামর্শ দেওয়া হয়, তারপর শুধুমাত্র পরিবর্তিত এলাকার জন্য setNeedsDisplay(_:) কল করুন। এটি iOS-এ ড্রইং অ্যাপ্লিকেশন এবং গ্রাফিক এডিটরগুলিতে একটি মানক কৌশল।

displayIfNeeded() বনাম setNeedsDisplay()

displayIfNeeded() একটি সিঙ্ক্রোনাস মেথড যা run loop-এর শেষের জন্য অপেক্ষা না করেই অনুক্রমের সমস্ত dirty ভিউ-এর পুনরায় অঙ্কন অবিলম্বে শুরু করে। setNeedsDisplay()-এর বিপরীতে, যা শুধুমাত্র একটি ফ্ল্যাগ সেট করে, displayIfNeeded() draw(_:) এর তাৎক্ষণিক সম্পাদন বাধ্য করে।

Apple শুধুমাত্র চরম ক্ষেত্রে displayIfNeeded() ব্যবহার করার পরামর্শ দেয় যখন অঙ্কনের ফলাফল অবিলম্বে প্রয়োজন — উদাহরণস্বরূপ, স্ক্রিনশট নেওয়ার আগে বা UIGraphicsImageRenderer-এর জন্য সিঙ্ক্রোনাস ইমেজ জেনারেশনের সময়। সাধারণ পরিস্থিতিতে, setNeedsDisplay()-এর মাধ্যমে অ্যাসিঙ্ক্রোনাস মডেল পছন্দনীয় কারণ এটি মূল থ্রেডকে ব্লক করে না।

swift
    // অ্যাসিঙ্ক্রোনাস — সুপারিশ
someView.setNeedsDisplay()

    // সিঙ্ক্রোনাস — শুধুমাত্র প্রয়োজন হলে
someView.setNeedsDisplay()
someView.displayIfNeeded() // draw(_:) তাত্ক্ষণিক ডাকা হয়েছে

পূর্ববর্তী setNeedsDisplay() ছাড়া displayIfNeeded() কল করার কোনো প্রভাব থাকবে না — মেথডটি শুধুমাত্র ইতিমধ্যে dirty হিসাবে চিহ্নিত ভিউ প্রক্রিয়া করে। যদি কোনো ভিউ-এর পুনরায় অঙ্কনের প্রয়োজন না হয়, তবে displayIfNeeded() draw(_:) কল না করেই সম্পূর্ণ হয়।

setNeedsDisplay() কল অপ্টিমাইজেশন

ঘন ঘন setNeedsDisplay() কল পারফরম্যান্স হ্রাস করতে পারে, বিশেষ করে অ্যানিমেশনের সময়। আসুন প্রধান অপ্টিমাইজেশন কৌশলগুলি দেখি।

মডেলের মাধ্যমে পরিবর্তনগুলি গ্রুপিং

পৃথক প্রপার্টির প্রতিটি পরিবর্তনে setNeedsDisplay() কল করার পরিবর্তে, পরিবর্তনগুলি জমা করুন এবং সমস্ত আপডেট প্রয়োগ করার পরে একবার মেথডটি কল করুন। উদাহরণস্বরূপ, একটি উপাদানের রং, আকার এবং অবস্থান পরিবর্তন করার সময় — সমস্ত প্রপার্টি সেট করার পরে একবার setNeedsDisplay() কল করুন।

অ্যানিমেটেবল প্রপার্টির জন্য CALayer ব্যবহার

যদি কোনো প্রপার্টি CALayer-এর মাধ্যমে অ্যানিমেটেড করা যায় (backgroundColor, opacity, position, transform), তাহলে draw(_:) এর পরিবর্তে Core Animation ব্যবহার করুন। CALayer প্রপার্টিগুলি draw(_:) কল না করেই GPU-তে আপডেট হয়, যা CPU লোড ছাড়াই 60 FPS প্রদান করে।

CATransaction-এর মাধ্যমে ব্যাচ আপডেট

একাধিক পরিবর্তনকে এক রেন্ডারিং পাসে গ্রুপ করতে CATransaction ব্যবহার করুন। এটি লেনদেনের শেষে একাধিক setNeedsDisplay() কলকে একটি draw(_:) অপারেশনে একত্রিত করতে দেয়।

swift
CATransaction.begin()
CATransaction.setDisableActions(true)

view1.setNeedsDisplay()
view2.setNeedsDisplay()
view3.setNeedsDisplay()

CATransaction.commit()

displayIfNeeded() অতিরিক্ত ব্যবহার করবেন না — সিঙ্ক্রোনাস পুনরায় অঙ্কন মূল থ্রেড ব্লক করে এবং ফ্রেম ড্রপের কারণ হতে পারে। এটি শুধুমাত্র সেই অপারেশনগুলির জন্য ব্যবহার করুন যেখানে বর্তমান run loop শেষ হওয়ার আগে অঙ্কনের ফলাফল গুরুত্বপূর্ণ।

সচরাচর জিজ্ঞাসিত প্রশ্ন

আমার কি setNeedsDisplay()-এর পরিবর্তে সরাসরি draw(_:) কল করা উচিত?

না, সরাসরি draw(_:) কল করা নিষিদ্ধ। setNeedsDisplay() ভিউকে dirty হিসাবে সঠিকভাবে চিহ্নিত করে, এবং সিস্টেম রেন্ডারিং চক্রের সঠিক সময়ে draw(_:) কল করে। সরাসরি draw(_:) কল ক্যাশিং মেকানিজমকে উপেক্ষা করে এবং অসামঞ্জস্যপূর্ণ অবস্থার দিকে নিয়ে যেতে পারে।

setNeedsDisplay()-এর একাধিক কল করলে কী হয়?

একই ভিউ-এর জন্য setNeedsDisplay()-এর একাধিক কল সিস্টেম দ্বারা একটি draw(_:) কলে একত্রিত হয়। এটি ঘটে কারণ মেথডটি শুধুমাত্র dirty ফ্ল্যাগ সেট করে, যা run loop-এর শেষে draw(_:) এর প্রকৃত সম্পাদনের পরেই মুছে ফেলা হয়।

setNeedsDisplay() setNeedsLayout() থেকে কীভাবে আলাদা?

setNeedsDisplay() ভিউ-এর বিষয়বস্তুর পুনরায় অঙ্কনের অনুরোধ করে (draw(_:) কল করে)। setNeedsLayout() সাবভিউ-এর পুনর্বিন্যাসের অনুরোধ করে (layoutSubviews() কল করে)। layoutSubviews() আকার পরিবর্তনের কারণ হতে পারে, যা ফলস্বরূপ পুনরায় অঙ্কন ট্রিগার করতে পারে।

কখন setNeedsDisplay(_:) ব্যবহার করবেন?

setNeedsDisplay(_:) বিন্দুগত পরিবর্তনের জন্য ব্যবহার করা উচিত: কার্সার চলাচল, নির্বাচিত এলাকার রং পরিবর্তন, গ্রাফের অংশ আপডেট করা। এটি পুনরায় অঙ্কন এলাকা সীমিত করে এবং সম্পূর্ণ ভিউ পুনরায় আঁকার তুলনায় পারফরম্যান্স উন্নত করে।

ফ্রেম পরিবর্তন কি স্বয়ংক্রিয়ভাবে setNeedsDisplay() কল করে?

ডিফল্টরূপে, ফ্রেম বা bounds পরিবর্তন setNeedsDisplay() কল করে না। সিস্টেম শুধুমাত্র ভিউ সরিয়ে নেয়। যদি আকার পরিবর্তনের সময় পুনরায় অঙ্কনের প্রয়োজন হয়, তাহলে contentMode প্রপার্টি .redraw-এ সেট করুন — তাহলে UIKit স্বয়ংক্রিয়ভাবে প্রতিটি bounds পরিবর্তনে setNeedsDisplay() কল করবে।

সারসংক্ষেপ

  • setNeedsDisplay() — dirty ফ্ল্যাগ সেট করে বিলম্বিত পুনরায় অঙ্কনের অনুরোধ করার জন্য UIView-এর একটি অ্যাসিঙ্ক্রোনাস মেথড
  • setNeedsDisplay(_:) — শুধুমাত্র নির্দিষ্ট অঞ্চলের আংশিক পুনরায় অঙ্কনের জন্য CGRect সহ একটি ওভারলোড, পারফরম্যান্স অপ্টিমাইজ করে
  • displayIfNeeded() — dirty ভিউ-এর তাৎক্ষণিক পুনরায় অঙ্কনের জন্য একটি সিঙ্ক্রোনাস মেথড, শুধুমাত্র একান্ত প্রয়োজন হলে ব্যবহৃত হয়
  • Run loop — সিস্টেম বর্তমান চক্রের শেষে dirty ভিউ প্রক্রিয়া করে, একাধিক কলকে একটি draw(_:) পাসে একত্রিত করে
  • CALayer — অ্যানিমেটেবল প্রপার্টির (position, opacity) জন্য draw(_:) এর পরিবর্তে Core Animation ব্যবহার করুন — এটি অনেক বেশি কার্যকর
  • CATransaction — একাধিক পরিবর্তনকে এক রেন্ডারিং চক্রে গ্রুপ করে, draw(_:) কলের সংখ্যা হ্রাস করে
  • contentMode = .redraw — ভিউ-এর bounds পরিবর্তনে স্বয়ংক্রিয় setNeedsDisplay() কল সক্ষম করে

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

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

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

আরও পড়ুন