আমি একটি পয়েন্টার আছে UIView
। আমি কীভাবে এর অ্যাক্সেস করব UIViewController
? [self superview]
অন্য UIView
, কিন্তু না UIViewController
, তাই না?
আমি একটি পয়েন্টার আছে UIView
। আমি কীভাবে এর অ্যাক্সেস করব UIViewController
? [self superview]
অন্য UIView
, কিন্তু না UIViewController
, তাই না?
উত্তর:
হ্যাঁ, এটি superview
সেই দৃশ্য যা আপনার দৃষ্টিভঙ্গি ধারণ করে। আপনার দৃষ্টিভঙ্গিটি ঠিক কী এর ভিউ কন্ট্রোলার তা জানা উচিত নয়, কারণ এটি এমভিসি নীতিগুলি ভঙ্গ করে।
অন্যদিকে, কন্ট্রোলার জানে যে এটি কোন দৃষ্টির জন্য দায়ী ( self.view = myView
) এবং সাধারণত, এই দৃষ্টিভঙ্গি নিয়ামককে পরিচালনা করার জন্য পদ্ধতি / ইভেন্টগুলির প্রতিনিধিত্ব করে।
সাধারণত আপনার দৃশ্যের দিকে নির্দেশকের পরিবর্তে আপনার নিয়ামকের কাছে আপনার পয়েন্টার থাকা উচিত যা ফলস্বরূপ কিছু নিয়ন্ত্রণকারী যুক্তি সম্পাদন করতে পারে বা তার দৃষ্টিতে কিছু সরবরাহ করতে পারে।
এর UIResponder
জন্য ডকুমেন্টেশন থেকে nextResponder
:
ইউআইআরআইএসপোন্ডার শ্রেণি পূর্ববর্তী উত্তরদাতাকে স্বয়ংক্রিয়ভাবে সঞ্চয় বা সেট করে না, পরিবর্তে ডিফল্টরূপে শূন্য করে। পরবর্তী উত্তরদাতা সেট করতে সাবক্লাসগুলি অবশ্যই এই পদ্ধতিটিকে ওভাররাইড করতে হবে। ইউআইভিউউ এই পদ্ধতিটি পরিচালনা করে ইউআইভিউকন্ট্রোলার অবজেক্টটি যা এটি পরিচালনা করে (যদি এটি থাকে) বা এর তত্ত্বাবধান (যদি তা না হয়) ফিরে আসে ; ইউআইভিউকন্ট্রোলার তার দর্শনের তত্ত্বাবধানে ফিরে এসে পদ্ধতিটি প্রয়োগ করে; UIWindow অ্যাপ্লিকেশন অবজেক্টটি ফেরত দেয় এবং ইউআইএআইপ্লিকেশন শূন্য করে।
সুতরাং, যদি আপনি কোনও ভিউটি nextResponder
টাইপ না করা পর্যন্ত UIViewController
পুনরাবৃত্তি করেন তবে আপনার কোনও ভিউর প্যারেন্ট ভিউ কনট্রোলার রয়েছে।
দ্রষ্টব্য যে এটিতে এখনও পিতামাতাকে দেখার নিয়ামক না থাকতে পারে । তবে কেবলমাত্র যদি ভিউতে কোনও কনট্রোলারের ভিউয়ের ভিউ হায়ারার্কির অংশ না থাকে।
সুইফট 3 এবং সুইফট 4.1 এক্সটেনশন:
extension UIView {
var parentViewController: UIViewController? {
var parentResponder: UIResponder? = self
while parentResponder != nil {
parentResponder = parentResponder?.next
if let viewController = parentResponder as? UIViewController {
return viewController
}
}
return nil
}
}
সুইফট 2 এক্সটেনশন:
extension UIView {
var parentViewController: UIViewController? {
var parentResponder: UIResponder? = self
while parentResponder != nil {
parentResponder = parentResponder!.nextResponder()
if let viewController = parentResponder as? UIViewController {
return viewController
}
}
return nil
}
}
উদ্দেশ্য-সি বিভাগ:
@interface UIView (mxcl)
- (UIViewController *)parentViewController;
@end
@implementation UIView (mxcl)
- (UIViewController *)parentViewController {
UIResponder *responder = self;
while ([responder isKindOfClass:[UIView class]])
responder = [responder nextResponder];
return (UIViewController *)responder;
}
@end
এই ম্যাক্রো বিভাগ দূষণ এড়ানো:
#define UIViewParentController(__view) ({ \
UIResponder *__responder = __view; \
while ([__responder isKindOfClass:[UIView class]]) \
__responder = [__responder nextResponder]; \
(UIViewController *)__responder; \
})
UIResponder
;)। খুব সম্পাদনকারী পোস্ট।
@ অ্যান্ড্রে এক লাইনে উত্তর ( সুইফট ৪.১-এ পরীক্ষিত ):
extension UIResponder {
public var parentViewController: UIViewController? {
return next as? UIViewController ?? next?.parentViewController
}
}
ব্যবহার:
let vc: UIViewController = view.parentViewController
parentViewController
public
এক্সটেনশনটি যদি একই ফাইলে থাকে তবে এটি UIView
সেট করতে পারেন fileprivate
, সংজ্ঞায়িত করা যায় না এটি সংকলন করে কিন্তু এটি কার্যকর হয় না! 😐
শুধুমাত্র ডিবাগ উদ্দেশ্যে, আপনি ভিউগুলিতে _viewDelegate
তাদের ভিউ কন্ট্রোলারগুলি পেতে কল করতে পারেন । এটি ব্যক্তিগত API, তাই অ্যাপ স্টোরের জন্য নিরাপদ নয়, তবে ডিবাগিংয়ের জন্য এটি দরকারী।
অন্যান্য দরকারী পদ্ধতি:
_viewControllerForAncestor
- প্রথম নিয়ামক পান যা সুপারভিউ চেইনে একটি দৃশ্য পরিচালনা করে। (ধন্যবাদ n00neimp0rtant)_rootAncestorViewController
- পূর্বপুরুষের নিয়ামক পান যার ভিউটি উইন্ডোতে বর্তমানে সেট করা আছে।_viewControllerForAncestor
ততক্ষণ তত্ত্বাবধানগুলি পর্যবেক্ষণ করবে যতক্ষণ না এটি প্রথম দেখার জন্য একজন ভিউ কন্ট্রোলারের অন্তর্ভুক্ত।
ইউআইভিউ কনকন্ট্রোলারের ইউআইভিউ থাকার বিষয়ে রেফারেন্স পেতে আপনি ইউআইআরআইএসপন্ডার (যা ইউআইভিউ এবং ইউআইভিউউকন্ট্রোলারের জন্য সুপার ক্লাস) বর্ধন করতে পারেন, যা প্রতিক্রিয়াশীল চেইনের মাধ্যমে যেতে পারে এবং এইভাবে ইউআইভিউউকন্ট্রোলারে পৌঁছাতে পারে (অন্যথায় শূন্যপদে ফিরে আসবে)।
extension UIResponder {
func getParentViewController() -> UIViewController? {
if self.nextResponder() is UIViewController {
return self.nextResponder() as? UIViewController
} else {
if self.nextResponder() != nil {
return (self.nextResponder()!).getParentViewController()
}
else {return nil}
}
}
}
//Swift 3
extension UIResponder {
func getParentViewController() -> UIViewController? {
if self.next is UIViewController {
return self.next as? UIViewController
} else {
if self.next != nil {
return (self.next!).getParentViewController()
}
else {return nil}
}
}
}
let vc = UIViewController()
let view = UIView()
vc.view.addSubview(view)
view.getParentViewController() //provide reference to vc
সুইফট 3 এ দ্রুত এবং জেনেরিক উপায়:
extension UIResponder {
func parentController<T: UIViewController>(of type: T.Type) -> T? {
guard let next = self.next else {
return nil
}
return (next as? T) ?? next.parentController(of: T.self)
}
}
//Use:
class MyView: UIView {
...
let parentController = self.parentController(of: MyViewController.self)
}
আপনি যদি কোডটির সাথে পরিচিত না হন এবং আপনি প্রদত্ত দর্শনে ভিউকন্ট্রোলার কোরস্পন্ডিং খুঁজে পেতে চান, তবে আপনি চেষ্টা করতে পারেন:
po (ইউআইভিউ *) 0x7fe523bd3000 po [(ইউআইভিউ *) 0x7fe523bd3000 পরবর্তী পুনরায় সরবরাহকারী] po [[(ইউআইভিউ *) 0x7fe523bd3000 পরের প্রতিবেদনকারী] পরবর্তী রেসপন্ডার] পো [[[(ইউআইভিউ *) 0x7fe523bd3000 পরবর্তী রেসপন্ডার] পরবর্তী রেসপন্ডার] পরবর্তী রেসপন্ডার] ...
বেশিরভাগ ক্ষেত্রে আপনি ইউআইভিউ পাবেন তবে সময়ে সময়ে ইউআইভিউউকন্ট্রোলার ভিত্তিক বর্গ থাকবে।
আমি মনে করি আপনি ভিউ কন্ট্রোলারে ট্যাপটি প্রচার করতে পারেন এবং এটি পরিচালনা করতে দিন। এটি আরও গ্রহণযোগ্য পদ্ধতির। এর ভিউ থেকে কোনও ভিউ কন্ট্রোলারের অ্যাক্সেসের জন্য, অন্য কোনও উপায় নেই বলে আপনার ভিউ কন্ট্রোলারের একটি রেফারেন্স বজায় রাখা উচিত। এই থ্রেডটি দেখুন, এটি সহায়তা করতে পারে: একটি দৃশ্য থেকে দর্শন নিয়ামক অ্যাক্সেস করা
সুইফট ৩.০ এর জন্য আরও প্রকারের নিরাপদ কোড
extension UIResponder {
func owningViewController() -> UIViewController? {
var nextResponser = self
while let next = nextResponser.next {
nextResponser = next
if let vc = nextResponser as? UIViewController {
return vc
}
}
return nil
}
}
হায় আফসোস, আপনি যদি ভিউ সাবক্লাস না করেন এবং এটিকে কোনও দৃষ্টান্ত সম্পত্তি বা একই রকমের সাথে সরবরাহ না করেন যা দৃশ্যে যুক্ত হওয়ার সাথে সাথে তার ভিতরে ভিউ কন্ট্রোলার রেফারেন্স সঞ্চয় করে ...
বেশিরভাগ ক্ষেত্রে - এই পোস্টের মূল সমস্যাটি ঘিরে কাজ করা খুব সহজ কারণ বেশিরভাগ ভিউ কন্ট্রোলাররা প্রোগ্রামারের কাছে সুপরিচিত সত্তা যারা ভিউকন্ট্রোলারের ভিউতে কোনও সংক্ষিপ্তসার যুক্ত করার জন্য দায়বদ্ধ ছিলেন ;-) যে কারণে আমি অনুমান করি যে অ্যাপল কখনও এই সম্পত্তি যুক্ত করতে বিরক্ত করেনি।
কিছুটা দেরি হলেও এখানে একটি এক্সটেনশন যা আপনাকে ভিউকন্ট্রোলার সহ যে কোনও ধরণের প্রতিক্রিয়াশীল খুঁজে পেতে সক্ষম করে।
extension NSObject{
func findNext(type: AnyClass) -> Any{
var resp = self as! UIResponder
while !resp.isKind(of: type.self) && resp.next != nil
{
resp = resp.next!
}
return resp
}
}
আপনি যদি ব্রেক ব্রেকপয়েন্ট সেট করেন, তবে ভিউ হায়ারার্কি মুদ্রণের জন্য আপনি এটি ডিবাগারে পেস্ট করতে পারেন:
po [[UIWindow keyWindow] recursiveDescription]
আপনার গণ্ডগোলের কোথাও আপনার দেখার পিতামাতাকে খুঁজে পেতে সক্ষম হওয়া উচিত :)
recursiveDescription
শুধুমাত্র দেখার শ্রেণিবিন্যাস ছাপায়, নিয়ন্ত্রণকারীদের নয় view