নেভিগেশন স্ট্যাক থেকে ভিউকন্ট্রোলারগুলি সরানো হচ্ছে


96

আমার কাছে একটি নেভিগেশন স্ট্যাক রয়েছে, যেখানে 5 টি ইউআইভিউকন্ট্রোলার রয়েছে। আমি 5 তম ভিউ কনট্রোলারের একটি বোতামের ক্লিকের স্ট্যাকের তৃতীয় এবং চতুর্থ ভিউ কনট্রোলারগুলি সরিয়ে দিতে চাই। এটা করা কি সম্ভব? যদি তাই হয়, কিভাবে?

উত্তর:


171

এই কোডটি ব্যবহার করুন এবং উপভোগ করুন:

NSMutableArray *navigationArray = [[NSMutableArray alloc] initWithArray: self.navigationController.viewControllers];

// [navigationArray removeAllObjects];    // This is just for remove all view controller from navigation stack.
[navigationArray removeObjectAtIndex: 2];  // You can pass your index here
self.navigationController.viewControllers = navigationArray;
[navigationArray release];

আশা করি এটা তোমাকে সাহায্য করবে।

সম্পাদনা করুন: সুইফট কোড

guard let navigationController = self.navigationController else { return }
var navigationArray = navigationController.viewControllers // To get all UIViewController stack as Array
navigationArray.remove(at: navigationArray.count - 2) // To remove previous UIViewController
self.navigationController?.viewControllers = navigationArray

আমি এটি বেঁধেছি এবং কাজ করে না। আমাকে জানানো হয়েছিল যে বৈশিষ্ট্যগুলির সাথে কিছু করার কারণে এটি দর্শকদের নিয়ন্ত্রণে রাখে না।
নোহ পাসালাক্কোয়া

4
এটি আইওএস <7 এ কাজ করেছে তবে আইওএস 7-এ অদ্ভুত আচরণের ফলাফল results
বেন এইচ

4
আইওএস 8 এর জন্য দুর্দান্ত কাজ করে!
ইভান আর

4
বিবেক: নেতিবাচক ভোটের আগে আপনি কী চেষ্টা করেছেন এবং সৌজন্যবোধ করেছেন তা আমাকে দেখান।
নিতিন

7
এই পদ্ধতিটি স্ট্যাক থেকে প্রকৃতপক্ষে একজন ভিউকন্ট্রোলারকে সরিয়ে দেয় তবে এমনভাবে একটি নেভিগেশনের স্ট্যাকও দেখা যায় যা ক্ষতিগ্রস্থ হয় না। আইওএস ৮.৪-এ আমি যে আচরণটি পাই তা হ'ল: আমাদের কন্ট্রোলার রয়েছে 1 2 3 4 5. আমি 4 টি সরিয়ে ফেলি, 5-এ দেখানো ব্যাক বোতামটি প্রভাবিত হয় না। আমি ফিরে ক্লিক করি, এটি 3 টি কিন্তু 4 এর শিরোনাম দেখায় আমি আবার ফিরে ক্লিক করি, এটি 3 এর শিরোনাম সহ 3 দেখায়
Radu Simionescu

49

আপনি প্রথমে অ্যারেতে সমস্ত ভিউ কন্ট্রোলার পেতে পারেন এবং তারপরে সংশ্লিষ্ট ভিউ কন্ট্রোলার ক্লাসের সাথে চেক করার পরে আপনি যা চান সেটি মুছতে পারেন।

এখানে কোডের একটি ছোট অংশ রয়েছে:

NSArray* tempVCA = [self.navigationController viewControllers];

for(UIViewController *tempVC in tempVCA)
{
    if([tempVC isKindOfClass:[urViewControllerClass class]])
    {
        [tempVC removeFromParentViewController];
    }
}

আমি মনে করি এটি আপনার কাজকে আরও সহজ করে দেবে।


এটি একাধিক উদ্দেশ্যে ব্যবহার করা যেতে পারে। ধন্যবাদ :)
হেমাং

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

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

4
@ মেহমেটেমেমারে আমি নিজেই.বিভিশনকন্ট্রোলার? .ভিউকন্ট্রোলার্স.রিমোভলাস্ট () সহ সুইফট ২.১ ব্যবহার করি? এটি আমার পক্ষে বেশ ভাল কাজ করে।
রবিন এলার্কম্যান

4
আমি যখন 4 ভিউ কনট্রোলার ছিলাম তখন 80MB ছিল যখন সমস্ত ভিউকন্ট্রোলার লগ আউট করে। স্মৃতি এখনও 80MB। তাই স্মৃতি প্রকাশ হচ্ছে না। :(
অনিল গুপ্ত

40

সুইফট 3 এবং 4/5

self.navigationController!.viewControllers.removeAll()

self.navigationController?.viewControllers.remove(at: "insert here a number")

সুইফট 2.1

সব মুছে ফেলুন:

self.navigationController!.viewControllers.removeAll()

সূচকে অপসারণ

self.navigationController?.viewControllers.removeAtIndex("insert here a number")

অপসারণের সম্ভাব্য ক্রিয়াগুলির একগুচ্ছ যেমন রিমুভাল ফার্স্ট, রেঞ্জ ইত্যাদি


4
আপনার উত্তরটি খুঁজছেন, আমি আমার প্রকল্পের কর্মপ্রবাহের জন্য একটি ধারণা পেয়েছি। অনেক ধন্যবাদ.
অনিরুদ্ধ মহলে

এটি নেভিগেশন নিয়ন্ত্রকটিকে নিজেই সরিয়ে দেয়,
দর্শনীয়

16

সুইফট 5:

navigationController?.viewControllers.removeAll(where: { (vc) -> Bool in
    if vc.isKind(of: MyViewController.self) || vc.isKind(of: MyViewController2.self) {
        return false
    } else {
        return true
    }
})

4
return !vc.isKind(of: MyViewController.self) && !vc.isKind(of: MyViewController2.self)কাজটি এক লাইনে করবে :-)
চিহ্নিত করুন

10

setViewControllersথেকে ফাংশন ব্যবহার UINavigationControllerকরা সবচেয়ে ভাল উপায়। রয়েছে animatedঅ্যানিমেশন সক্রিয় করতে প্যারামিটার।

func setViewControllers(_ viewControllers: [UIViewController], animated: Bool)

প্রশ্নের জন্য দ্রুত উদাহরণ

func goToFifthVC() {

    var currentVCStack = self.navigationController?.viewControllers
    currentVCStack?.removeSubrange(2...3)

    let fifthVC = UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "fifthVC")
    currentVCStack?.append(fifthVC)

    self.navigationController?.setViewControllers(currentVCStack!, animated: true)
}

আমি অন্যান্য উপায় চেষ্টা করেছিলাম [tempVC removeFromParentViewController];। এটি অদ্ভুত আচরণ করে, সরানো ভিউকন্ট্রোলার নেভিগেশন এখনও দেখায় যখন পপ ব্যাক লাইক @ রবিন-এলার্কম্যান দ্বারা রিপোর্ট করা হয়েছে


4
এটি আসলে সেরা সমাধান: ন্যাভিগেশনকন্ট্রোলার থেকে ভিসি সরিয়ে? আমি জম্বি বা রেফারেন্স চক্রও পরীক্ষা করে দেখেছি, এটি নিরাপদ।
ওহাদএম

আমি নিশ্চিত করি যে এটি একটি দুর্দান্ত সমাধান: আমি প্রকৃতপক্ষে সেই setViewControllers(_:animated:)কৌশলটি উভয় উপায়েই ব্যবহার করছি : একাধিক কন্ট্রোলার পপ করতে এবং একাধিক নিয়ামককে ধাক্কা দেওয়ার জন্য।
সিউর

8

সুইফট ২.০:

  var navArray:Array = (self.navigationController?.viewControllers)!
  navArray.removeAtIndex(navArray.count-2)
  self.navigationController?.viewControllers = navArray

4
সুতরাং আপনি নেভিগেশন নিয়ামককে মোড়ক থেকে জোর করে চাপিয়ে দিচ্ছেন না, আপনি এটিকে একটি বিবৃতি দিতে পারেনif var navArray = ... { ... }
কিলি

8

সুইফ্ট 5, এক্সকোড 11.3

আপনি নেভিগেশন স্ট্যাক থেকে কোন ভিউ কন্ট্রোলার (গুলি) মুছে ফেলতে চান তা নির্দিষ্ট করে এই পদ্ধতির সন্ধান পেয়েছি।

extension UINavigationController {

    func removeViewController(_ controller: UIViewController.Type) {
        if let viewController = viewControllers.first(where: { $0.isKind(of: controller.self) }) {
            viewController.removeFromParent()
        }
    }
}

উদাহরণ ব্যবহার:

navigationController.removeViewController(YourViewController.self)

5

যদি আপনি 5 তম ভিউ কন্ট্রোলার (3 য় এবং 4 র্থ এড়ানো) থেকে দ্বিতীয় দর্শন নিয়ন্ত্রকের কাছে যাওয়ার চেষ্টা করছেন, আপনি ব্যবহার করতে চান [self.navigationController popToviewController:secondViewController]

আপনি secondViewControllerনেভিগেশন নিয়ামক স্ট্যাক থেকে এটি পেতে পারেন ।

secondViewController =  [self.navigationController.viewControllers objectAtIndex:yourViewControllerIndex];

4
বর্তমান ভিউকন্ট্রোলারটিকে পপ করতে চান না। বর্তমানের ভিউকন্ট্রোলারটি অক্ষত থাকতে হবে। তবে আমাকে স্ট্যাকের মধ্যে পড়ে থাকা 2 জন ভিউকন্ট্রোলারদের পপ করতে হবে
জিন পল স্কট

পছন্দ করুন আমি ভাবছি কেন পপিংয়ের জন্য না হলে আপনি তা করতে চান?!।
বিগনেশ

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

@ বিগনেশ আইওএস in তে প্রয়োজনীয় হিসাবে কাজ করবে না কারণ 'সোয়াইপ টু পপ' অঙ্গভঙ্গির কারণে
ডেনিস পশকভ

আপনি যা চান তা অর্জন করতে @ জিনপলস্কটটি, আপনার নতুন ভিউ নিয়ন্ত্রকের উদাহরণটি চাপ দেওয়ার আগে সবচেয়ে নিরাপদ জিনিসটি দু'বার পপ করা উচিত।
রাদু সিমিয়নেসকু

4

এটা ব্যবহার কর

if let navVCsCount = navigationController?.viewControllers.count {
    navigationController?.viewControllers.removeSubrange(Range(2..<navVCsCount - 1))
}

এটি নেভিগেশনকন্ট্রোলারের ভিউকন্ট্রোলারদের যত্ন নেবে। ভিউকন্ট্রোলার এবং একটি নেভিগেশন আইটেমগুলি নেভিগেশনবারে স্ট্যাক করা আছে।

দ্রষ্টব্য: কমপক্ষে ভিডিড অ্যাপের পরে এটিকে কল করতে ভুলবেন না


4
এই পদ্ধতি সুইফট 5, Xcode 10.3 ... যদি দিন navVCsCount = navigationController .viewControllers.count {? Self.navigationController .viewControllers.removeSubrange (- 1 navVCsCount -3 .. <navVCsCount)} মধ্যে আমার জন্য পুরোপুরি কাজ
কেদার Sukerkar

3

সুইফ্ট 5.1, এক্সকোড 11

extension UINavigationController{
public func removePreviousController(total: Int){
    let totalViewControllers = self.viewControllers.count
    self.viewControllers.removeSubrange(totalViewControllers-total..<totalViewControllers - 1)
}}

পূর্ববর্তী কন্ট্রোলারের ভিডিডিস্পায়ার () বা নতুন নিয়ামকের ভিউডিডঅ্যাপার () এর পরে এই ইউটিলিটি ফাংশনটি কল করতে ভুলবেন না


3

বিশদ

  • সুইফ্ট 5.1, এক্সকোড 11.3.1

সমাধান

extension UIViewController {
    func removeFromNavigationController() { navigationController?.removeController(.last) { self == $0 } }
}

extension UINavigationController {
    enum ViewControllerPosition { case first, last }
    enum ViewControllersGroupPosition { case first, last, all }

    func removeController(_ position: ViewControllerPosition, animated: Bool = true,
                          where closure: (UIViewController) -> Bool) {
        var index: Int?
        switch position {
            case .first: index = viewControllers.firstIndex(where: closure)
            case .last: index = viewControllers.lastIndex(where: closure)
        }
        if let index = index { removeControllers(animated: animated, in: Range(index...index)) }
    }

    func removeControllers(_ position: ViewControllersGroupPosition, animated: Bool = true,
                           where closure: (UIViewController) -> Bool) {
        var range: Range<Int>?
        switch position {
            case .first: range = viewControllers.firstRange(where: closure)
            case .last:
                guard let _range = viewControllers.reversed().firstRange(where: closure) else { return }
                let count = viewControllers.count - 1
                range = .init(uncheckedBounds: (lower: count - _range.min()!, upper: count - _range.max()!))
            case .all:
                let viewControllers = self.viewControllers.filter { !closure($0) }
                setViewControllers(viewControllers, animated: animated)
                return
        }
        if let range = range { removeControllers(animated: animated, in: range) }
    }

    func removeControllers(animated: Bool = true, in range: Range<Int>) {
        var viewControllers = self.viewControllers
        viewControllers.removeSubrange(range)
        setViewControllers(viewControllers, animated: animated)
    }

    func removeControllers(animated: Bool = true, in range: ClosedRange<Int>) {
        removeControllers(animated: animated, in: Range(range))
    }
}

private extension Array {
    func firstRange(where closure: (Element) -> Bool) -> Range<Int>? {
        guard var index = firstIndex(where: closure) else { return nil }
        var indexes = [Int]()
        while index < count && closure(self[index]) {
            indexes.append(index)
            index += 1
        }
        if indexes.isEmpty { return nil }
        return Range<Int>(indexes.min()!...indexes.max()!)
    }
}

ব্যবহার

removeFromParent()

navigationController?.removeControllers(in: 1...3)

navigationController?.removeController(.first) { $0 != self }

navigationController?.removeController(.last) { $0 != self }

navigationController?.removeControllers(.all) { $0.isKind(of: ViewController.self) }

navigationController?.removeControllers(.first) { !$0.isKind(of: ViewController.self) }

navigationController?.removeControllers(.last) { $0 != self }

সম্পূর্ণ নমুনা

সমাধান কোডটি এখানে পেস্ট করতে ভুলবেন না

import UIKit

class ViewController2: ViewController {}

class ViewController: UIViewController {

    private var tag: Int = 0
    deinit { print("____ DEINITED: \(self), tag: \(tag)" ) }

    override func viewDidLoad() {
        super.viewDidLoad()
        print("____ INITED: \(self)")
        let stackView = UIStackView()
        stackView.axis = .vertical
        view.addSubview(stackView)
        stackView.translatesAutoresizingMaskIntoConstraints = false
        stackView.centerYAnchor.constraint(equalTo: view.centerYAnchor).isActive = true
        stackView.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true

        stackView.addArrangedSubview(createButton(text: "Push ViewController() white", selector: #selector(pushWhiteViewController)))
        stackView.addArrangedSubview(createButton(text: "Push ViewController() gray", selector: #selector(pushGrayViewController)))
        stackView.addArrangedSubview(createButton(text: "Push ViewController2() green", selector: #selector(pushController2)))
        stackView.addArrangedSubview(createButton(text: "Push & remove previous VC", selector: #selector(pushViewControllerAndRemovePrevious)))
        stackView.addArrangedSubview(createButton(text: "Remove first gray VC", selector: #selector(dropFirstGrayViewController)))
        stackView.addArrangedSubview(createButton(text: "Remove last gray VC", selector: #selector(dropLastGrayViewController)))
        stackView.addArrangedSubview(createButton(text: "Remove all gray VCs", selector: #selector(removeAllGrayViewControllers)))
        stackView.addArrangedSubview(createButton(text: "Remove all VCs exept Last", selector: #selector(removeAllViewControllersExeptLast)))
        stackView.addArrangedSubview(createButton(text: "Remove all exept first and last VCs", selector: #selector(removeAllViewControllersExeptFirstAndLast)))
        stackView.addArrangedSubview(createButton(text: "Remove all ViewController2()", selector: #selector(removeAllViewControllers2)))
        stackView.addArrangedSubview(createButton(text: "Remove first VCs where bg != .gray", selector: #selector(dropFirstViewControllers)))
        stackView.addArrangedSubview(createButton(text: "Remove last VCs where bg == .gray", selector: #selector(dropLastViewControllers)))
    }

    override func viewWillAppear(_ animated: Bool) {
        super.viewWillAppear(animated)
        if title?.isEmpty ?? true { title = "First" }
    }

    private func createButton(text: String, selector: Selector) -> UIButton {
        let button = UIButton()
        button.setTitle(text, for: .normal)
        button.setTitleColor(.blue, for: .normal)
        button.addTarget(self, action: selector, for: .touchUpInside)
        return button
    }
}

extension ViewController {

    private func createViewController<VC: ViewController>(backgroundColor: UIColor = .white) -> VC {
        let viewController = VC()
        let counter = (navigationController?.viewControllers.count ?? -1 ) + 1
        viewController.tag = counter
        viewController.title = "Controller \(counter)"
        viewController.view.backgroundColor = backgroundColor
        return viewController
    }

    @objc func pushWhiteViewController() {
        navigationController?.pushViewController(createViewController(), animated: true)
    }

    @objc func pushGrayViewController() {
        navigationController?.pushViewController(createViewController(backgroundColor: .lightGray), animated: true)
    }

    @objc func pushController2() {
        navigationController?.pushViewController(createViewController(backgroundColor: .green) as ViewController2, animated: true)
    }

    @objc func pushViewControllerAndRemovePrevious() {
        navigationController?.pushViewController(createViewController(), animated: true)
        removeFromNavigationController()
    }

    @objc func removeAllGrayViewControllers() {
        navigationController?.removeControllers(.all) { $0.view.backgroundColor == .lightGray }
    }

    @objc func removeAllViewControllersExeptLast() {
        navigationController?.removeControllers(.all) { $0 != self }
    }

    @objc func removeAllViewControllersExeptFirstAndLast() {
        guard let navigationController = navigationController, navigationController.viewControllers.count > 1 else { return }
        let lastIndex = navigationController.viewControllers.count - 1
        navigationController.removeControllers(in: 1..<lastIndex)
    }

    @objc func removeAllViewControllers2() {
        navigationController?.removeControllers(.all) { $0.isKind(of: ViewController2.self) }
    }

    @objc func dropFirstViewControllers() {
        navigationController?.removeControllers(.first) { $0.view.backgroundColor != .lightGray }
    }

    @objc func dropLastViewControllers() {
        navigationController?.removeControllers(.last) { $0.view.backgroundColor == .lightGray }
    }

    @objc func dropFirstGrayViewController() {
        navigationController?.removeController(.first) { $0.view.backgroundColor == .lightGray }
    }

    @objc func dropLastGrayViewController() {
        navigationController?.removeController(.last) { $0.view.backgroundColor == .lightGray }
    }
}

ফলাফল

এখানে চিত্র বর্ণনা লিখুন


2

এই সমাধানটি আমার পক্ষে দ্রুত 4 এ কাজ করেছে:

let VCCount = self.navigationController!.viewControllers.count
self.navigationController?.viewControllers.removeSubrange(Range(VCCount-3..<VCCount - 1))

স্ট্যাকের মধ্যে আপনার বর্তমান দর্শন নিয়ামক সূচকটি হ'ল:

self.navigationController!.viewControllers.count - 1

0

আমি পদ্ধতি সহ একটি এক্সটেনশন লিখেছি যা অন্যথায় নির্দিষ্ট না করা থাকলে মূল এবং শীর্ষের মধ্যে থাকা সমস্ত কন্ট্রোলারকে সরিয়ে দেয়।

extension UINavigationController {
func removeControllers(between start: UIViewController?, end: UIViewController?) {
    guard viewControllers.count > 1 else { return }
    let startIndex: Int
    if let start = start {
        guard let index = viewControllers.index(of: start) else {
            return
        }
        startIndex = index
    } else {
        startIndex = 0
    }

    let endIndex: Int
    if let end = end {
        guard let index = viewControllers.index(of: end) else {
            return
        }
        endIndex = index
    } else {
        endIndex = viewControllers.count - 1
    }
    let range = startIndex + 1 ..< endIndex
    viewControllers.removeSubrange(range)
}

}

আপনি যদি ব্যাপ্তি ব্যবহার করতে চান (উদাহরণস্বরূপ: 2 থেকে 5) আপনি কেবল ব্যবহার করতে পারেন

    let range = 2 ..< 5
    viewControllers.removeSubrange(range)

আইওএস 12.2, সুইফট 5 এ পরীক্ষিত


0

// স্ট্যাক থেকে শ্রেণি নাম দিয়ে ভিউ কন্ট্রোলারগুলি সরিয়ে এবং তারপরে বর্তমান ভিউটি খারিজ করে।

 self.navigationController?.viewControllers.removeAll(where: { (vc) -> Bool in
      if vc.isKind(of: ViewController.self) || vc.isKind(of: ViewController2.self) 
       {
        return true
        } 
     else 
        {
         return false
         }
        })
self.navigationController?.popViewController(animated: false)
self.dismiss(animated: true, completion: nil)
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.