मेरे पास एक नेविगेशन स्टैक है, जिसमें 5 UIViewControllers हैं। मैं 5 वें व्यू कंट्रौलर में एक बटन के क्लिक पर स्टैक में तीसरे और चौथे दृश्य नियंत्रक को हटाना चाहता हूं। क्या इसे करना संभव है? यदि हां, तो कैसे?
मेरे पास एक नेविगेशन स्टैक है, जिसमें 5 UIViewControllers हैं। मैं 5 वें व्यू कंट्रौलर में एक बटन के क्लिक पर स्टैक में तीसरे और चौथे दृश्य नियंत्रक को हटाना चाहता हूं। क्या इसे करना संभव है? यदि हां, तो कैसे?
जवाबों:
इस कोड का उपयोग करें और आनंद लें:
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
आप पहले सभी व्यू कंट्रोलर्स को ऐरे में प्राप्त कर सकते हैं और फिर संबंधित व्यू कंट्रोलर क्लास के साथ जांच करने के बाद, आप जो चाहें उसे हटा सकते हैं।
यहाँ कोड का छोटा टुकड़ा है:
NSArray* tempVCA = [self.navigationController viewControllers];
for(UIViewController *tempVC in tempVCA)
{
if([tempVC isKindOfClass:[urViewControllerClass class]])
{
[tempVC removeFromParentViewController];
}
}
मुझे लगता है कि इससे आपका काम आसान हो जाएगा।
स्विफ्ट 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")
अधिक संभावित क्रियाओं जैसे कि निष्कासन, सीमा आदि का एक गुच्छा।
स्विफ्ट 5:
navigationController?.viewControllers.removeAll(where: { (vc) -> Bool in
if vc.isKind(of: MyViewController.self) || vc.isKind(of: MyViewController2.self) {
return false
} else {
return true
}
})
return !vc.isKind(of: MyViewController.self) && !vc.isKind(of: MyViewController2.self)
एक पंक्ति में काम करना होगा :-)
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];
। यह अजीब व्यवहार करता है, हटाए गए ViewController नेविगेशन अभी भी दिखा रहा है जब @ robin-ellerkmann द्वारा रिपोर्ट किया गया था
setViewControllers(_:animated:)
में दोनों तरीकों से उस तकनीक का उपयोग कर रहा हूं : कई नियंत्रक पॉप करने के लिए और कई नियंत्रक पुश करने के लिए।
स्विफ्ट 2.0:
var navArray:Array = (self.navigationController?.viewControllers)!
navArray.removeAtIndex(navArray.count-2)
self.navigationController?.viewControllers = navArray
if var navArray = ... { ... }
स्विफ्ट 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)
यदि आप 5th व्यू कंट्रोलर (3rd और 4th को छोड़ कर) से 2nd व्यू कंट्रोलर में जाने का प्रयास कर रहे हैं, तो आप उपयोग करना चाहेंगे [self.navigationController popToviewController:secondViewController]
।
आप secondViewController
नेविगेशन कंट्रोलर स्टैक से प्राप्त कर सकते हैं ।
secondViewController = [self.navigationController.viewControllers objectAtIndex:yourViewControllerIndex];
इसे इस्तेमाल करो
if let navVCsCount = navigationController?.viewControllers.count {
navigationController?.viewControllers.removeSubrange(Range(2..<navVCsCount - 1))
}
यह नेविगेशनकंट्रोलर के ViewControllers का ख्याल रखेगा। viewControllers और भी एक नेविगेशन।
नोट: कम से कम viewDidAppear के बाद इसे कॉल करना सुनिश्चित करें
इस समाधान ने मेरे लिए स्विफ्ट 4 में काम किया:
let VCCount = self.navigationController!.viewControllers.count
self.navigationController?.viewControllers.removeSubrange(Range(VCCount-3..<VCCount - 1))
स्टैक में आपका वर्तमान दृश्य नियंत्रक सूचकांक है:
self.navigationController!.viewControllers.count - 1
स्विफ्ट 5.1, एक्सकोड 11
extension UINavigationController{
public func removePreviousController(total: Int){
let totalViewControllers = self.viewControllers.count
self.viewControllers.removeSubrange(totalViewControllers-total..<totalViewControllers - 1)
}}
पिछले नियंत्रक या viewDidAppear () के नए नियंत्रक के viewDisDisappear () के बाद इस उपयोगिता फ़ंक्शन को कॉल करना सुनिश्चित करें
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 }
}
}
मैंने विधि के साथ एक विस्तार लिखा है जो रूट और टॉप के बीच सभी नियंत्रकों को हटा देता है, जब तक कि अन्यथा निर्दिष्ट न हो।
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)
IOS 12.2 पर परीक्षण, स्विफ्ट 5
// स्टैक से क्लास के नामों द्वारा व्यूकंट्रोलर्स को हटाना और फिर वर्तमान दृश्य को खारिज करना।
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)