সাবক্লাসিং ইউআইভিউয়ের জন্য সঠিক অনুশীলন?


158

আমি কিছু কাস্টম ইউআইভিউ-ভিত্তিক ইনপুট নিয়ন্ত্রণগুলিতে কাজ করছি, এবং আমি ভিউ সেট আপ করার জন্য যথাযথ অনুশীলনটি সনাক্ত করার চেষ্টা করছি। যখন একটি UIViewController সঙ্গে কাজ করলেন, এটি ব্যবহার করার জন্য মোটামুটি সহজ loadViewও সংশ্লিষ্ট viewWill, viewDidপদ্ধতি, কিন্তু যখন একটি UIView subclassing, নিকটতম methosds আমি আছে `awakeFromNib, drawRectএবং layoutSubviews। (আমি সেটআপ এবং টিয়ারডাউন কলব্যাকগুলির ক্ষেত্রে বিবেচনা করছি)) আমার ক্ষেত্রে, আমি আমার ফ্রেম এবং অভ্যন্তরীণ দৃষ্টিভঙ্গিগুলি সেট আপ করছি layoutSubviews, তবে আমি অনস্ক্রিনে কিছুই দেখছি না।

আমার দৃষ্টিতে সঠিক উচ্চতা এবং প্রস্থ যেটি আমি চাই তা নিশ্চিত করার সর্বোত্তম উপায় কী? (আমি অটোলেআউট ব্যবহার করছি কিনা তা বিবেচনা না করেই আমার প্রশ্নটি প্রযোজ্য, যদিও এর দুটি উত্তর থাকতে পারে)) সঠিক "সেরা অনুশীলন" কী?

উত্তর:


298

অ্যাপল কীভাবে UIViewডকটিতে সাবক্লাস করবেন সে সম্পর্কে স্পষ্টভাবে সংজ্ঞায়িত করেছেন ।

নীচের তালিকাটি দেখুন, বিশেষত একবার initWithFrame:এবং একবার দেখুন layoutSubviews। পূর্ববর্তীটি আপনার ফ্রেম সেটআপ করার উদ্দেশ্যে তৈরি হয়েছে UIViewযেখানে পরবর্তীকালের ফ্রেম এবং তার সংক্ষিপ্তসারগুলির বিন্যাস সেটআপ করার উদ্দেশ্যে তৈরি করা হয়েছে।

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

অবশেষে, আপনি যদি UIViewকোনও নিব (বা স্টোরিবোর্ড) থেকে লোড করেন তবে awakeFromNibকাস্টম ফ্রেম এবং লেআউট প্রারম্ভিককরণগুলি সম্পাদন করার সুযোগও রয়েছে, যেহেতু এটি যখন awakeFromNibনিশ্চিত হয় যে শ্রেণিবদ্ধের প্রতিটি দৃষ্টিভঙ্গি সংরক্ষণাগারভুক্ত এবং আরম্ভ করা হয়েছিল।

এর দস্তাবেজ NSNibAwaking(এখনকার দস্তাবেজ দ্বারা উত্সাহিত awakeFromNib):

জাগ্রত থেকে অন্য বস্তুর বার্তাগুলি নিরাপদে প্রেরণ করা যেতে পারে ফ্রেমনিব - যার মাধ্যমে এটি নিশ্চিত হয়ে গেছে যে সমস্ত বস্তু সংরক্ষণাগারভুক্ত এবং প্রারম্ভিক (যদিও অবশ্যই জাগ্রত নয়)

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

ডকুমেন্টেশন থেকে সরাসরি :

ওভাররাইড করার পদ্ধতিগুলি

আরম্ভ

  • initWithFrame:আপনি এই পদ্ধতিটি বাস্তবায়ন করার পরামর্শ দেওয়া হচ্ছে। আপনি এই পদ্ধতিটি ছাড়াও বা পরিবর্তে কাস্টম সূচনা পদ্ধতিও প্রয়োগ করতে পারেন।

  • initWithCoder: যদি আপনি কোনও ইন্টারফেস বিল্ডার নিব ফাইল থেকে আপনার দৃষ্টিভঙ্গি লোড করেন এবং আপনার দৃশ্যের জন্য কাস্টম সূচনা প্রয়োজন this

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

অঙ্কন এবং মুদ্রণ

  • drawRect:আপনার দৃষ্টিভঙ্গি কাস্টম সামগ্রী আঁকলে এই পদ্ধতিটি প্রয়োগ করুন। যদি আপনার দৃষ্টিভঙ্গি কোনও কাস্টম অঙ্কন না করে তবে এই পদ্ধতিটিকে ওভাররাইড করা এড়িয়ে চলুন।

  • drawRect:forViewPrintFormatter: আপনি যদি মুদ্রণের সময় আপনার দর্শনের সামগ্রীটি আলাদাভাবে আঁকতে চান তবে এই পদ্ধতিটি কার্যকর করুন।

সীমাবদ্ধতাসমূহ

  • requiresConstraintBasedLayout যদি আপনার ভিউ ক্লাসে সঠিকভাবে কাজ করতে বাধার প্রয়োজন হয় তবে এই শ্রেণি পদ্ধতিটি প্রয়োগ করুন।

  • updateConstraints আপনার দৃশ্যের মধ্যে আপনার সাবউভিউগুলির মধ্যে কাস্টম সীমাবদ্ধতা তৈরি করতে হলে এই পদ্ধতিটি প্রয়োগ করুন lement

  • alignmentRectForFrame:, frameForAlignmentRect:আপনার দৃষ্টিভঙ্গি কীভাবে অন্যান্য দৃশ্যের সাথে সামঞ্জস্য হয় সেটিকে ওভাররাইড করতে এই পদ্ধতিগুলি প্রয়োগ করুন।

বিন্যাস

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

  • layoutSubviews যদি আপনার সাবউভিউগুলির বিন্যাসের উপরে বাধা বা স্বতঃসংশ্লিষ্ট আচরণগুলি সরবরাহ করে তার চেয়ে বেশি সুনির্দিষ্ট নিয়ন্ত্রণের প্রয়োজন হয় তবে এই পদ্ধতিটি কার্যকর করুন।

  • didAddSubview:, willRemoveSubview:সাবউভিউগুলির সংযোজন এবং অপসারণগুলি ট্র্যাক করার জন্য প্রয়োজনীয় এই পদ্ধতিগুলি প্রয়োগ করুন।

  • willMoveToSuperview:, didMoveToSuperviewআপনার ভিউ হায়ারার্কিতে বর্তমান দর্শনের গতিপথ ট্র্যাক করার জন্য প্রয়োজনীয় এই পদ্ধতিগুলি প্রয়োগ করুন।

  • willMoveToWindow:, didMoveToWindowআপনার দৃষ্টিভঙ্গিটিকে অন্য একটি উইন্ডোতে চলাচল করতে ট্র্যাক করার জন্য প্রয়োজনীয় এই পদ্ধতিগুলি প্রয়োগ করুন।

ইভেন্ট হ্যান্ডলিং:

  • touchesBegan:withEvent:, touchesMoved:withEvent:, touchesEnded:withEvent:, touchesCancelled:withEvent:যদি আপনি সরাসরি স্পর্শ ঘটনা হ্যান্ডেল প্রয়োজন এই পদ্ধতি বাস্তবায়ন। (অঙ্গভঙ্গি-ভিত্তিক ইনপুট জন্য, অঙ্গভঙ্গি সনাক্তকারী ব্যবহার করুন))

  • gestureRecognizerShouldBegin: যদি আপনার ভিউ টাচ ইভেন্টগুলি সরাসরি পরিচালনা করে এবং সংযুক্ত অঙ্গভঙ্গি শনাক্তকারীদের অতিরিক্ত ক্রিয়াকলাপগুলি থেকে আটকাতে চায় তবে এই পদ্ধতিটি প্রয়োগ করুন।


কী - (শূন্য) সেট ফ্রেম: (সিজিআরেক্ট) ফ্রেম?
pfrank

ভাল আপনি অবশ্যই এটিকে ওভাররাইড করতে পারেন, তবে কী উদ্দেশ্যে?
গ্যাব্রিয়েল পেট্রোনেলা

ফ্রেম আকার বা অবস্থানের পরিবর্তনগুলি যে কোনও সময় লেআউট / অঙ্কন পরিবর্তন করতে
pfrank


থেকে stackoverflow.com/questions/4000664/... , "এই সমস্যা যে subviews শুধুমাত্র তাদের আকার পরিবর্তন করতে পারে না, কিন্তু তারা এটি আকার পরিবর্তন এনিমেট করতে পারেন। যখন UIView অ্যানিমেশন রান আউট, এটি layoutSubviews প্রতিটি সময় কল করে না।" যদিও এটি ব্যক্তিগতভাবে পরীক্ষিত হয়নি
স্পষ্ট করুন

38

এটি এখনও গুগলে উচ্চ আসে। নীচে দ্রুতগতির জন্য একটি আপডেট করা উদাহরণ।

didLoadফাংশন আপনি আপনার সমস্ত কাস্টম আরম্ভের কোড করা করতে দেয়। অন্যরা যেমন didLoadবলেছে , প্রোগ্রাম হিসাবে কোনও ভিউ তৈরি করা হয় init(frame:)বা এক্সআইবি ডিজিজারাইজার যখন আপনার ভিউতে একটি এক্সআইবি টেম্পলেট একত্রিত করে তখন ডাকা হবেinit(coder:)

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

import UIKit

class MyView: UIView {
  //-----------------------------------------------------------------------------------------------------
  //Constructors, Initializers, and UIView lifecycle
  //-----------------------------------------------------------------------------------------------------
  override init(frame: CGRect) {
      super.init(frame: frame)
      didLoad()
  }

  required init?(coder aDecoder: NSCoder) {
    super.init(coder: aDecoder)
    didLoad()
  }

  convenience init() {
    self.init(frame: CGRectZero)
  }

  func didLoad() {
    //Place your initialization code here

    //I actually create & place constraints in here, instead of in
    //updateConstraints
  }

  override func layoutSubviews() {
     super.layoutSubviews()

     //Custom manually positioning layout goes here (auto-layout pass has already run first pass)
  }

  override func updateConstraints() {
    super.updateConstraints()

    //Disable this if you are adding constraints manually
    //or you're going to have a 'bad time'
    //self.translatesAutoresizingMaskIntoConstraints = false

    //Add custom constraint code here
  }
}

আপনি কীভাবে ব্যাখ্যা করতে পারেন যে আপনি কখন / কেন আপনার ডিআইডি প্রক্রিয়া এবং লেআউটসুভিউ এবং আপডেটসন্ট্রেন্টগুলি থেকে ডাকা একটি পদ্ধতির মধ্যে লেআউট সীমাবদ্ধতার কোডটি বিভক্ত করবেন? দেখে মনে হচ্ছে লেআউট কোড রাখার জন্য তারা তিনটিই সম্ভাব্য প্রার্থীর অবস্থান। সুতরাং আপনি কীভাবে জানবেন কখন / কী / কেন তিনটির মধ্যে লেআউট কোড বিভক্ত করবেন?
ক্লে এলিস

3
আমি কখনই আপডেটকন্ট্রেন্ট ব্যবহার করি না; আপডেটকন্ট্রেন্টগুলি দুর্দান্ত হতে পারে কারণ আপনি জানেন যে আপনার দর্শন শ্রেণিবদ্ধতা পুরোপুরি ইনপিতে সেট আপ হয়েছিল, সুতরাং আপনি শ্রেণিবদ্ধ নয় এমন দুটি মতামতের মধ্যে একটি সীমাবদ্ধতা যুক্ত করে ব্যতিক্রম বাড়াতে পারবেন না :) লেআউটভিউগুলিতে কখনও বাধা পরিবর্তন হওয়া উচিত নয়; লেআউট পাসের সময় সীমাবদ্ধতাগুলি 'অবৈধ' করা হলে এটি সহজেই একটি অসীম পুনরাবৃত্তি ঘটায় কারণ লেআউটসুভিউগুলি বলা হয়। ম্যানুয়াল লেআউট সেটআপ (সরাসরি ফ্রেম সেট করার ক্ষেত্রে, পারফরম্যান্সের কারণে আপনি যদি খুব কমই আর প্রয়োজন হয়) লেআউটসুউভিউতে যান। ব্যক্তিগতভাবে, আমি সৃজনশীলতার সীমাবদ্ধতা রাখি init
seo

কাস্টম রেন্ডারিং কোডের জন্য, আমাদের কি drawপদ্ধতিটি ওভাররাইড করা উচিত ?
পেট্রাস থেরন 14 ই

14

অ্যাপল ডকুমেন্টেশনে একটি শালীন সংক্ষিপ্তসার রয়েছে এবং এটি আইটিউনসে উপলব্ধ ফ্রি স্ট্যানফোর্ড কোর্সে ভালভাবে আচ্ছাদিত । আমি আমার টিএল; ডিআর সংস্করণটি এখানে উপস্থাপন করছি:

যদি আপনার ক্লাসটি বেশিরভাগ সাবউভিউ নিয়ে থাকে তবে এগুলিকে বরাদ্দ দেওয়ার সঠিক জায়গাটি initপদ্ধতিগুলিতে। দর্শনগুলির জন্য, দুটি পৃথক initপদ্ধতি কল করা যেতে পারে যা আপনার ভিউটি কোড থেকে বা কোনও নিব / স্টোরিবোর্ড থেকে ইনস্ট্যান্ট করা হচ্ছে কিনা তার উপর নির্ভর করে get আমি যা করি তা হ'ল আমার নিজস্ব setupপদ্ধতি লিখুন এবং তারপরে এটিকে দুটি initWithFrame:এবং initWithCoder:পদ্ধতি উভয় থেকেই কল করুন ।

আপনি যদি কাস্টম অঙ্কন করছেন, আপনি অবশ্যই drawRect:আপনার দৃষ্টিতে ওভাররাইড করতে চান । আপনার কাস্টম ভিউটি যদি বেশিরভাগ ক্ষেত্রে সাবউভিউগুলির জন্য ধারক হয় তবে আপনাকে সম্ভবত এটি করার প্রয়োজন হবে না।

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


আমি আপনার উত্তরটি ভিউ (যা জাগ্রত থেকে নেওয়া হয়েছে) এর সাবভিউয়ের ফ্রেমে এতে পরিবর্তন করতে ব্যবহার করেছি layoutSubViewsit
বিমান

1

layoutSubviews শিশু দৃষ্টিভঙ্গিতে ফ্রেম সেট করতে বোঝানো হয়, ভিউ নিজেই নয়।

কারণ UIView, নির্ধারিত কনস্ট্রাক্টর সাধারণত হয় initWithFrame:(CGRect)frameএবং আপনার ফ্রেমটি সেখানে সেট করা উচিত (বা মধ্যে initWithCoder:), সম্ভবত ফ্রেমের মান পাস করা উপেক্ষা করে। আপনি একটি ভিন্ন নির্মাতা সরবরাহ করতে পারেন এবং ফ্রেমটি সেখানে সেট করতে পারেন।


আপনি আরও বিস্তারিত নিতে পারেন? আমি আপনার মাধ্যমটি জানি না a ভিউ'র সাবভিউয়ের ফ্রেমটি কীভাবে সেট করবেন? দর্শনটি হ'লawakeFromNib
বিমানটি

২০১ 2016-তে দ্রুত এগিয়ে যেতে আপনার সম্ভবত ফ্রেম সেট করা এবং অটোলেআউট (সীমাবদ্ধতা) ব্যবহার করা উচিত নয়। যদি ভিউটি এক্সআইবি (বা স্টোরিবোর্ড) থেকে আসছে, সাব-ভিউটি ইতিমধ্যে সেটআপ হওয়া উচিত।
প্রক্সি
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.