একাধিক সাবক্লাসের জন্য কীভাবে একক স্টোরিবোর্ড ইউভিউকন্ট্রোলার ব্যবহার করবেন


118

ধরা যাক আমার কাছে একটি স্টোরিবোর্ড রয়েছে UINavigationControllerযাতে প্রাথমিক ভিউ নিয়ামক হিসাবে রয়েছে contains এর রুট ভিউ কন্ট্রোলারটি সাবক্লাস UITableViewController, যা BasicViewController। এটি IBActionযা নেভিগেশন বারের ডান নেভিগেশন বোতামের সাথে সংযুক্ত

রয়েছে সেখান থেকে আমি স্টোরিবোর্ডটি অন্য স্টোরিবোর্ডগুলি তৈরি না করেই অন্য দর্শনের জন্য টেমপ্লেট হিসাবে ব্যবহার করতে চাই। বলুন যে এই দর্শনগুলির ঠিক একই ইন্টারফেস থাকবে তবে শ্রেণীর রুট ভিউ কন্ট্রোলারের সাথে SpecificViewController1এবং SpecificViewController2যা সাবক্লাস BasicViewController
এই 2 টি ভিউ কন্ট্রোলারের IBActionপদ্ধতি ব্যতীত একই কার্যকারিতা এবং ইন্টারফেস থাকবে ।
এটি নিম্নলিখিত মত হবে:

@interface BasicViewController : UITableViewController

@interface SpecificViewController1 : BasicViewController

@interface SpecificViewController2 : BasicViewController

আমি কি এরকম কিছু করতে পারি?
আমি কি কেবল স্টোরিবোর্ড ইনস্ট্যান্ট করতে পারি BasicViewControllerতবে সাবক্লাসে রুট ভিউ কন্ট্রোলার রাখতে পারি SpecificViewController1এবং SpecificViewController2?

ধন্যবাদ।


3
এটি উল্লেখ করার মতো হতে পারে যে আপনি নিব দিয়ে এটি করতে পারেন। তবে আপনি যদি আমার মতো হন যে কেবল স্টোরিবোর্ডের কিছু দুর্দান্ত বৈশিষ্ট্য চান (যেমন স্ট্যাটিক / প্রোটোটাইপ সেল, উদাহরণস্বরূপ), তবে আমি অনুমান করি যে আমাদের ভাগ্য নেই।
জোসেফ লিন

উত্তর:


57

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

এটি স্টোরিবোর্ড সংজ্ঞায় নির্দিষ্ট করা ভিউ কন্ট্রোলারের সাথে ডিফল্টরূপে আরম্ভ হবে।

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

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

আপনি নিতে পারেন এমন কয়েকটি পদ্ধতির:

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

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

এটি দুর্দান্ত হবে যদি অ্যাপল আপনার প্রস্তাব অনুযায়ী যা করার একটি উপায় নিয়ে আসে তবে গ্রাফিক উপাদানগুলি নিয়ামক সাবক্লাসের সাথে প্রাক-সংযুক্ত থাকার বিষয়টি এখনও একটি সমস্যা হয়ে দাঁড়াবে।

নতুন বছর শুভ হোক!! ভাল থাকা


সেটা দ্রুত ছিল. আমি যেমন ভেবেছি, এটা সম্ভব হবে না। বর্তমানে আমি কেবল সেই বেসিকভিউ নিয়ন্ত্রণকারী শ্রেণীর সাথে একটি সমাধান নিয়ে এসেছি এবং কোন "শ্রেণি" / "মোড" এটি হিসাবে কাজ করবে তা নির্দেশ করার জন্য অতিরিক্ত সম্পত্তি রয়েছে। যাই হোক ধন্যবাদ.
ভার্দি

2
খুব খারাপ :( Guess আমি কার্যসংক্রান্ত হিসাবে কপি করে একই দৃশ্য নিয়ামক পেস্ট এবং পরিবর্তন তার বর্গ আছে।
Hlung

1
এবং এ কারণেই আমি স্টোরিবোর্ডগুলি পছন্দ করি না ... কোনওভাবে স্ট্যান্ডার্ড
ভিউয়ের

শুনে তুমি খুব দুঃখ পেয়েছ। আমি সমাধানের সন্ধান করছি
টনি

2
আরও একটি পদ্ধতির রয়েছে: বিভিন্ন প্রতিনিধি এবং ক্রেডিট ফরসেগ-এ কাস্টম যুক্তি নির্দিষ্ট করুন, সঠিক প্রতিনিধি নিয়োগ করুন। এইভাবে, আপনি স্টোরিবোর্ডে 1 টি ইউআইভিউকন্ট্রোলার + 1 ইউআইভিউউকন্ট্রোলার তৈরি করেন তবে আপনার একাধিক বাস্তবায়ন সংস্করণ রয়েছে।
plam4u

45

আমরা যে লাইনের কোড সন্ধান করছি তা হ'ল:

object_setClass(AnyObject!, AnyClass!)

স্টোরিবোর্ডে -> ইউআইভিউউকন্ট্রোলার যুক্ত করুন এটি একটি প্যারেন্টভিসি শ্রেণীর নাম দিন।

class ParentVC: UIViewController {

    var type: Int?

    override func awakeFromNib() {

        if type = 0 {

            object_setClass(self, ChildVC1.self)
        }
        if type = 1 {

            object_setClass(self, ChildVC2.self)
        }  
    }

    override func viewDidLoad() {   }
}

class ChildVC1: ParentVC {

    override func viewDidLoad() {
        super.viewDidLoad()

        println(type)
        // Console prints out 0
    }
}

class ChildVC2: ParentVC {

    override func viewDidLoad() {
        super.viewDidLoad()

        println(type)
        // Console prints out 1
    }
}

5
ধন্যবাদ, এটি কেবল কাজ করে, উদাহরণস্বরূপ:class func instantiate() -> SubClass { let instance = (UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SuperClass") as? SuperClass)! object_setClass(instance, SubClass.self) return (instance as? SubClass)! }
কোকোবোবিজ 10:48

3
আমি নিশ্চিত না যে আমি বুঝতে পারছি এটি কীভাবে কাজ করার কথা। পিতা-মাতা তার ক্লাসটি সন্তানের মতো সেট করে দিচ্ছেন? আপনার একাধিক বাচ্চা থাকতে পারে কীভাবে ?!
ব্যবহারকারী 1366265

2
আপনি স্যার, আমার দিনটি তৈরি করেছেন

2
ঠিক আছে ছেলেরা, সুতরাং আমাকে আরও একটু বিস্তৃতভাবে এটি ব্যাখ্যা করতে দাও: আমরা কী অর্জন করতে চাই? আমরা আমাদের প্যারেন্টভিউ কনট্রোলারকে সাবক্লাস করতে চাই যাতে এর স্টোরিবোর্ডটি আরও ক্লাসের জন্য ব্যবহার করতে পারি। সুতরাং যাদুবিদ্যার রেখাটি যা সব কিছু করে তা আমার সমাধানে হাইলাইট করা হয় এবং অবশ্যই তাকে প্যারেন্টভিসিতে জাগ্রত থেকে নেওয়া উচিত rom তারপরে যা ঘটে তা হ'ল এটি নতুন সেট করা চাইল্ডভিসি 1 থেকে সমস্ত পদ্ধতি ব্যবহার করে যা সাবক্লাস হিসাবে পরিণত হয়। আপনি যদি আরও চাইল্ডভিসির জন্য এটি ব্যবহার করতে চান? কেবল আপনার যুক্তিটি জাগ্রত থেকে নেওয়া করুন .. যদি (টাইপ = ক) {অবজেক্ট_সেটক্লাস (স্ব, চাইল্ডভিসি 1. নিজে)} অন্য {অবজেক্ট_সেটক্লাস (স্ব.চিল্ডভিসি 2.সেলফ)} শুভকামনা।
জিří জহালকা

10
এটি ব্যবহার করার সময় খুব সাবধান! সাধারণত এটি মোটেও ব্যবহার করা উচিত নয় ... এটি কেবলমাত্র প্রদত্ত পয়েন্টারটির আইএসএ পয়েন্টারকে পরিবর্তন করে এবং বিভিন্ন বৈশিষ্ট্যের জন্য যেমন মেমরিকে পুনরায় স্থান দিতে পারে না। এর জন্য একটি সূচক হ'ল পয়েন্টারটি selfপরিবর্তিত হয় না। সুতরাং বস্তুর পরিদর্শন (যেমন _ivar / সম্পত্তি মানগুলি পড়া) এর পরে object_setClassক্র্যাশ হতে পারে।
প্যাট্রিক

15

গৃহীত উত্তর হিসাবে বলা হয়েছে, স্টোরিবোর্ডগুলি দিয়ে করা সম্ভব বলে মনে হচ্ছে না।

আমার সমাধানটি হ'ল নিব ব্যবহার করা - যেমন ডিভগুলি তাদের স্টোরিবোর্ডগুলির আগে ব্যবহার করেছিল। আপনি যদি পুনরায় ব্যবহারযোগ্য, সাবক্লাসেবল ভিউ কন্ট্রোলার (বা এমনকি একটি দর্শন) রাখতে চান তবে আমার সুপারিশটি নিবস ব্যবহার করা use

SubclassMyViewController *myViewController = [[SubclassMyViewController alloc] initWithNibName:@"MyViewController" bundle:nil]; 

আপনি যখন আপনার সমস্ত আউটলেটগুলি "ফাইলের মালিক" এর সাথে সংযুক্ত করেন যখন MyViewController.xibনিবটি কোন শ্রেণীর হিসাবে লোড করা উচিত তা নির্দিষ্ট করে দিচ্ছেন না, আপনি কেবল কী-মান যুক্তগুলি উল্লেখ করছেন: " এই দর্শনটি এই দৃষ্টান্তের পরিবর্তনশীল নামের সাথে সংযুক্ত করা উচিত " " [SubclassMyViewController alloc] initWithNibName:প্রারম্ভিককরণ প্রক্রিয়া কল করার সময় নিব মধ্যে আপনি তৈরি করা ভিউ " নিয়ন্ত্রণ " করতে কোন ভিউ নিয়ন্ত্রণকারী ব্যবহার করা হবে তা নির্দিষ্ট করে ।


আশ্চর্যজনকভাবে মনে হচ্ছে স্টোরিবোর্ডগুলির মাধ্যমে এটি সম্ভব, ওজেসি রানটাইম লাইব্রেরির জন্য ধন্যবাদ। আমার উত্তরটি এখানে দেখুন: স্ট্যাকওভারফ্লো.
com/a/57622836

9

স্টোরিবোর্ডে কাস্টম ভিউ কন্ট্রোলারের বিভিন্ন সাবক্লাস ইনস্ট্যান্ট করা সম্ভব, যদিও এতে কিছুটা অপ্রচলিত কৌশল জড়িত: allocভিউ কন্ট্রোলারের জন্য পদ্ধতিটি ওভাররাইড করে । কাস্টম ভিউ কন্ট্রোলার তৈরি করা হলে, ওভাররাইড বরাদ্দ পদ্ধতি বাস্তবে allocসাবক্লাসে চলার ফলাফল প্রদান করে।

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

প্রদর্শনের উদ্দেশ্যে, আমার কাছে UIViewControllerডাকা একটি সাবক্লাস রয়েছে TestViewController, যার একটি ইউআইএলবেল আইবিউলেট এবং একটি আইবিএ রয়েছে। আমার স্টোরিবোর্ডে, আমি একটি ভিউ কন্ট্রোলার যুক্ত করেছি এবং এর ক্লাসটি সংশোধন TestViewControllerকরেছি এবং আইবিআউটলেটকে একটি ইউআইএলবেল এবং আইবিএশনকে একটি ইউআইবুটনের সাথে সংযুক্ত করেছি। আমি পূর্ববর্তী ভিউকন্ট্রোলারে একটি ইউআইবাটন দ্বারা চালিত একটি মডেল সেগুয়ের মাধ্যমে টেস্টভিউ কনট্রোলার উপস্থাপন করি।

স্টোরিবোর্ডের চিত্র

কোন ক্লাসটি ইনস্ট্যান্ট হয় তা নিয়ন্ত্রণ করতে, আমি একটি স্থিতিশীল ভেরিয়েবল এবং সম্পর্কিত শ্রেণিবদ্ধ পদ্ধতি যুক্ত করেছি যাতে সাবক্লাসটি ব্যবহার করতে সেট / সেট করুন (আমার ধারণা অনুমান করা হয় যে কোন সাবক্লাসটি ইনস্ট্যান্ট করতে হবে তা নির্ধারণের অন্যান্য উপায়গুলি গ্রহণ করতে পারে):

TestViewController.m:

#import "TestViewController.h"

@interface TestViewController ()
@end

@implementation TestViewController

static NSString *_classForStoryboard;

+(NSString *)classForStoryboard {
    return [_classForStoryboard copy];
}

+(void)setClassForStoryBoard:(NSString *)classString {
    if ([NSClassFromString(classString) isSubclassOfClass:[self class]]) {
        _classForStoryboard = [classString copy];
    } else {
        NSLog(@"Warning: %@ is not a subclass of %@, reverting to base class", classString, NSStringFromClass([self class]));
        _classForStoryboard = nil;
    }
}

+(instancetype)alloc {
    if (_classForStoryboard == nil) {
        return [super alloc];
    } else {
        if (NSClassFromString(_classForStoryboard) != [self class]) {
            TestViewController *subclassedVC = [NSClassFromString(_classForStoryboard) alloc];
            return subclassedVC;
        } else {
            return [super alloc];
        }
    }
}

আমার পরীক্ষার জন্য আমার দুটি সাবক্লাস রয়েছে TestViewController: RedTestViewControllerএবং GreenTestViewController। উপশ্রেণীর প্রত্যেকের অতিরিক্ত বৈশিষ্ট্য রয়েছে এবং প্রতিটি ওভাররাইড viewDidLoadভিউটির পটভূমির রঙ পরিবর্তন করতে এবং UILabel IBOutlet এর পাঠ্য আপডেট করতে পারে:

RedTestViewController.m:

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    self.view.backgroundColor = [UIColor redColor];
    self.testLabel.text = @"Set by RedTestVC";
}

GreenTestViewController.m:

- (void)viewDidLoad {
    [super viewDidLoad];

    self.view.backgroundColor = [UIColor greenColor];
    self.testLabel.text = @"Set by GreenTestVC";
}

কিছু উপলক্ষ্যে আমি TestViewControllerনিজেই অন্য সময়ে RedTestViewControllerবা তাত্ক্ষণিকভাবে চাইতে চাই GreenTestViewController। পূর্ববর্তী ভিউ কন্ট্রোলারে, আমি নীচে এলোমেলোভাবে এটি করি:

NSInteger vcIndex = arc4random_uniform(4);
if (vcIndex == 0) {
    NSLog(@"Chose TestVC");
    [TestViewController setClassForStoryBoard:@"TestViewController"];
} else if (vcIndex == 1) {
    NSLog(@"Chose RedVC");
    [TestViewController setClassForStoryBoard:@"RedTestViewController"];
} else if (vcIndex == 2) {
    NSLog(@"Chose BlueVC");
    [TestViewController setClassForStoryBoard:@"BlueTestViewController"];
} else {
    NSLog(@"Chose GreenVC");
    [TestViewController setClassForStoryBoard:@"GreenTestViewController"];
}

নোট করুন যে setClassForStoryBoardপদ্ধতিটি কোনও শ্রেণীর মিশ্রণগুলি এড়ানোর জন্য অনুরোধ করা শ্রেণীর নামটি সত্যই টেস্টভিউ কনট্রোলারের একটি সাবক্লাস কিনা তা পরীক্ষা করে দেখুন। BlueTestViewControllerএই কার্যকারিতাটি পরীক্ষা করার জন্য উপরের রেফারেন্সটি রয়েছে।


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

উপায় দ্বারা এই পদ্ধতিটি দ্রুত আর হিসাবে কাজ বন্ধ করতে পারে কারণ অ্যাপল ভিউ কন্ট্রোলারগুলিতে বরাদ্দ কল বন্ধ করে। উদাহরণস্বরূপ NSManagedObject বর্গ কখন বরাদ্দ পদ্ধতি পায় না। আমি মনে করি অ্যাপল কোডটি অন্য কোনও পদ্ধতিতে অনুলিপি করতে পারে: সম্ভবত + বরাদ্দব্যবস্থাপনা
টিম

7

ইনস্ট্যান্টিয়েটভিউ কন্ট্রোলার উইথআইডেন্টিফায়ারের পরে এটি চেষ্টা করুন।

- (void)setClass:(Class)c {
    object_setClass(self, c);
}

পছন্দ:

SubViewController *vc = [sb instantiateViewControllerWithIdentifier:@"MainViewController"];
[vc setClass:[SubViewController class]];

আপনার কোডটি কী করে সে সম্পর্কে কিছু সহায়ক ব্যাখ্যা যুক্ত করুন।
কোডফোরস্টার

7
আপনি যদি সাবক্লাস থেকে উদাহরণ ভেরিয়েবল ব্যবহার করেন তবে এর সাথে কী ঘটে? আমি ক্র্যাশ অনুমান করছি, কারণ এটি ফিট করার জন্য পর্যাপ্ত মেমরি নেই। আমার পরীক্ষায়, আমি পাচ্ছি EXC_BAD_ACCESS, তাই এটির প্রস্তাব দিচ্ছি না।
লেগোলেস

1
আপনি শিশু শ্রেণিতে নতুন ভেরিয়েবল যুক্ত করলে এটি কার্যকর হবে না। এবং সন্তানের initএছাড়াও বলা হবে না। এই জাতীয় প্রতিবন্ধকতা সমস্ত পদ্ধতির অকেজো করে তোলে।
আল জোঙ্কে

6

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

class func instantiate<T: BasicViewController>(as _: T.Type) -> T? {
        let storyboard = UIStoryboard(name: "StoryboardName", bundle: nil)
        guard let instance = storyboard.instantiateViewController(withIdentifier: "Identifier") as? BasicViewController else {
            return nil
        }
        object_setClass(instance, T.self)
        return instance as? T
    }

জোর মোড়ক এড়ানো (স্যুইফেলিন্ট সতর্কতা) এড়ানোর জন্য বিকল্পগুলি যুক্ত করা হয়, তবে পদ্ধতিটি সঠিক অবজেক্টগুলি দেয়।


5

যদিও এটি কঠোরভাবে একটি সাবক্লাস নয়, আপনি এটি করতে পারেন:

  1. optionএকটি অনুলিপি তৈরি করতে ডকুমেন্ট আউটলাইনে বেস ক্লাসের ভিউ কন্ট্রোলারটি টেনে আনুন
  2. নতুন ভিউ কন্ট্রোলার অনুলিপি স্টোরিবোর্ডের একটি পৃথক স্থানে সরান
  3. পরিচয় পরিদর্শকের সাবক্লাস ভিউ কন্ট্রোলারে ক্লাস পরিবর্তন করুন

এখানে আমি লিখেছি এমন একটি ব্লক টিউটোরিয়াল থেকে একটি উদাহরণ এখানে ViewControllerদিয়ে সাবক্লাসিং করছি WhiskeyViewController:

উপরের তিনটি পদক্ষেপের অ্যানিমেশন

এটি আপনাকে স্টোরিবোর্ডে দৃশ্যের নিয়ামক সাবক্লাসগুলি তৈরি করতে দেয়। তারপরে আপনি instantiateViewControllerWithIdentifier:নির্দিষ্ট সাবক্লাস তৈরি করতে ব্যবহার করতে পারেন।

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


11
এটি কোনও সাবক্লাস সাথি নয়, এটি কেবলমাত্র একটি ভিউকন্ট্রোলারকে নকল করছে।
এস গ্রিন

1
এটা ঠিক না আপনি যখন ক্লাসটি সাবক্লাসে পরিবর্তন করেন তখন এটি একটি সাবক্লাসে পরিণত হয় (পদক্ষেপ 3)। তারপরে আপনি যা কিছু পরিবর্তন করতে চান তা করতে পারেন এবং আপনার সাবক্লাসের আউটলেটগুলি / ক্রিয়াকলাপগুলি আপ করতে পারেন।
অ্যারন ব্র্যাজার

6
আমি মনে করি না আপনি সাবক্লাসিংয়ের ধারণাটি পেয়েছেন।
এস গ্রিন

5
যদি "পরবর্তীতে স্টুবোর্ডের মধ্যে বেস ক্লাস কন্ট্রোলারে পরিবর্তনগুলি সাবক্লাসে প্রচার না করে", তাকে "সাবক্লাসিং" বলা হয় না। এটি অনুলিপি এবং পেস্ট করুন।
superarts.org

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

4

Objc_setclass পদ্ধতি চাইল্ডভিসির উদাহরণ তৈরি করে না। চাইল্ডভিসি থেকে বেরিয়ে যাওয়ার সময়, চাইল্ডভিসি-র ডিনিট কল করা হচ্ছে। যেহেতু চাইল্ডভিসির জন্য আলাদাভাবে কোনও মেমরি বরাদ্দ নেই, তাই অ্যাপ ক্র্যাশ। বেসকন্ট্রোলারের একটি উদাহরণ রয়েছে, যেখানে চাইল্ড ভিসি নেই।


2

আপনি যদি স্টোরিবোর্ডগুলিতে খুব বেশি নির্ভরশীল না হন তবে আপনি নিয়ামকের জন্য পৃথক .xib ফাইল তৈরি করতে পারেন।

প্রধান ভিসিতে যথাযথ ফাইলের মালিক এবং আউটলেটগুলি সেট করুন MainViewControllerএবং ওভাররাইড করুন init(nibName:bundle:)যাতে তার বাচ্চারা একই নিব এবং এর আউটলেটগুলিতে অ্যাক্সেস করতে পারে।

আপনার কোডটি দেখতে এমন হওয়া উচিত:

class MainViewController: UIViewController {
    @IBOutlet weak var button: UIButton!

    override init(nibName nibNameOrNil: String?, bundle nibBundleOrNil: Bundle?) {
        super.init(nibName: "MainViewController", bundle: nil)
    }

    required init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }

    override func viewDidLoad() {
        super.viewDidLoad()
        button.tintColor = .red
    }
}

এবং আপনার শিশু উপাচার্য তার পিতামাতার নিব পুনরায় ব্যবহার করতে সক্ষম হবে:

class ChildViewController: MainViewController {
    override func viewDidLoad() {
        super.viewDidLoad()
        button.tintColor = .blue
    }
}

2

এখান থেকে উত্তর নিয়ে, আমি এই ঝরঝরে সমাধান নিয়ে এসেছি।

এই ফাংশনটি সহ একটি প্যারেন্ট ভিউ কন্ট্রোলার তৈরি করুন।

class ParentViewController: UIViewController {


    func convert<T: ParentViewController>(to _: T.Type) {

        object_setClass(self, T.self)

    }

}

এটি সংকলকটিকে নিশ্চিত করতে অনুমতি দেয় যে চাইল্ড ভিউ কন্ট্রোলারটি পিতামাত্তি নিয়ন্ত্রকের কাছ থেকে উত্তরাধিকার সূত্রে প্রাপ্ত।

তারপরে আপনি যখনই কোনও সাব ক্লাস ব্যবহার করে এই নিয়ামকের কাছে সিগ করতে চান আপনি তা করতে পারেন:

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    super.prepare(for: segue, sender: sender)

    if let parentViewController = segue.destination as? ParentViewController {
        ParentViewController.convert(to: ChildViewController.self)
    }

}

দুর্দান্ত অংশটি হ'ল আপনি নিজের কাছে স্টোরিবোর্ডের রেফারেন্স যুক্ত করতে পারেন এবং তারপরে "পরবর্তী" শিশু প্রদর্শনের নিয়ামককে কল করতে থাকুন calling


1

সম্ভবত সবচেয়ে নমনীয় উপায় হ'ল পুনরায় ব্যবহারযোগ্য দর্শনগুলি ব্যবহার করা।

(পৃথক XIB ফাইলে একটি ভিউ তৈরি করুন বা Container viewস্টোরিবোর্ডের প্রতিটি সাবক্লাস ভিউ কন্ট্রোলার দৃশ্যে এটি যুক্ত করুন)


1
আপনি যখন কম অনুগ্রহ করে মন্তব্য করুন। আমি জানি যে আমি সরাসরি সেই প্রশ্নের উত্তর দিই না তবে আমি মূল সমস্যার সমাধানের প্রস্তাব দিই।
ড্যানস্কিল

1

একটি সহজ, সুস্পষ্ট, দৈনন্দিন সমাধান আছে।

কেবল নতুন স্টোরিবার্ড / নিয়ামকের ভিতরে বিদ্যমান স্টোরিবোর্ড / নিয়ামকটি রেখে দিন। আইটি কনটেইনার ভিউ হিসাবে।

এটি "সাবক্লাসিং" এর হুবহু অনুরূপ ধারণা, কারণ দেখুন নিয়ামকগুলি।

সাবক্লাসের মতো সবকিছুই ঠিক কাজ করে।

আপনি যেমন একটি ভিউ সাবভিউ সাধারণত অন্য দৃশ্যের ভিতরে রেখে দেন , তেমনি স্বাভাবিকভাবেই আপনি অন্য ভিউ কন্ট্রোলারের ভিতরে একটি ভিউ কন্ট্রোলার রেখে দেন

আর কীভাবে আপনি এটা করতে পারেন?

এটি আইওএসের একটি প্রাথমিক অংশ, ধারণা "সাবভিউ" এর মতই সহজ।

এটা সহজ ...

/*

Search screen is just a modification of our List screen.

*/

import UIKit

class Search: UIViewController {
    
    var list: List!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        list = (_sb("List") as! List
        addChild(list)
        view.addSubview(list.view)
        list.view.bindEdgesToSuperview()
        list.didMove(toParent: self)
    }
}

আপনি এখন listযা করতে চান স্পষ্টতই

list.mode = .blah
list.tableview.reloadData()
list.heading = 'Search!'
list.searchBar.isHidden = false

ইত্যাদি ইত্যাদি

ধারক দর্শনগুলি "সাবউকভিউগুলি" যেমন "সাবক্লাসিংয়ের মতো" সাবক্লাসিংয়ের মতো "ঠিক তেমন"।

অবশ্যই স্পষ্টতই, আপনি "একটি লেআউট sublcass" করতে পারবেন না - এর অর্থ কী?

("সাবক্লাসিং" ওও সফ্টওয়্যার সম্পর্কিত এবং "লেআউটগুলি" এর সাথে কোনও সংযোগ নেই))

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

আপনি যখন কোনও নিয়ামক বিন্যাস পুনরায় ব্যবহার করতে চান, আপনি কেবল অন্য নিয়ামকের ভিতরে এটি ধারক করেন।

এটি আইওএসের সবচেয়ে বেসিক মেকানিজমের মতো !!


দ্রষ্টব্য - বছরের পর বছর ধরে এটি একটি ধারক ভিউ হিসাবে গতিশীলভাবে অন্য ভিউ কন্ট্রোলারটিকে লোড করতে তুচ্ছ। শেষ বিভাগে ব্যাখ্যা করা হয়েছে: https://stackoverflow.com/a/23403979/294884

দ্রষ্টব্য - "_sb" হ'ল একটি স্পষ্ট ম্যাক্রো যা আমরা টাইপিং সংরক্ষণের জন্য ব্যবহার করি,

func _sb(_ s: String)->UIViewController {
    // by convention, for a screen "SomeScreen.storyboard" the
    // storyboardID must be SomeScreenID
    return UIStoryboard(name: s, bundle: nil)
       .instantiateViewController(withIdentifier: s + "ID")
}

1

@ জিৎ জহালকার এই অনুপ্রেরণামূলক উত্তরের জন্য ধন্যবাদ, আমি আমার সমাধানটি 4 বছর আগে এখানে উত্তর দিয়েছিলাম , কিন্তু @ সায়কা আমাকে উত্তর হিসাবে পোস্ট করার পরামর্শ দিয়েছিল, তাই এটি এখানে।

আমার প্রকল্পগুলিতে, সাধারণত, আমি যদি কোনও ইউআইভিউকন্ট্রোলার সাবক্লাসের জন্য স্টোরিবোর্ড ব্যবহার করি, তবে স্টোরিবোর্ড instantiate()থেকে সহজেই উদাহরণ তৈরি করতে আমি সবসময় সেই সাবক্লাসে ডাকা একটি স্ট্যাটিক পদ্ধতি প্রস্তুত করি । সুতরাং ওপি-র প্রশ্নের সমাধানের জন্য, আমরা যদি বিভিন্ন সাবক্লাসের জন্য একই স্টোরিবোর্ডটি ভাগ করতে চাই, তবে তা ফেরানোর setClass()আগে আমরা কেবলমাত্র সেই উদাহরণটিতে যেতে পারি।

class func instantiate() -> SubClass {
    let instance = (UIStoryboard(name: "Main", bundle: nil).instantiateViewControllerWithIdentifier("SuperClass") as? SuperClass)!
    object_setClass(instance, SubClass.self)
    return (instance as? SubClass)!
}

0

জিৎ জহালকা উত্তর থেকে কোকোবাবের মন্তব্য আমাকে এই সমাধান পেতে সাহায্য করেছে এবং এটি ভালভাবে কাজ করেছে।

func openChildA() {
    let storyboard = UIStoryboard(name: "Main", bundle: nil);
    let parentController = storyboard
        .instantiateViewController(withIdentifier: "ParentStoryboardID") 
        as! ParentClass;
    object_setClass(parentController, ChildA.self)
    self.present(parentController, animated: true, completion: nil);
}
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.