setNeedsLayout বনাম setNeedsUpdateConstraints এবং লেআউটআইফনেড বনাম আপডেটকেনট্রেটসআইফনিড


227

আমি জানি যে অটো লেআউট চেইনে মূলত 3 টি পৃথক প্রক্রিয়া থাকে।

  1. সীমাবদ্ধতা আপডেট
  2. বিন্যাসের দর্শন (এখানে আমরা ফ্রেমের গণনা পাই)
  3. প্রদর্শন

কি সম্পূর্ণই আমার কাছে পরিষ্কার না হয় মধ্যে ভেতরের পার্থক্য নেই -setNeedsLayoutএবং -setNeedsUpdateConstraints। অ্যাপল ডক্স থেকে:

setNeedsLayout

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

setNeedsUpdateConstraints

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

যখন আমি কোনও সীমাবদ্ধতা সংশোধন করার পরে একটি দৃশ্যকে সঞ্জীবিত করতে চাই এবং আমি সাধারণত যে পরিবর্তনগুলি বলি তা অ্যানিমেট করতে চাই:

[UIView animateWithDuration:1.0f delay:0.0f usingSpringWithDamping:0.5f initialSpringVelocity:1 options:UIViewAnimationOptionCurveEaseInOut animations:^{
        [self.modifConstrView setNeedsUpdateConstraints];
        [self.modifConstrView layoutIfNeeded];
    } completion:NULL];

আমি খুঁজে পেয়েছি যে আমি যদি সবকিছু -setNeedsLayoutপরিবর্তে -setNeedsUpdateConstraintsপ্রত্যাশা অনুযায়ী ব্যবহার করি তবে আমি যদি এটির -layoutIfNeededসাথে পরিবর্তন করি -updateConstraintsIfNeededতবে অ্যানিমেশনটি ঘটবে না।
আমি আমার নিজের উপসংহারটি চেষ্টা করার চেষ্টা করেছি:

  • -updateConstraintsIfNeeded কেবলমাত্র সীমাবদ্ধতাগুলি আপডেট করে তবে লেআউটটি প্রক্রিয়াতে আসতে বাধ্য করে না, সুতরাং মূল ফ্রেমগুলি এখনও সংরক্ষিত রয়েছে
  • -setNeedsLayoutকল এছাড়াও -updateContraintsপদ্ধতি

সুতরাং যখন অন্যটির পরিবর্তে একটি ব্যবহার করা ঠিক আছে? এবং লেআউট পদ্ধতিগুলি সম্পর্কে, আমার কি তাদের এই দৃষ্টিভঙ্গিতে কোনও পরিবর্তন বা অভিভাবকের দৃষ্টিভঙ্গিতে পরিবর্তন রয়েছে এমন কল করা উচিত?


27
আমি মানুষকে ... সুতরাং আপনার এ বিষয়ে কিছু করা উচিত, যেমন বাধ্যতামূলক হিসাবে কারণ জিজ্ঞাসা করা বা সেগুলি সম্পূর্ণ অর্থহীন
অ্যান্ড্রিয়া

7
সম্ভবত তাদের কেবল সমালোচক ব্যাজ (প্রথম নিচে ভোট) প্রাপ্ত করা দরকার
ফুজিয়ানজিন 6471

1
আমি আপনাকে এখানে দেখতে অত্যন্ত পরামর্শ দিচ্ছি । উত্তরটি একটি বাস্তব সমস্যার সমাধান বেশি। এই
মধু

উত্তর:


258

আপনার সিদ্ধান্তগুলি সঠিক। প্রাথমিক স্কিমটি হ'ল:

  • setNeedsUpdateConstraintsভবিষ্যতে updateConstraintsIfNeededকলগুলিতে কল নিশ্চিত করে updateConstraints
  • setNeedsLayoutভবিষ্যতে layoutIfNeededকলগুলিতে কল নিশ্চিত করে layoutSubviews

যখন layoutSubviewsডাকা হয়, এটিও ডাকে updateConstraintsIfNeeded, সুতরাং ম্যানুয়ালি এটিকে কল করা আমার অভিজ্ঞতার মধ্যে খুব কমই প্রয়োজন। প্রকৃতপক্ষে, ডিবাগিং লেআউটগুলি বাদে আমি কখনই এটিকে ডাকিনি called

সীমাবদ্ধতাগুলি ব্যবহার করে আপডেট setNeedsUpdateConstraintsকরা খুব বিরল, cজেক.আইও auto একটি অটোলেআউটগুলি সম্পর্কে অবশ্যই পড়তে হবে – বলেছেন :

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

তদুপরি, আমার অভিজ্ঞতা হিসাবে, আমাকে কখনই বাধাগুলি অকার্যকর করতে হয়নি, এবং কোডটির setNeedsLayoutপরবর্তী লাইনে সেট করা হয়নি , কারণ নতুন সীমাবদ্ধতাগুলি একটি নতুন বিন্যাসের জন্য জিজ্ঞাসা করছে।

থাম্বের বিধিগুলি হ'ল:

  • আপনি যদি সরাসরি প্রতিবন্ধকতাগুলি চালিত করেন তবে কল করুন setNeedsLayout
  • আপনি কিছু অবস্থার যা (অফসেট বা প্রস্তুত হত্তয়া মত) পরিবর্তিত হলে হবে আপনার উপেক্ষিত মধ্যে সীমাবদ্ধতা পরিবর্তন updateConstraintsপদ্ধতি (পরিবর্তন সীমাবদ্ধতার একটি প্রস্তাবিত উপায়, BTW), কল setNeedsUpdateConstraints, এবং সময় বেশিরভাগ setNeedsLayoutরকম।
  • তাত্ক্ষণিকভাবে প্রভাব ফেলতে যদি আপনার উপরের কোনও ক্রিয়া প্রয়োজন হয় — যেমন একটি লেআউট পাসের পরে আপনার যখন নতুন ফ্রেমের উচ্চতা শেখার দরকার হয় - এটিকে এটি যুক্ত করুন layoutIfNeeded

এছাড়াও, আপনার অ্যানিমেশন setNeedsUpdateConstraintsকোডটিতে , আমি বিশ্বাস করি যে বিনা শৃঙ্খলাবদ্ধ, যেহেতু অ্যানিমেশনটি ম্যানুয়ালি করার আগে সীমাবদ্ধতাগুলি আপডেট করা হয়েছে এবং পুরানো এবং নতুনগুলির মধ্যে পার্থক্যের ভিত্তিতে অ্যানিমেশনটি কেবল পুনরায় সাজিয়েছে।


@ কভারব্যাক, সুতরাং ওজেক্ট.আইও বলেছে "যদি এর পরে কিছু পরিবর্তন হয় তবে এটি আপনার বাধাগুলির একটিটিকে অকার্যকর করে তোলে, আপনার অবিলম্বে এই সীমাবদ্ধতাটি সরিয়ে নেওয়া উচিত এবং সেটনিডস আপডেট কনট্রেন্টস কল করা উচিত। বাস্তবে, এটিই কেবলমাত্র আপনার ক্ষেত্রে সীমাবদ্ধ আপডেট পাসটি চালু করতে হবে।" এবং তারপরে অ্যানিমেশন ব্লকে বলা আছে যে আমি যখন সীমাবদ্ধতা সরিয়ে, যুক্ত বা পরিবর্তন করি তখন আমাকে সেটনিডলয়আউট কল করতে হবে। পার্থক্য কি? আমি আসল বোকা বোধ করছি :(
pash3r

3
@ pash3r পার্থক্য ধ্রুবক আপডেট করা হচ্ছে "অবৈধকরণ" হিসাবে যোগ্য নয়। অবৈধতা হ'ল যখন এটি আর প্রাসঙ্গিক নয়, যেমন অন্য কোনও দৃশ্যের সাথে সংযুক্ত থাকতে হবে বা পুরোপুরি মুছে ফেলা উচিত। ধ্রুবক কেবলমাত্র একটি দৃশ্যের কাছাকাছি বা আরও দূরে স্থাপন করবে বা এর আকার পরিবর্তন করবে, সুতরাং এটির প্রয়োজন setNeedsLayout
কভারব্যাক

@ কভারব্যাক setNeedsLayoutনিশ্চিত করে তোলে যে layoutSubviewsপরবর্তী আপডেটিং চক্রটিতে ডাকা হবে, তবে সম্ভবত এটির কিছুই করার নেই layoutIfNeeded?
ফুজিয়ানজিন 6471

2
@ কভারব্যাক আপনি যদি সীমাবদ্ধতাগুলি সরাসরি পরিচালনা করেন তবে layoutSubviewsস্বয়ংক্রিয়ভাবে কল করা হবে, কল করার দরকার নেইsetNeedsLayout
ফুজিয়ানজিন 716471১

হ্যাঁ, সীমাবদ্ধতার বৈশিষ্ট্যগুলি সরাসরি পরিচালনা করা ট্রিগার করবে layoutSubviews, সুতরাং এটি ম্যানুয়ালি করার দরকার নেই। তবে, layoutIfNeededআপনাকে পরবর্তী লেআউট চক্রের পরিবর্তে তাত্ক্ষণিকভাবে কার্যকর হওয়ার জন্য যদি পরিবর্তনগুলির প্রয়োজন হয় তবে আপনাকে কল করতে হবে
চার্লি মার্টিন

89

Coverback দ্বারা উত্তর প্রশংসনীয় সঠিক। তবে আমি কিছু অতিরিক্ত বিশদ যুক্ত করতে চাই।

নীচে একটি সাধারণ ইউআইভিউ চক্রের চিত্রটি দেওয়া হয়েছে যা অন্যান্য আচরণগুলি ব্যাখ্যা করে:

ইউআইভিউ'র জীবনচক্র

  1. আমি খুঁজে পেয়েছি যে আমি যদি সবকিছু -setNeedsLayoutপরিবর্তে -setNeedsUpdateConstraintsপ্রত্যাশা অনুযায়ী ব্যবহার করি তবে আমি যদি এটির -layoutIfNeededসাথে পরিবর্তন করি -updateConstraintsIfNeededতবে অ্যানিমেশনটি ঘটবে না।

updateConstraintsসাধারণত কিছু না। এটি কেবল বাধার সমাধান করে যতক্ষণ না layoutSubviewsডাকা হয় সেগুলি এটি প্রয়োগ করে না । সুতরাং অ্যানিমেশন একটি কল প্রয়োজন layoutSubviews

  1. setNeedsLayout কলও-আপডেট নিয়ন্ত্রণ ব্যবস্থা

না এটি প্রয়োজনীয় নয়। আপনার সীমাবদ্ধতাগুলি যদি না পরিবর্তন করা হয় তবে ইউআইভিউউ কল এড়িয়ে যাবে updateConstraintssetNeedsUpdateConstraintপ্রক্রিয়াটির সীমাবদ্ধতাগুলি পরিবর্তন করতে আপনাকে স্পষ্টভাবে কল করতে হবে to

কল করার জন্য updateConstraintsআপনাকে নিম্নলিখিতগুলি করতে হবে:

[view setNeedsUpdateConstraints];
[view setNeedsLayout]; 
[view layoutIfNeeded];

ধন্যবাদ, এটি আমার সমস্যার সমাধান করেছে। অ্যানিমেশনের আগে লেআউটআইফনিডকে () কল করার সময় আমার কোনও অভিভাবক ইউআইভিউউয়ের সাথে একটি ইউআইওয়াইন্ডো ছিল যা এতে সাময়িক বাধা যুক্ত হয়েছিল। UIWindow এ একটি সাবভিউ র্যাপার যুক্ত করা এবং এটিতে এই তিনটি পদ্ধতির কল করা আমার সমস্যাটি স্থির করেছে।
মাস্টারওয়াক

আমি মনে করি না যে কলিং লেআউটটি সেটনিডস লেআউটটি ঠিক পরে ঠিক পরে নেওয়া হয়েছে N কারণ একটিকে তত্ক্ষণাত লেআউটটি পুনরায় চিত্রিত করা এবং দ্বিতীয়টি পরবর্তী চক্রের মধ্যে দ্বিতীয়টি তৈরি করা সত্ত্বেও পদ্ধতিগুলি একই কাজ করে।
ফিলিপি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.