iOS অ্যাপ্লিকেশন ত্রুটি - সাবউভিউ হিসাবে স্ব যুক্ত করতে পারে না


157

আমি এই ক্র্যাশ প্রতিবেদনটি পেয়েছি, তবে কীভাবে এটি ডিবাগ করা যায় তা আমি জানি না।

Fatal Exception NSInvalidArgumentException
Can't add self as subview
0 ...    CoreFoundation  __exceptionPreprocess + 130
1    libobjc.A.dylib     objc_exception_throw + 38
2    CoreFoundation  -[NSException initWithCoder:]
3    UIKit   -[UIView(Internal) _addSubview:positioned:relativeTo:] + 110
4    UIKit   -[UIView(Hierarchy) addSubview:] + 30
5    UIKit   __53-[_UINavigationParallaxTransition animateTransition:]_block_invoke + 1196
6    UIKit   +[UIView(Animation) performWithoutAnimation:] + 72
7    UIKit   -[_UINavigationParallaxTransition animateTransition:] + 732
8    UIKit   -[UINavigationController _startCustomTransition:] + 2616
9    UIKit   -[UINavigationController _startDeferredTransitionIfNeeded:] + 418
10   UIKit   -[UINavigationController __viewWillLayoutSubviews] + 44
11   UIKit   -[UILayoutContainerView layoutSubviews] + 184
12   UIKit   -[UIView(CALayerDelegate) layoutSublayersOfLayer:] + 346
13   QuartzCore  -[CALayer layoutSublayers] + 142
14   QuartzCore  CA::Layer::layout_if_needed(CA::Transaction*) + 350
15   QuartzCore  CA::Layer::layout_and_display_if_needed(CA::Transaction*) + 16
16   QuartzCore  CA::Context::commit_transaction(CA::Transaction*) + 228
17   QuartzCore  CA::Transaction::commit() + 314
18   QuartzCore  CA::Transaction::observer_callback(__CFRunLoopObserver*, unsigned long, void*) + 56

আইওএস সংস্করণটি 7.0.3। কেউ কি এই অদ্ভুত ক্রাশ অভিজ্ঞতা?

হালনাগাদ:

আমি জানি না আমার কোডে কোথায় এই ক্রাশ হয়েছিল, তাই আমি কোডটি এখানে পোস্ট করতে পারছি না, দুঃখিত।

দ্বিতীয় আপডেট

নীচে উত্তর দেখুন।


3
আপনি কি আমাদের আপনার কোড প্রদর্শন করতে পারেন?
ডেভিড গুলঝিউসার

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

9
এই প্রশ্নটি একটি সঠিক। ব্যবহারকারী এই পরিস্থিতিতে ত্রুটির সঠিক কোড দিতে পারবেন না। কারণ তিনি জানেন না যে কোন দৃশ্যে নিয়ামক কিছু ভুল করছে
রবীন্দ্র বাঘালে

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

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

উত্তর:


51

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

navigationController:didShowViewController:animated:

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


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

আমারো একই ইস্যু ছিল. আমার ক্ষেত্রে এটি ঘটেছিল কারণ অ্যাপ্লিকেশনটি এমন একটি নির্দেশনা কার্যকর করেছে যা নতুন ভিউ কন্ট্রোলারের [newViewController setLabelTitle:...]সাথে Animated:YES.ইউএস পরিবর্তন করার সাথে সাথে নতুন ভিউ কন্ট্রোলারকে কল করার পরে এবং আমি সেটল্যাবলিটিটল পদ্ধতিটিকে নতুন ভিউকন্ট্রোলারের ভিডিডলয়েডে সরানোর সমাধান করেছি solved আমাকে ক্লু দেওয়ার জন্য ধন্যবাদ
jeprubio

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

14

আমরাও এই সমস্যাটি পেতে শুরু করেছি এবং সম্ভাবনা খুব সম্ভবত ছিল যে আমাদের সমস্যাটি একই সমস্যার কারণে হয়েছিল।

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

আমাদের সলিউশনটি ইউআইএনএভিগেশন কন্ট্রোলারের একটি বিভাগ যা উপরের ভিসি সময় মতো নির্দিষ্ট বিন্দু থেকে একই না হলে ধাক্কা / পপগুলি প্রতিরোধ করে।

.h ফাইল:

@interface UINavigationController (SafePushing)

- (id)navigationLock; ///< Obtain "lock" for pushing onto the navigation controller

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock; ///< Uses a horizontal slide transition. Has no effect if the view controller is already in the stack. Has no effect if navigationLock is not the current lock.
- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock; ///< Pops view controllers until the one specified is on top. Returns the popped controllers. Has no effect if navigationLock is not the current lock.
- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated navigationLock:(id)navigationLock; ///< Pops until there's only a single view controller left on the stack. Returns the popped controllers. Has no effect if navigationLock is not the current lock.

@end

.m ফাইল:

@implementation UINavigationController (SafePushing)

- (id)navigationLock
{
    return self.topViewController;
}

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock
{
    if (!navigationLock || self.topViewController == navigationLock) 
        [self pushViewController:viewController animated:animated];
}

- (NSArray *)popToRootViewControllerAnimated:(BOOL)animated navigationLock:(id)navigationLock
{
    if (!navigationLock || self.topViewController == navigationLock)
        return [self popToRootViewControllerAnimated:animated];
    return @[];
}

- (NSArray *)popToViewController:(UIViewController *)viewController animated:(BOOL)animated navigationLock:(id)navigationLock
{
    if (!navigationLock || self.topViewController == navigationLock)
        return [self popToViewController:viewController animated:animated];
    return @[];
}

@end

এখনও পর্যন্ত এটি আমাদের জন্য সমস্যার সমাধান করেছে বলে মনে হচ্ছে। উদাহরণ:

id lock = _dataViewController.navigationController.navigationLock;
[[MyApi sharedClient] getUserProfile:_user.id success:^(MyUser *user) {
    ProfileViewController *pvc = [[ProfileViewController alloc] initWithUser:user];
    [_dataViewController.navigationController pushViewController:pvc animated:YES navigationLock:lock];
}];

মূলত, নিয়মটি হ'ল: কোনও নন-ব্যবহারকারী সম্পর্কিত বিলম্বের আগে প্রাসঙ্গিক ন্যাভাল কন্ট্রোলারের কাছ থেকে একটি লক দখল করার আগে , এবং এটি ধাক্কা / পপ করার কলটিতে অন্তর্ভুক্ত করে।

"লক" শব্দটি কিছুটা দুর্বল শব্দ হতে পারে কারণ এটি এমন কিছু লক ঘটতে পারে যা আনলক করা দরকার, তবে যেহেতু কোনও "আনলক" পদ্ধতি নেই, সম্ভবত এটি ঠিক আছে।

(সিডনোট হিসাবে, "নন-ব্যবহারকারী সম্পর্কিত বিলম্ব" হ'ল কোডের ফলে যে কোনও বিলম্ব ঘটছে, অর্থাত্ অ্যাসিঙ্ক্রোনাস যেকোন কিছু Users মামলা।)


যেহেতু আপনি বলেছেন যে আপনি এই সমাধানটি চেষ্টা করে দেখছেন, তাই এটি কি আপনার জন্য সমস্যাটি সমাধান করেছে?
মাইক ডি

এখনও পর্যন্ত হ্যা. সমস্যাটি আবার দেখা দেয়নি। আমি উত্তর আপডেট করব।
ক্লে

4
আমি আপনার উপর ভিত্তি করে পরিবর্তিত সংস্করণ ব্যবহার করেছি: gist.github.com/mdewolfe/9369751 । দেখে মনে হচ্ছে এটি ঠিক করে দিয়েছে।
মাইক ডি

2
@ কলে এই সমাধানটি পুশ / পপ জন্য কাজ করে। তবে আমি যদি সিগি ব্যবহার করি তবে এই ত্রুটিটি কীভাবে সমাধান করবেন?
গীক

@ কেডল আপনি কি এটি বাস্তবায়নে আমাকে সহায়তা করতে পারেন? লুক stackoverflow.com/q/23247713/1323014 THX
Marckaraujo

12

এই কোডটি এই সমস্যাটি সমাধান করে: https://gist.github.com/nonamelive/9334458

এটি একটি প্রাইভেট এপিআই ব্যবহার করে তবে আমি এটি নিশ্চিত করতে পারি যে এটি অ্যাপ স্টোর নিরাপদ। (এই কোডটি ব্যবহার করে আমার একটি অ্যাপ্লিকেশন অ্যাপ স্টোর দ্বারা অনুমোদিত হয়েছে))

@interface UINavigationController (DMNavigationController)

- (void)didShowViewController:(UIViewController *)viewController animated:(BOOL)animated;

@end

@interface DMNavigationController ()

@property (nonatomic, assign) BOOL shouldIgnorePushingViewControllers;

@end

@implementation DMNavigationViewController

#pragma mark - Push

- (void)pushViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    if (!self.shouldIgnorePushingViewControllers)
    {
        [super pushViewController:viewController animated:animated];
    }

    self.shouldIgnorePushingViewControllers = YES;
}

#pragma mark - Private API

// This is confirmed to be App Store safe.
// If you feel uncomfortable to use Private API, you could also use the delegate method navigationController:didShowViewController:animated:.
- (void)didShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
    [super didShowViewController:viewController animated:animated];
    self.shouldIgnorePushingViewControllers = NO;
}

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

এই কোডটি আমার জন্য সংকলন করে না, কিছু অনুপস্থিত?
ম্যাক্সিমাম বি

8

আমি আমার অ্যাপ্লিকেশনটিতে এই ক্র্যাশ সম্পর্কে আরও বিশদ বর্ণনা করব এবং উত্তর হিসাবে এটি চিহ্নিত করব।

আমার অ্যাপ্লিকেশনটিতে একটি ইউআইএনএভিগেশন কন্ট্রোলার রয়েছে যার সাথে রুট কন্ট্রোলার একটি ইউআইটিএবলভিউ কনট্রোলার যাতে নোটের অবজেক্টগুলির একটি তালিকা থাকে। নোট অবজেক্টটির এইচটিএমএলে একটি সামগ্রীর সম্পত্তি রয়েছে। একটি নোট নির্বাচন করুন বিস্তারিত কন্ট্রোলারে যাবে।

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    //get note object
    DetailViewController *controller = [[DetailViewController alloc] initWithNote:note];
    [self.navigationController pushViewController:controller animated:YES];
}

বিশদ নিয়ামক

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

- (void)viewDidLoad
{
    ...
    [_webView loadHTMLString:note.content baseURL:nil];
    ...
}

এই নিয়ামক হ'ল ওয়েবভিউ নিয়ন্ত্রণের প্রতিনিধি। যদি নোটটিতে লিঙ্কগুলি থাকে তবে একটি লিঙ্ক আলতো চাপুন অ্যাপ্লিকেশন ওয়েব ব্রাউজারে।

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    WebBrowserViewController *browserController = [[WebBrowserViewController alloc] init];
    browserController.startupURL = request.URL;
    [self.navigationController pushViewController:webViewController animated:YES];
    return NO;
}

আমি উপরের ক্র্যাশ প্রতিবেদনটি প্রতিদিন পেয়েছি। আমি জানি না আমার কোডে কোথায় এই ক্রাশ হয়েছিল caused কোনও ব্যবহারকারীর সহায়তায় কিছু তদন্তের পরে, অবশেষে আমি এই ক্র্যাশটি ঠিক করতে সক্ষম হয়েছি। এই এইচটিএমএল সামগ্রীটি ক্রাশের কারণ ঘটবে:

...
<iframe src="http://google.com"></iframe>
...

বিস্তারিত কন্ট্রোলারের ভিউডিডলড পদ্ধতিতে, আমি এই এইচটিএমএলটিকে ওয়েবভিউ নিয়ন্ত্রণে লোড করেছি, ঠিক তার পরে, উপরের প্রতিনিধি পদ্ধতিটিকে অনুরোধের সাথে সাথে তত্ক্ষণাত ডাকা হয়েছিল URL ইউআরএলএইফ্রেমের উত্স (google.com)। এই প্রতিনিধি পদ্ধতিটি ভিডিডএলড => ক্র্যাশের সময় পুশভিউ কনট্রোলার পদ্ধতি কল করে!

আমি নেভিগেশন টাইপ পরীক্ষা করে এই ক্র্যাশটিকে স্থির করেছি:

- (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType)navigationType
{
    if (navigationType != UIWebViewNavigationTypeOther)
    {
        //go to web browser controller
    }
}

আশাকরি এটা সাহায্য করবে


1
যখন ফোন করা হয়েছে তখন অ্যানিমেশন ছাড়াই নিয়ামককে চাপ দেওয়া কি ভাল বিকল্প হবে না viewDidLoad?
রিভেরা

6

আমার একই সমস্যা ছিল, যা কেবল আমার জন্য কাজ করেছিল তা ছিল অ্যানিমেটেড: হ্যাঁ থেকে অ্যানিমেটেড: না।

দেখে মনে হচ্ছে সমস্যাটি অ্যানিমেশন সময়মতো না শেষ হওয়ার কারণে হয়েছিল।

আশা করি এটি কাউকে সাহায্য করবে।


3

এই ত্রুটিটি পুনরুত্পাদন করতে, একই সাথে দু'জন ভিউ কন্ট্রোলারকে চাপ দেওয়ার চেষ্টা করুন। বা একই সাথে ধাক্কা দেওয়া এবং পপিং করা। উদাহরণ:

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

#import "UINavigationController+Consistent.h"
#import <objc/runtime.h>
/// This char is used to add storage for the isPushingViewController property.
static char const * const ObjectTagKey = "ObjectTag";

@interface UINavigationController ()
@property (readwrite,getter = isViewTransitionInProgress) BOOL viewTransitionInProgress;

@end

@implementation UINavigationController (Consistent)

- (void)setViewTransitionInProgress:(BOOL)property {
    NSNumber *number = [NSNumber numberWithBool:property];
    objc_setAssociatedObject(self, ObjectTagKey, number , OBJC_ASSOCIATION_RETAIN);
}


- (BOOL)isViewTransitionInProgress {
    NSNumber *number = objc_getAssociatedObject(self, ObjectTagKey);

    return [number boolValue];
}


#pragma mark - Intercept Pop, Push, PopToRootVC
/// @name Intercept Pop, Push, PopToRootVC

- (NSArray *)safePopToRootViewControllerAnimated:(BOOL)animated {
    if (self.viewTransitionInProgress) return nil;
    if (animated) {
        self.viewTransitionInProgress = YES;
    }
    //-- This is not a recursion, due to method swizzling the call below calls the original  method.
    return [self safePopToRootViewControllerAnimated:animated];

}


- (NSArray *)safePopToViewController:(UIViewController *)viewController animated:(BOOL)animated {
    if (self.viewTransitionInProgress) return nil;
    if (animated) {
        self.viewTransitionInProgress = YES;
    }
    //-- This is not a recursion, due to method swizzling the call below calls the original  method.
    return [self safePopToViewController:viewController animated:animated];
}


- (UIViewController *)safePopViewControllerAnimated:(BOOL)animated {
    if (self.viewTransitionInProgress) return nil;
    if (animated) {
        self.viewTransitionInProgress = YES;
    }
    //-- This is not a recursion, due to method swizzling the call below calls the original  method.
    return [self safePopViewControllerAnimated:animated];
}



- (void)safePushViewController:(UIViewController *)viewController animated:(BOOL)animated {
    self.delegate = self;
    //-- If we are already pushing a view controller, we dont push another one.
    if (self.isViewTransitionInProgress == NO) {
        //-- This is not a recursion, due to method swizzling the call below calls the original  method.
        [self safePushViewController:viewController animated:animated];
        if (animated) {
            self.viewTransitionInProgress = YES;
        }
    }
}


// This is confirmed to be App Store safe.
// If you feel uncomfortable to use Private API, you could also use the delegate method navigationController:didShowViewController:animated:.
- (void)safeDidShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    //-- This is not a recursion. Due to method swizzling this is calling the original method.
    [self safeDidShowViewController:viewController animated:animated];
    self.viewTransitionInProgress = NO;
}


// If the user doesnt complete the swipe-to-go-back gesture, we need to intercept it and set the flag to NO again.
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated {
    id<UIViewControllerTransitionCoordinator> tc = navigationController.topViewController.transitionCoordinator;
    [tc notifyWhenInteractionEndsUsingBlock:^(id<UIViewControllerTransitionCoordinatorContext> context) {
        self.viewTransitionInProgress = NO;
        //--Reenable swipe back gesture.
        self.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)viewController;
        [self.interactivePopGestureRecognizer setEnabled:YES];
    }];
    //-- Method swizzling wont work in the case of a delegate so:
    //-- forward this method to the original delegate if there is one different than ourselves.
    if (navigationController.delegate != self) {
        [navigationController.delegate navigationController:navigationController
                                     willShowViewController:viewController
                                                   animated:animated];
    }
}


+ (void)load {
    //-- Exchange the original implementation with our custom one.
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(pushViewController:animated:)), class_getInstanceMethod(self, @selector(safePushViewController:animated:)));
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(didShowViewController:animated:)), class_getInstanceMethod(self, @selector(safeDidShowViewController:animated:)));
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(popViewControllerAnimated:)), class_getInstanceMethod(self, @selector(safePopViewControllerAnimated:)));
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(popToRootViewControllerAnimated:)), class_getInstanceMethod(self, @selector(safePopToRootViewControllerAnimated:)));
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(popToViewController:animated:)), class_getInstanceMethod(self, @selector(safePopToViewController:animated:)));
}

@end

এই সমাধানটির একটি সমস্যা হ'ল আপনি যদি কল করেন popToRootViewControllerবা popToViewController:যখন আপনি ইতিমধ্যে রুট ভিউ নিয়ন্ত্রণকারী বা ভিউকন্ট্রোলারে রয়েছেন তখন পপ করা didShowViewControllerহবে না , তবে এটি কল করা হবে না এবং এটি আটকে থাকবে viewTransitionInProgress
ডাইভারজিও

1
আপনি এই লাইনগুলি ব্যাখ্যা করতে পারেন: self.interactivePopGestureRecognizer.delegate = (id<UIGestureRecognizerDelegate>)viewController; [self.interactivePopGestureRecognizer setEnabled:YES]; সনাক্তকারী কখন অক্ষম ছিল? এবং কীভাবে আপনি জানেন যে প্রতিনিধিটি কী হওয়া উচিত? এই লাইনগুলিতে, আমার জন্য এটি একবার পপিংয়ের পরে পপ অঙ্গভঙ্গিটি ভেঙে দেয়।
ডাইভারজিও

আমি এটি বাস্তবায়নের চেষ্টা করেছি এবং কিছুক্ষণ পরে এটি নেভিগেশন কন্ট্রোলারটিকে লক করে ফেলেছে, সম্ভবত @divergio এর উল্লেখ অনুসারে।
নীলনক

2

সবেমাত্র এই সমস্যাটিও অভিজ্ঞতা হয়েছে। আমাকে আমার কোডটি আপনাকে দেখাতে দাও:

override func viewDidLoad() { 
  super.viewDidLoad()

  //First, I create a UIView
  let firstFrame = CGRect(x: 50, y: 70, height: 200, width: 200)
  let firstView = UIView(frame: firstFrame)
  firstView.addBackgroundColor = UIColor.yellow
  view.addSubview(firstView) 

  //Now, I want to add a subview inside firstView
  let secondFrame = CGRect(x: 20, y:50, height: 15, width: 35)
  let secondView = UIView(frame: secondFrame)
  secondView.addBackgroundColor = UIColor.green
  firstView.addSubView(firstView)
 }

এই লাইনের কারণে ত্রুটিটি উপস্থিত হয়:

firstView.addSubView(firstView)

আপনি সাবউভিউতে স্ব যুক্ত করতে পারবেন না। আমি কোডের লাইনটি এতে পরিবর্তন করেছি:

firstView.addSubView(secondView)

ত্রুটিটি চলে গেল এবং আমি উভয় মতামত দেখতে সক্ষম হয়েছি। এই ভেবেছিলেন যে এটি উদাহরণস্বরূপ দেখতে চাইবে এমন কাউকে সহায়তা করবে।


আমিও এই পদ্ধতির চেষ্টা করেছিলাম কিন্তু স্ট্যাকট্রেসটি আলাদা হবে এবং ক্র্যাশ হওয়ার কারণে আপনার কোডটির লাইনটি প্রকৃতপক্ষে প্রদর্শন করবে। আমি বিশ্বাস করি উত্স সমস্যাটি প্রশ্ন থেকে আলাদা is
বেন

1

"অ্যাডসুভিউ" এর জন্য আপনার কোডটি অনুসন্ধান করুন।

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

উদাহরণ স্বরূপ:

[self.view addSubview:self.view];

বা:

[self.myLabel addSubview:self.myLabel];

আপনি আপনার ত্রুটিটি পেয়ে শুনে খুশী হয়েছিলেন এবং এখন আমি ঠিক বুঝতে পেরেছি কেন আপনি "সাবউভিউ হিসাবে নিজেকে যুক্ত করতে পারেন না" received এমন এক পর্যায়ে যেখানে আপনার ভিউ 2টি আপনার ন্যাভিগেশন কন্ট্রোলারের রুট ভিউ কন্ট্রোলার হিসাবে আপনি ভিউ 2 কে ধাক্কা দিয়েছিলেন যার ফলে এটি ঘটে: [View2.view addSubview:View2.view]সুতরাং সাবউভিউ হিসাবে নিজেকে যুক্ত করুন adding
মিশাল শটজ

1

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

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

পরিবর্তে আমি একটি পুশ কল সারি কার্যকর করেছি:

// SafeNavigationController.h

@interface SafeNavigationController : UINavigationController
@end

 

// SafeNavigationController.m

#define timeToWaitBetweenAnimations 0.5

@interface SafeNavigationController ()

@property (nonatomic, strong) NSMutableArray * controllersQueue;
@property (nonatomic)         BOOL animateLastQueuedController;
@property (nonatomic)         BOOL pushScheduled;
@property (nonatomic, strong) NSDate * lastAnimatedPushDate;

@end

@implementation SafeNavigationController

- (void)awakeFromNib
{
    [super awakeFromNib];

    self.controllersQueue = [NSMutableArray array];
}

- (void)pushViewController:(UIViewController *)viewController
                  animated:(BOOL)animated
{
    [self.controllersQueue addObject:viewController];
    self.animateLastQueuedController = animated;

    if (self.pushScheduled)
        return;

    // Wait for push animation to finish
    NSTimeInterval timeToWait = self.lastAnimatedPushDate ? timeToWaitBetweenAnimations + [self.lastAnimatedPushDate timeIntervalSinceNow] : 0.0;
    dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)((timeToWait > 0.0 ? timeToWait : 0.0) * NSEC_PER_SEC)),
                   dispatch_get_main_queue(), ^
                   {
                       [self pushQueuedControllers];

                       self.lastAnimatedPushDate = self.animateLastQueuedController ? [NSDate date] : nil;
                       self.pushScheduled = NO;
                   });
    self.pushScheduled = YES;
}

- (void)pushQueuedControllers
{
    for (NSInteger index = 0; index < (NSInteger)self.controllersQueue.count - 1; index++)
    {
        [super pushViewController:self.controllersQueue[index]
                         animated:NO];
    }
    [super pushViewController:self.controllersQueue.lastObject
                     animated:self.animateLastQueuedController];

    [self.controllersQueue removeAllObjects];
}

@end

এটি পুশ এবং পপগুলির মিশ্র সারিগুলি পরিচালনা করে না তবে আমাদের বেশিরভাগ ক্র্যাশগুলি ঠিক করার জন্য এটি একটি ভাল স্টার্টার।

সংক্ষিপ্তসার: https://gist.github.com/rivera-ernesto/0bc628be1e24ff5704ae


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

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

1

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

আমি এখানে একটি সংক্ষেপ আপলোড করেছিজিনিসগুলি সহজ করতে ।

আপনার স্টোরিবোর্ডে নেভিগেশনকন্ট্রোলার হিসাবে আপনি এই নতুন ক্লাসটি সেট করেছেন তা নিশ্চিত করুন।


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

0

@ রবপি দুর্দান্ত ইঙ্গিতের ভিত্তিতে আমি এই জাতীয় সমস্যাগুলি রোধ করার জন্য ইউআইএনএভিগেশন কন্ট্রোলার সাবক্লাস তৈরি করেছি । এটি পুশিং এবং / বা পপিং পরিচালনা করে এবং আপনি নিরাপদে সম্পাদন করতে পারেন:

[self.navigationController pushViewController:vc1 animated:YES];
[self.navigationController pushViewController:vc2 animated:YES];
[self.navigationController pushViewController:vc3 animated:YES];
[self.navigationController popViewControllerAnimated:YES];

যদি 'গ্রহণযোগ্য কনফ্লিক্টিংকম্যান্ডস' পতাকাটি সত্য করে দেয় (ডিফল্টরূপে) ব্যবহারকারীরা ভিসি 1, ভিসি 2, ভিসি 3 এর অ্যানিমেটেড পুশিং দেখতে পাবেন এবং তারপরে ভিসি 3 এর অ্যানিমেটেড পপিং দেখতে পাবেন। যদি 'গ্রহণযোগ্য কনফ্লিক্টিংকম্যান্ডস' মিথ্যা হয়, ভিসি 1 পুরোপুরি ধাক্কা না দেওয়া পর্যন্ত সমস্ত পুশ / পপ অনুরোধ বাতিল করা হবে - সুতরাং অন্যান্য 3 টি কল বাতিল করা হবে।


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

এটি প্রকৃতপক্ষে ওবজিসি এবং আইওএস-এর সাথে ক্র্যাশ হয়েছিল it এটি এখনও এখনও আছে কিনা তা আমি নিশ্চিত করতে পারি না। আপনি কি নিশ্চিত যে animated:trueপতাকাটি দিয়ে আদেশগুলি কার্যকর করছেন ?
hris.to

হ্যাঁ আমি অ্যানিমেটেড: সত্য পতাকা ব্যবহার করছিলাম।
ক্রুইনহ

0

ননামেলিভের সমাধানটি দুর্দান্ত। কিন্তু আপনি ব্যক্তিগত API- টি ব্যবহার করার না চান তাহলে, আপনি শুধু অর্জন করতে পারেন UINavigationControllerDelegatemethod.Or আপনি অ্যানিমেটেড পরিবর্তন করতে পারেন YESথেকে NO। এখানে কোডের একটি নমুনা রয়েছে, আপনি এটি উত্তরাধিকারী হতে পারেন। আশা করি এটি সহায়ক:)

https://github.com/antrix1989/ANNavigationController


0

আমি এই সমস্যাটি অনেক অনুসন্ধান করেছি, এটি একই সাথে দু'এরও বেশি উপাচার্যকে চাপ দিচ্ছে, যার ফলে ধাক্কা দেওয়া অ্যানিমেশন সমস্যা দেখা দেয়, আপনি এইটি উল্লেখ করতে পারেন: সাবউভিউ হিসাবে নিজেকে যুক্ত করা যায় না 崩溃 解决 办法

কেবলমাত্র নিশ্চিত করুন যে একই সময়ে স্থানান্তরের অগ্রগতির জন্য একজন ভিসি রয়েছে , শুভকামনা।


0

কখনও কখনও আপনি ভুলভাবে নিজের দৃষ্টিতে একটি ভিউ যুক্ত করার চেষ্টা করেছিলেন।

halfView.addSubview(halfView)

আপনার সাব ভিউ এ এটি পরিবর্তন করুন।

halfView.addSubview(favView)

0

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

আমি এটিও দেখতে পেলাম যে উইন্ডোর রুট ভিউকন্ট্রোলার প্রদর্শিত হয়, একাধিক পুশ করার পরে আবার একই সমস্যা দেখা দেবে না। (আপনি AppDelegate.swift এ টেস্টকোল্ড স্টার্টআপ (রুটনাভ) মন্তব্য করতে পারেন, এবং ভিউকন্ট্রোলআর সুইউটে টেস্টকোল্ড স্টার্টআপ () মন্তব্যটি আপত্তিহীন করতে পারেন)

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


-2

শেষ নেভিগেশন অ্যানিমেশনটি শেষ করার জন্য, বিলম্ব পদ্ধতিটি ব্যবহার করে আপনার নেভিগেশনটি চেষ্টা করুন,

[self performSelector:<#(SEL)#> withObject:<#(id)#> afterDelay:<#(NSTimeInterval)#>]


-2

একটি দর্শন নিজের মধ্যে একটি সংক্ষিপ্তসার হিসাবে যুক্ত করা যায় না।

মতামত একটি পিতা-সন্তানের স্তরক্রম বজায় রাখে তাই আপনি যদি নিজের মতামতটি একটি মতামত হিসাবে নিজের মধ্যে যুক্ত করেন তবে এটি ব্যতিক্রমের মধ্য দিয়ে যাবে।

কোনও শ্রেণি যদি ইউআইভিউকন্ট্রোলার হয় তবে তার দৃষ্টিভঙ্গি পেতে আপনি স্ব.ভিউ ব্যবহার করুন।

কোনও শ্রেণি যদি ইউআইভিউ ক্লাস হয় তবে তার দৃষ্টিভঙ্গি পেতে আপনি স্ব ব্যবহার করেন।


-3

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


-9

আপনি যদি একটি দৃশ্যে একটি সাবউভি যুক্ত করতে চান তবে আপনি এটি এটি করতে পারেন;

UIView *mainview = [[UIView alloc] initWithFrame:CGRectMake(0, 0, [UIScreen mainScreen].bounds.size.width, [UIScreen mainScreen].bounds.size.height)]; //Creats the mainview
    UIView *subview = [[UIView alloc] initWithFrame:CGRectMake(100, 100, 100, 100)]; //Creates the subview, you can use any kind of Views (UIImageView, UIWebView, UIView…)

    [mainview addSubview:subview]; //Adds subview to mainview

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

@ পোপে আপনি কি আরও ভাল ধারণা পেতে পারেন?
ডেভিড গুলঝিউসার

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

2
আমার ধারণা, কেবল সমস্যাটি বন্ধ করতে এটি তাদের পক্ষে আরও বেশি সহায়ক হয়েছিল। বুঝেছি! স্ট্যাকওভারফ্লোতে কাউকে আসলেই সাহায্য করার চেষ্টা করার জন্য ডেভিড জি এর জন্য +1। আমি আশা করি আমি আপনার নিকটতম ভোট -1 করতে পারে !!! এটি এখনও ব্যবহারকারীদের জন্য ঘটছে এবং এটি আমরা জানি সকলের জন্য এটি iOS7 এ একটি বাগ হতে পারে। সুতরাং কেউ আপত্তিজনক কোড পোস্ট করতে পারে না তার অর্থ এই নয় যে প্রশ্নটি অন্য ব্যবহারকারীদের দেখার জন্য বৈধ এবং মূল্যবান নয়। এমনকি এটি দেখার জন্য যদি অন্য লোকেরা এটির কারণ দেখায় তবে কোনও যৌক্তিক কারণ ছাড়াই একই সমস্যাটি দেখছে। -আরহ
রিচি হায়াট
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.