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


204

আমাকে একটি ক্রিয়া সম্পাদন করতে হবে (অ্যারে খালি করে), যখন একটি এর পিছনের বোতামটি UINavigationControllerটিপানো হয়, যখন বোতামটি এখনও ViewControllerস্ট্যাকের পূর্ববর্তীটি প্রদর্শিত হয়। আমি কীভাবে সুইফট ব্যবহার করে এটি সম্পাদন করতে পারি? এখানে চিত্র বর্ণনা লিখুন

উত্তর:


152

একটি বিকল্প আপনার নিজস্ব কাস্টম ব্যাক বোতাম বাস্তবায়ন করা হবে। আপনার ভিডডিলোড পদ্ধতিতে আপনাকে নিম্নলিখিত কোডটি যুক্ত করতে হবে:

- (void) viewDidLoad {
    [super viewDidLoad];
    self.navigationItem.hidesBackButton = YES;
    UIBarButtonItem *newBackButton = [[UIBarButtonItem alloc] initWithTitle:@"Back" style:UIBarButtonItemStyleBordered target:self action:@selector(back:)];
    self.navigationItem.leftBarButtonItem = newBackButton;
}

- (void) back:(UIBarButtonItem *)sender {
    // Perform your custom actions
    // ...
    // Go back to the previous ViewController
    [self.navigationController popViewControllerAnimated:YES];
}

হালনাগাদ:

সুইফটের সংস্করণটি এখানে:

    override func viewDidLoad {
        super.viewDidLoad()
        self.navigationItem.hidesBackButton = true
        let newBackButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.Bordered, target: self, action: "back:")
        self.navigationItem.leftBarButtonItem = newBackButton
    }

    func back(sender: UIBarButtonItem) {
        // Perform your custom actions
        // ...
        // Go back to the previous ViewController
        self.navigationController?.popViewControllerAnimated(true)
    }

আপডেট 2:

সুইফট 3 এর সংস্করণ এখানে রয়েছে:

    override func viewDidLoad {
        super.viewDidLoad()
        self.navigationItem.hidesBackButton = true
        let newBackButton = UIBarButtonItem(title: "Back", style: UIBarButtonItemStyle.plain, target: self, action: #selector(YourViewController.back(sender:)))
        self.navigationItem.leftBarButtonItem = newBackButton
    }

    func back(sender: UIBarButtonItem) {
        // Perform your custom actions
        // ...
        // Go back to the previous ViewController
        _ = navigationController?.popViewController(animated: true)
    }

2
এটি পূর্ববর্তী ভিউ কন্ট্রোলারে পপ হয় না; এটি রুট ভিউ কন্ট্রোলারে পপ হয়।
রকি

91
সাধারণ ব্যাক বোতামের মতো আমার কীভাবে তীর থাকতে পারে?
টমসওয়ায়ার

@ রকি আপনি ব্যাক ফাংশনে নীচের লাইনটি চেষ্টা করতে পারেন: [স্ব। নেভিগেশন কন্ট্রোলার বরখাস্ত ভিউকন্ট্রোলার অ্যানিমেটেড: হ্যাঁ সমাপ্তি: শূন্য];
মালাজিসি

2
@ টমসওয়ের তার জন্য, দয়া করে নীচের উত্তরটি দেখুন

7
কোনও বৈশিষ্ট্যকে ওভাররাইড করার জন্য সিস্টেম বোতামের বিকল্প প্রতিস্থাপন করা ভাল উপায় নয়। সেরা উপায় নীচের উত্তর! stackoverflow.com/a/27715660/2307276
dpizzuto

477

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

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

কিছু দেখতে হবে:

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    if self.isMovingFromParentViewController {
        // Your code...
    }
}

দ্রুত 4.2

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    if self.isMovingFromParent {
        // Your code...
    }
}

5
@gmogames হ্যাঁ, আপনি এটি করতে পারবেন না। যদিও প্রশ্নটি জিজ্ঞাসা করেনি। ফিরে যাওয়ার ক্রিয়া বন্ধ করতে সক্ষম হওয়ার জন্য আমি অনুমান করি যে আপনাকে সত্যিই বোতামটি ওভাররাইড করতে হবে।
manecosta

13
জন্য সুইফট 3.1 :override func viewWillDisappear(_ animated: Bool) { super.viewWillDisappear(animated) if isMovingFromParentViewController { // Your code... } }
ডগ আমোস

23
viewWillDisappear(animated:)আপনি একটি ফোন কল পেলে ট্রিগার হবে। এটি সম্ভবত আপনি চান না। সম্ভবত ব্যবহার করা আরও ভালwillMove(toParentViewController:)
জো সুজনিক

সুইফট 4-এ, নিখোঁজ : ওভাররাইড ফানক ভিউ উইলডিস্পিয়ার ( অ্যানিমেটেড: বুল)
জাভিয়ের

1
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। পরিষ্কার এবং সহজ।
টেম্পে

60
override func willMove(toParent parent: UIViewController?)
{
    super.willMove(toParent: parent)
    if parent == nil
    {
        print("This VC is 'will' be popped. i.e. the back button was pressed.")
    }
}

2
সুইফট 3 / আইওএস 10 এ কাজ করছেন না, কনসোল প্রিন্টগুলির 'নেস্টেড পপ অ্যানিমেশন দুর্গন্ধযুক্ত নেভিগেশন বারে' ফলস্বরূপ হতে পারে।
itji10 ডিগ্রি

1
একেবারেই ডাকা হচ্ছে না
জুলকারনাইন শাহ

3
কেবল ফিরে যাওয়ার সময় নয়, একটি নতুন উপাচার্যে যাওয়ার সময় এটিরও আহ্বান জানানো হচ্ছে।
হোসে রামিরেজ

@ জোজেমাইট অ্যাপস এর মন্তব্য অনুসারে, কনটেইনার ভিউ কন্ট্রোলার থেকে ভিউ কন্ট্রোলার যুক্ত বা অপসারণের ঠিক আগে ডাকাড্ডিতে এটি রয়েছে।
nstein

2
এটি গ্রহণযোগ্য উত্তর হওয়া উচিত। আর যখন parent == nilআমরা যখন যাচ্ছি ফিরে যাওয়ার parentদৃশ্য
মধ্যে Sylvan ডি অ্যাশ

32

আমি নিম্নলিখিত সহ এটি অর্জন করতে সক্ষম হয়েছি:

সুইফট 3

override func didMoveToParentViewController(parent: UIViewController?) {
   super.didMoveToParentViewController(parent)

   if parent == nil {
      println("Back Button pressed.")
      delegate?.goingBack()
   }           
}

সুইফট 4

override func didMove(toParent parent: UIViewController?) {
    super.didMove(toParent: parent)

    if parent == nil {
        debugPrint("Back Button pressed.")
    }
}

কাস্টম ব্যাক বোতামের দরকার নেই।


এটি ফ্যান্টাস্টিক্স। পুরানো মন্তব্য কিন্তু এখনও সর্বশেষতম সুইফটের সাথে কাজ করে।
ব্যবহারকারী3204765

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

পূর্ববর্তী ব্যক্তি হিসাবে একই মন্তব্য, এই কোডটি পিছনের বোতামটির সক্রিয়করণ সনাক্ত করে না, তবে বর্তমান দৃশ্যের পপ।
ভিল্মির

31

আমি ঠিক (পিছনে) তীর সহ নিয়মিত ঠিক মত একটি ব্যাক বোতাম তৈরি করতে এই (সুইফ্ট) শ্রেণি তৈরি করেছি। এটি নিয়মিত পাঠ্য বা একটি চিত্র সহ একটি বোতাম তৈরি করতে পারে।

ব্যবহার

weak var weakSelf = self

// Assign back button with back arrow and text (exactly like default back button)
navigationItem.leftBarButtonItems = CustomBackButton.createWithText("YourBackButtonTitle", color: UIColor.yourColor(), target: weakSelf, action: #selector(YourViewController.tappedBackButton))

// Assign back button with back arrow and image
navigationItem.leftBarButtonItems = CustomBackButton.createWithImage(UIImage(named: "yourImageName")!, color: UIColor.yourColor(), target: weakSelf, action: #selector(YourViewController.tappedBackButton))

func tappedBackButton() {

    // Do your thing

    self.navigationController!.popViewControllerAnimated(true)
}

CustomBackButtonClass

(স্কেচ এবং পেইন্টকোড প্লাগইন দ্বারা তৈরি পিছনের তীর আঁকার কোড)

class CustomBackButton: NSObject {

    class func createWithText(text: String, color: UIColor, target: AnyObject?, action: Selector) -> [UIBarButtonItem] {
        let negativeSpacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
        negativeSpacer.width = -8
        let backArrowImage = imageOfBackArrow(color: color)
        let backArrowButton = UIBarButtonItem(image: backArrowImage, style: UIBarButtonItemStyle.Plain, target: target, action: action)
        let backTextButton = UIBarButtonItem(title: text, style: UIBarButtonItemStyle.Plain , target: target, action: action)
        backTextButton.setTitlePositionAdjustment(UIOffset(horizontal: -12.0, vertical: 0.0), forBarMetrics: UIBarMetrics.Default)
        return [negativeSpacer, backArrowButton, backTextButton]
    }

    class func createWithImage(image: UIImage, color: UIColor, target: AnyObject?, action: Selector) -> [UIBarButtonItem] {
        // recommended maximum image height 22 points (i.e. 22 @1x, 44 @2x, 66 @3x)
        let negativeSpacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.FixedSpace, target: nil, action: nil)
        negativeSpacer.width = -8
        let backArrowImageView = UIImageView(image: imageOfBackArrow(color: color))
        let backImageView = UIImageView(image: image)
        let customBarButton = UIButton(frame: CGRectMake(0,0,22 + backImageView.frame.width,22))
        backImageView.frame = CGRectMake(22, 0, backImageView.frame.width, backImageView.frame.height)
        customBarButton.addSubview(backArrowImageView)
        customBarButton.addSubview(backImageView)
        customBarButton.addTarget(target, action: action, forControlEvents: .TouchUpInside)
        return [negativeSpacer, UIBarButtonItem(customView: customBarButton)]
    }

    private class func drawBackArrow(frame frame: CGRect = CGRect(x: 0, y: 0, width: 14, height: 22), color: UIColor = UIColor(hue: 0.59, saturation: 0.674, brightness: 0.886, alpha: 1), resizing: ResizingBehavior = .AspectFit) {
        /// General Declarations
        let context = UIGraphicsGetCurrentContext()!

        /// Resize To Frame
        CGContextSaveGState(context)
        let resizedFrame = resizing.apply(rect: CGRect(x: 0, y: 0, width: 14, height: 22), target: frame)
        CGContextTranslateCTM(context, resizedFrame.minX, resizedFrame.minY)
        let resizedScale = CGSize(width: resizedFrame.width / 14, height: resizedFrame.height / 22)
        CGContextScaleCTM(context, resizedScale.width, resizedScale.height)

        /// Line
        let line = UIBezierPath()
        line.moveToPoint(CGPoint(x: 9, y: 9))
        line.addLineToPoint(CGPoint.zero)
        CGContextSaveGState(context)
        CGContextTranslateCTM(context, 3, 11)
        line.lineCapStyle = .Square
        line.lineWidth = 3
        color.setStroke()
        line.stroke()
        CGContextRestoreGState(context)

        /// Line Copy
        let lineCopy = UIBezierPath()
        lineCopy.moveToPoint(CGPoint(x: 9, y: 0))
        lineCopy.addLineToPoint(CGPoint(x: 0, y: 9))
        CGContextSaveGState(context)
        CGContextTranslateCTM(context, 3, 2)
        lineCopy.lineCapStyle = .Square
        lineCopy.lineWidth = 3
        color.setStroke()
        lineCopy.stroke()
        CGContextRestoreGState(context)

        CGContextRestoreGState(context)
    }

    private class func imageOfBackArrow(size size: CGSize = CGSize(width: 14, height: 22), color: UIColor = UIColor(hue: 0.59, saturation: 0.674, brightness: 0.886, alpha: 1), resizing: ResizingBehavior = .AspectFit) -> UIImage {
        var image: UIImage

        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        drawBackArrow(frame: CGRect(origin: CGPoint.zero, size: size), color: color, resizing: resizing)
        image = UIGraphicsGetImageFromCurrentImageContext()
        UIGraphicsEndImageContext()

        return image
    }

    private enum ResizingBehavior {
        case AspectFit /// The content is proportionally resized to fit into the target rectangle.
        case AspectFill /// The content is proportionally resized to completely fill the target rectangle.
        case Stretch /// The content is stretched to match the entire target rectangle.
        case Center /// The content is centered in the target rectangle, but it is NOT resized.

        func apply(rect rect: CGRect, target: CGRect) -> CGRect {
            if rect == target || target == CGRect.zero {
                return rect
            }

            var scales = CGSize.zero
            scales.width = abs(target.width / rect.width)
            scales.height = abs(target.height / rect.height)

            switch self {
                case .AspectFit:
                    scales.width = min(scales.width, scales.height)
                    scales.height = scales.width
                case .AspectFill:
                    scales.width = max(scales.width, scales.height)
                    scales.height = scales.width
                case .Stretch:
                    break
                case .Center:
                    scales.width = 1
                    scales.height = 1
            }

            var result = rect.standardized
            result.size.width *= scales.width
            result.size.height *= scales.height
            result.origin.x = target.minX + (target.width - result.width) / 2
            result.origin.y = target.minY + (target.height - result.height) / 2
            return result
        }
    }
}

SWIFT 3.0

class CustomBackButton: NSObject {

    class func createWithText(text: String, color: UIColor, target: AnyObject?, action: Selector) -> [UIBarButtonItem] {
        let negativeSpacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
        negativeSpacer.width = -8
        let backArrowImage = imageOfBackArrow(color: color)
        let backArrowButton = UIBarButtonItem(image: backArrowImage, style: UIBarButtonItemStyle.plain, target: target, action: action)
        let backTextButton = UIBarButtonItem(title: text, style: UIBarButtonItemStyle.plain , target: target, action: action)
        backTextButton.setTitlePositionAdjustment(UIOffset(horizontal: -12.0, vertical: 0.0), for: UIBarMetrics.default)
        return [negativeSpacer, backArrowButton, backTextButton]
    }

    class func createWithImage(image: UIImage, color: UIColor, target: AnyObject?, action: Selector) -> [UIBarButtonItem] {
        // recommended maximum image height 22 points (i.e. 22 @1x, 44 @2x, 66 @3x)
        let negativeSpacer = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.fixedSpace, target: nil, action: nil)
        negativeSpacer.width = -8
        let backArrowImageView = UIImageView(image: imageOfBackArrow(color: color))
        let backImageView = UIImageView(image: image)
        let customBarButton = UIButton(frame: CGRect(x: 0, y: 0, width: 22 + backImageView.frame.width, height: 22))
        backImageView.frame = CGRect(x: 22, y: 0, width: backImageView.frame.width, height: backImageView.frame.height)
        customBarButton.addSubview(backArrowImageView)
        customBarButton.addSubview(backImageView)
        customBarButton.addTarget(target, action: action, for: .touchUpInside)
        return [negativeSpacer, UIBarButtonItem(customView: customBarButton)]
    }

    private class func drawBackArrow(_ frame: CGRect = CGRect(x: 0, y: 0, width: 14, height: 22), color: UIColor = UIColor(hue: 0.59, saturation: 0.674, brightness: 0.886, alpha: 1), resizing: ResizingBehavior = .AspectFit) {
        /// General Declarations
        let context = UIGraphicsGetCurrentContext()!

        /// Resize To Frame
        context.saveGState()
        let resizedFrame = resizing.apply(CGRect(x: 0, y: 0, width: 14, height: 22), target: frame)
        context.translateBy(x: resizedFrame.minX, y: resizedFrame.minY)
        let resizedScale = CGSize(width: resizedFrame.width / 14, height: resizedFrame.height / 22)
        context.scaleBy(x: resizedScale.width, y: resizedScale.height)

        /// Line
        let line = UIBezierPath()
        line.move(to: CGPoint(x: 9, y: 9))
        line.addLine(to: CGPoint.zero)
        context.saveGState()
        context.translateBy(x: 3, y: 11)
        line.lineCapStyle = .square
        line.lineWidth = 3
        color.setStroke()
        line.stroke()
        context.restoreGState()

        /// Line Copy
        let lineCopy = UIBezierPath()
        lineCopy.move(to: CGPoint(x: 9, y: 0))
        lineCopy.addLine(to: CGPoint(x: 0, y: 9))
        context.saveGState()
        context.translateBy(x: 3, y: 2)
        lineCopy.lineCapStyle = .square
        lineCopy.lineWidth = 3
        color.setStroke()
        lineCopy.stroke()
        context.restoreGState()

        context.restoreGState()
    }

    private class func imageOfBackArrow(_ size: CGSize = CGSize(width: 14, height: 22), color: UIColor = UIColor(hue: 0.59, saturation: 0.674, brightness: 0.886, alpha: 1), resizing: ResizingBehavior = .AspectFit) -> UIImage {
        var image: UIImage

        UIGraphicsBeginImageContextWithOptions(size, false, 0)
        drawBackArrow(CGRect(origin: CGPoint.zero, size: size), color: color, resizing: resizing)
        image = UIGraphicsGetImageFromCurrentImageContext()!
        UIGraphicsEndImageContext()

        return image
    }

    private enum ResizingBehavior {
        case AspectFit /// The content is proportionally resized to fit into the target rectangle.
        case AspectFill /// The content is proportionally resized to completely fill the target rectangle.
        case Stretch /// The content is stretched to match the entire target rectangle.
        case Center /// The content is centered in the target rectangle, but it is NOT resized.

        func apply(_ rect: CGRect, target: CGRect) -> CGRect {
            if rect == target || target == CGRect.zero {
                return rect
            }

            var scales = CGSize.zero
            scales.width = abs(target.width / rect.width)
            scales.height = abs(target.height / rect.height)

            switch self {
            case .AspectFit:
                scales.width = min(scales.width, scales.height)
                scales.height = scales.width
            case .AspectFill:
                scales.width = max(scales.width, scales.height)
                scales.height = scales.width
            case .Stretch:
                break
            case .Center:
                scales.width = 1
                scales.height = 1
            }

            var result = rect.standardized
            result.size.width *= scales.width
            result.size.height *= scales.height
            result.origin.x = target.minX + (target.width - result.width) / 2
            result.origin.y = target.minY + (target.height - result.height) / 2
            return result
        }
    }
}

আইওএস 11 এর জন্য আপনার উত্তরটি আপডেট করার জন্য আপনি কি এত দয়াবান হবেন?
BR41N-FCK

2
হাই @ গুয়েডো, আপনার সমাধানটি নিখুঁত, আমি আপনার কোডটি চেষ্টা করে দেখেছি যে পিছনের বোতামের সামনে জায়গা রয়েছে যদিও আপনি নেতিবাচক প্রস্থের সাথে বার্বুটন যুক্ত করেছেন।
পাভরিউইস

26

আপনি যদি পিছনের তীরের সাথে পিছনে বাটন রাখতে চান তবে আপনি নীচে একটি চিত্র এবং কোড ব্যবহার করতে পারেন

backArrow.png arrow1backArrow@2x.pngarrow2 backArrow@3x.pngarrow3

override func viewDidLoad() {
    super.viewDidLoad()
    let customBackButton = UIBarButtonItem(image: UIImage(named: "backArrow") , style: .plain, target: self, action: #selector(backAction(sender:)))
    customBackButton.imageInsets = UIEdgeInsets(top: 2, left: -8, bottom: 0, right: 0)
    navigationItem.leftBarButtonItem = customBackButton
}

func backAction(sender: UIBarButtonItem) {
    // custom actions here
    navigationController?.popViewController(animated: true)
}

12

আপনি যদি ব্যবহার করেন navigationControllerতবে UINavigationControllerDelegateক্লাসে প্রোটোকল যুক্ত করুন এবং প্রতিনিধি পদ্ধতিটি নিম্নরূপ যুক্ত করুন:

class ViewController:UINavigationControllerDelegate {

    func navigationController(navigationController: UINavigationController, willShowViewController viewController: UIViewController,
animated: Bool) {
        if viewController === self {
            // do here what you want
        }
    }
}

যখনই নেভিগেশন নিয়ামক একটি নতুন স্ক্রিনে স্লাইড হবে তখন এই পদ্ধতিটি বলা হয়। যদি পিছনের বোতামটি টিপানো হয়, তবে নতুন ভিউ কন্ট্রোলার ViewControllerনিজেই।


একটি প্রতিনিধি হিসাবে একটি এনএসওজেক্টপ্রোটোকল ক্লাস ব্যবহার করার সময় যা ভয়ঙ্কর হয়ে ওঠে।
নিক ওয়েইভার

পিছনে বোতামটি চাপলে সর্বদা এটি ডাকা হয় না।
টেড

9

সুইফ্ট 5 এবং এক্সকোড 10.2 এ

দয়া করে কাস্টম বার বোতাম আইটেমটি যুক্ত করবেন না, এই ডিফল্ট আচরণটি ব্যবহার করুন।

এর কোনো প্রয়োজন viewWillDisappear , কোন প্রয়োজন কাস্টম BarButtonItem ইত্যাদি ...

ভিসি যখন তার পিতামাতা থেকে সরানো হয় তখন এটি শনাক্ত করা আরও ভাল।

এই দুটি ফাংশনের যে কোনও একটি ব্যবহার করুন

override func willMove(toParent parent: UIViewController?) {
    super.willMove(toParent: parent)
    if parent == nil {
        callStatusDelegate?.backButtonClicked()//Here write your code
    }
}

override func didMove(toParent parent: UIViewController?) {
    super.didMove(toParent: parent)
    if parent == nil {
        callStatusDelegate?.backButtonClicked()//Here write your code
    }
}

আপনি যদি ব্যাক বোতামের ডিফল্ট আচরণ বন্ধ করতে চান তবে কাস্টম বারবটন আইটেম যুক্ত করুন।


1
মনে রাখবেন যে আপনি প্রোগ্রামিয়ালি পপ করার সময় এটিকেও ডাকা হয়, কেবল ব্যাক বোতাম টিপুন না।
আইএক্সএক্স

7

কোন

override func willMove(toParentViewController parent: UIViewController?) { }

আপনি যে ভিউ কন্ট্রোলারে এই পদ্ধতিটিকে ওভাররাইড করছেন সেখানেও যদি আপনি বিযুক্ত হন তবেও এটির কল হবে । কোন যদি "চেক parent" হয় nilনা না চলন্ত নিশ্চিত হতে একটি সুনির্দিষ্ট উপায় ফিরে সঠিক UIViewControllerUINavigationControllerসঠিকভাবে UIViewControllerএই বর্তমানটিকে উপস্থাপিত করে ফিরে যাওয়া হচ্ছে কিনা তা নির্ধারণ করার জন্য , আপনাকে এর সাথে সামঞ্জস্য করতে হবেUINavigationControllerDelegate প্রোটোকলের ।

হ্যাঁ

দ্রষ্টব্য: MyViewControllerযা কিছু কেবল তার নামUIViewController আপনি যা থেকে ফিরে যেতে সনাক্ত করতে চান ।

1) আপনার ফাইলের শীর্ষে অ্যাড UINavigationControllerDelegate

class MyViewController: UIViewController, UINavigationControllerDelegate {

2) আপনার শ্রেণিতে এমন একটি সম্পত্তি যুক্ত করুন UIViewControllerযা আপনি যেগুলি থেকে বিভক্ত করছেন তা ট্র্যাক করে রাখবে ।

class MyViewController: UIViewController, UINavigationControllerDelegate {

var previousViewController:UIViewController

3) MyViewControllerএর viewDidLoadপদ্ধতিতে selfআপনার জন্য প্রতিনিধি হিসাবে নিয়োগ করুন UINavigationController

override func viewDidLoad() {
    super.viewDidLoad()
    self.navigationController?.delegate = self
}

3) আপনি segue আগে , পূর্ববর্তী UIViewControllerএই সম্পত্তি হিসাবে নির্ধারণ করুন ।

// In previous UIViewController
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "YourSegueID" {
        if let nextViewController = segue.destination as? MyViewController {
            nextViewController.previousViewController = self
        }
    }
}

4) এবং এর একটি পদ্ধতি MyViewControllerঅনুসারেUINavigationControllerDelegate

func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool) {
    if viewController == self.previousViewController {
        // You are going back
    }
}

1
সহায়ক উত্তরের জন্য ধন্যবাদ! পাঠকগণ নির্দিষ্ট ভিউ নিয়ন্ত্রকের কাছে ইউআইএনএভিগেশন কন্ট্রোলারের প্রতিনিধি নির্ধারণের বিষয়ে সতর্ক হন; যদি নেভিগেশন কন্ট্রোলারের ইতিমধ্যে কোনও প্রতিনিধি থাকে, তবে আপনি যে কল্যাব্যাকগুলি প্রত্যাশা করছেন তা অন্য প্রতিনিধি বঞ্চিত করার ঝুঁকিটি চালান। আমাদের অ্যাপ্লিকেশনটিতে, ইউআইএনএভিগেশন কন্ট্রোলারের প্রতিনিধি হ'ল একটি ভাগ করা অবজেক্ট (একটি অ্যাপকোর্ডিনেটর) যা সমস্ত দর্শনীয় নিয়ন্ত্রকের কাছে পয়েন্টার রয়েছে।
বিল ফেথ

7

আমার ক্ষেত্রে সবচেয়ে viewWillDisappearভাল কাজ। তবে কিছু ক্ষেত্রে পূর্বের ভিউ কন্ট্রোলারটি সংশোধন করতে হবে। পূর্ববর্তী ভিউ কন্ট্রোলারে অ্যাক্সেস সহ আমার সমাধানটি এখানে রয়েছে এবং এটি সুইফট 4 এ কাজ করে :

override func viewWillDisappear(_ animated: Bool) {
        super.viewWillDisappear(animated)
        if isMovingFromParentViewController {
            if let viewControllers = self.navigationController?.viewControllers {
                if (viewControllers.count >= 1) {
                    let previousViewController = viewControllers[viewControllers.count-1] as! NameOfDestinationViewController
                    // whatever you want to do
                    previousViewController.callOrModifySomething()
                }
            }
        }
    }

-ভিউডিডিস্পিয়ার (বা -উইউউইলডিস্পায়ার) এমনকি অন্য ভিউ কন্ট্রোলারের দৃশ্যের দ্বারাও ভিউটি আবৃত করা হলেও (<পিছনে বোতামটি চাপলে কেবল নয়) বলা হবে, সুতরাং মুভিংফ্র্যাম্পিয়ারভিউ কনট্রোলার চেক করা দরকার।
বিল ফেইথ

5

বর্তমান নিয়ামক ছাড়ার আগে আমাকে সতর্কতা দেখাতে হবে। সুতরাং আমি এটি এইভাবে করেছি:

  1. UINavigationControllerসাথে এক্সটেনশন যুক্ত করুনUINavigationBarDelegate
  2. আপনার নিয়ামক নেভিগেশন নির্বাচক যুক্ত করুন শোল্ডপপঅনব্যাক (সমাপ্তি :)

এটি কাজ করা হয়েছে)

extension UINavigationController: UINavigationBarDelegate {
    public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
        if let items = navigationBar.items, viewControllers.count < items.count {
            return true
        }

        let clientInfoVC = topViewController as? ClientInfoVC
        if clientInfoVC?.responds(to: #selector(clientInfoVC?.navigationShouldPopOnBack)) ?? false {
            clientInfoVC?.navigationShouldPopOnBack(completion: { isAllowPop in
                if isAllowPop {
                    DispatchQueue.main.async {
                        self.popViewController(animated: true)
                    }
                }
            })
        }

        DispatchQueue.main.async {
            self.popViewController(animated: true)
        }

        return false
    }
}

@objc func navigationShouldPopOnBack(completion: @escaping (Bool) -> ()) {
        let ok = UIAlertAction(title: R.string.alert.actionOk(), style: .default) { _ in
            completion(true)
        }
        let cancel = UIAlertAction(title: R.string.alert.actionCancel(), style: .cancel) { _ in
            completion(false)
        }
        let alertController = UIAlertController(title: "", message: R.string.alert.contractMessage(), preferredStyle: .alert)
        alertController.addAction(ok)
        alertController.addAction(cancel)
        present(alertController, animated: true, completion: nil)
    }

4

আমাদের জিনিস হিসাবে এটি কঠিন নয়। কেবল পরিষ্কার আইটেমের জন্য UIButton এর জন্য একটি ফ্রেম তৈরি করুন, বোতামটির জন্য ক্রিয়া বরাদ্দ করুন এবং নেভিগেশনবারের পিছনে বোতামের উপরে রাখুন। এবং অবশেষে ব্যবহারের পরে বোতামটি সরান।

এখানে সুইট 3 নমুনা কোডটি ইউআইবাটনটির পরিবর্তে ইউআইআইমেজ দিয়ে সম্পন্ন করা হয়েছে

override func viewDidLoad() {
    super.viewDidLoad()
    let imageView = UIImageView()
    imageView.backgroundColor = UIColor.clear
    imageView.frame = CGRect(x:0,y:0,width:2*(self.navigationController?.navigationBar.bounds.height)!,height:(self.navigationController?.navigationBar.bounds.height)!)
    let tapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(back(sender:)))
    imageView.isUserInteractionEnabled = true
    imageView.addGestureRecognizer(tapGestureRecognizer)
    imageView.tag = 1
    self.navigationController?.navigationBar.addSubview(imageView)
    }

কোড লিখুন কার্যকর করা প্রয়োজন

func back(sender: UIBarButtonItem) {

    // Perform your custom actions}
    _ = self.navigationController?.popViewController(animated: true)

    }

ক্রিয়া সম্পাদনের পরে সাবভিউটি সরান

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    for view in (self.navigationController?.navigationBar.subviews)!{
        if view.tag == 1 {
            view.removeFromSuperview()
        }
    }

ধন্যবাদ দোস্ত . :-)
আরশুইন ডেনিয়েভ লাল

স্পর্শ ডাউন করার সময় আপনি কীভাবে রাষ্ট্র তৈরি করবেন?
কোয়াং থাং

এটি আইওএস ১১ এ কাজ করবে বলে মনে হচ্ছে না যখন ইউআইআইমেজভিউয়ের পটভূমির রঙ পরিষ্কার হবে Not এটি একটি ভিন্ন রঙে সেট করুন এবং এটি কাজ করে।
ফর্মগুলি আলতো চাপুন

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


3

সুইফট 3:

override func didMove(toParentViewController parent: UIViewController?) {
    super.didMove(toParentViewController: parent)

    if parent == nil{
        print("Back button was clicked")
    }
}

-did / willMove (toParentViewController :) সম্ভবত "মুভিংফ্রান্সফায়ার্ট ভিউ কনট্রোলার ইন-ভিউউইলডিস্পায়ার চেক করার চেয়ে সম্ভবত এটি কেবল তখনই বলা হয় যখন ভিউ কন্ট্রোলার আসলে পিতামাতার পরিবর্তিত হয় (যখন ভিউটি অন্য ভিসির ভিউ দ্বারা আচ্ছাদিত হয় না) তবে আরও" সঠিক "সমাধানটি হয় ইউআইএনএভিগেশন কন্ট্রোলার প্রতিনিধি পদ্ধতি কার্যকর করতে। সাবধান, যদিও; নেভিগেশনকন্ট্রোলারের যদি ইতিমধ্যে কোনও প্রতিনিধি থাকে, তবে আপনি যে কলিগকে প্রত্যাশা করছেন তা অন্য প্রতিনিধিদের বঞ্চিত করার ঝুঁকিটি চালান।
বিল ফেথ

আমি একটি স্প্লিটভিউ কনট্রোলার দিয়ে পরীক্ষা করেছি। সেখানে, যুক্ত বা সরানোয়ের মধ্যে পার্থক্য তৈরি করতে পারেনি।
ক্লড 31

2

এটা চেষ্টা কর .

self.navigationItem.leftBarButtonItem?.target = "methodname"
func methodname ( ) {            
  //    enter code here
}

এটিও চেষ্টা করে দেখুন।

override func viewWillAppear(animated: Bool) {
  //empty your array
}

2

কেবল নিয়ন্ত্রণ করুন + বার আইটেমটিকে মজাদার নীচে টেনে আনুন। কবজ মত কাজ

@IBAction func done(sender: AnyObject) {
    if((self.presentingViewController) != nil){
        self.dismiss(animated: false, completion: nil)
        print("done")
    }
}

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


2

আপনি সাবক্লাস UINavigationControllerএবং ওভাররাইড করতে পারেনpopViewController(animated: Bool) । সেখানে কিছু কোড কার্যকর করতে সক্ষম হয়ে আপনি ব্যবহারকারীকে পুরোপুরি ফিরে যেতে বাধা দিতে পারেন, উদাহরণস্বরূপ তার বর্তমান কাজটি সংরক্ষণ বা বাতিল করার অনুরোধ জানাতে।

নমুনা বাস্তবায়ন যেখানে আপনি popHandlerধাক্কা নিয়ন্ত্রকদের দ্বারা সেট / সাফ হয়ে যায় এমন একটি সেট করতে পারবেন ।

class NavigationController: UINavigationController
{
    var popHandler: (() -> Bool)?

    override func popViewController(animated: Bool) -> UIViewController?
    {
        guard self.popHandler?() != false else
        {
            return nil
        }
        self.popHandler = nil
        return super.popViewController(animated: animated)
    }
}

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

let hasUnsavedWork: Bool = // ...
(self.navigationController as! NavigationController).popHandler = hasUnsavedWork ?
    {
        // Prompt saving work here with an alert

        return false // Prevent pop until as user choses to save or discard

    } : nil // No unsaved work, we clear popHandler to let it pop normally

একটি চমৎকার স্পর্শ হিসাবে, interactivePopGestureRecognizerযখন ব্যবহারকারী কোনও সোয়াইপ অঙ্গভঙ্গি ব্যবহার করে ফিরে যাওয়ার চেষ্টা করে তখনও এটি কল হয়ে যাবে।


উচ্চতর উত্তর, ধন্যবাদ Rivera
DvixExtract

2

এটি আমার সমাধান

extension UINavigationController: UINavigationBarDelegate {
    public func navigationBar(_ navigationBar: UINavigationBar, shouldPop item: UINavigationItem) -> Bool {
        if let shouldBlock = self.topViewController?.shouldPopFromNavigation() {
            return shouldBlock
        }
        return true
    }
}

extension UIViewController {
    @objc func shouldPopFromNavigation() -> Bool {
        return true
    }
}

আপনার ভিউ কন্ট্রোলারে, আপনি এটির মতো পরিচালনা করতে পারেন:

@objc override func shouldPopFromNavigation() -> Bool {
        // Your dialog, example UIAlertViewController or whatever you want
        return false
    }

1

আমি বুঝতে হিসাবে আপনি আপনার ফাঁকা করার ব্যাপারে arrayহিসাবে আপনি আপনার পিছনে বোতামটি টিপুন এবং আপনার আগের পপ ViewController letআপনার Arrayযা আপনি লোড এই পর্দায় রয়েছে

let settingArray  = NSMutableArray()
@IBAction func Back(sender: AnyObject) {
    self. settingArray.removeAllObjects()
    self.dismissViewControllerAnimated(true, completion: nil)
} 

1
    override public func viewDidLoad() {
         super.viewDidLoad()
         self.navigationController?.navigationBar.topItem?.title = GlobalVariables.selectedMainIconName
         let image = UIImage(named: "back-btn")

         image = image?.imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal)

        self.navigationItem.leftBarButtonItem = UIBarButtonItem(image: image, style: UIBarButtonItemStyle.Plain, target: self, action: #selector(Current[enter image description here][1]ViewController.back) )
    }

    func back() {
      self.navigationController?.popToViewController( self.navigationController!.viewControllers[ self.navigationController!.viewControllers.count - 2 ], animated: true)
    }


1

জন্য সুইফট 5 , আমরা এটা দৃশ্য পরীক্ষা করতে পারবেন অদৃশ্য হয়ে যাবে

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)

    if self.isMovingFromParent {
        delegate?.passValue(clickedImage: selectedImage)
    }
}

1

সুইফ্ট 5 __ এক্সকোড 11.5

আমার ক্ষেত্রে আমি একটি অ্যানিমেশন তৈরি করতে চেয়েছিলাম এবং এটি শেষ হয়ে গেলে ফিরে যান। পিছনের বোতামটির ডিফল্ট ক্রিয়াটি ওভাররাইট করে আপনার কাস্টম ক্রিয়াকে কল করার একটি উপায়:

     override func viewDidAppear(_ animated: Bool) {
        super.viewDidAppear(animated)
        setBtnBack()
    }

    private func setBtnBack() {
        for vw in navigationController?.navigationBar.subviews ?? [] where "\(vw.classForCoder)" == "_UINavigationBarContentView" {
            print("\(vw.classForCoder)")
            for subVw in vw.subviews where "\(subVw.classForCoder)" == "_UIButtonBarButton" {
                let ctrl = subVw as! UIControl
                ctrl.removeTarget(ctrl.allTargets.first, action: nil, for: .allEvents)
                ctrl.addTarget(self, action: #selector(backBarBtnAction), for: .touchUpInside)
            }
        }
    }


    @objc func backBarBtnAction() {
        doSomethingBeforeBack { [weak self](isEndedOk) in
            if isEndedOk {
                self?.navigationController?.popViewController(animated: true)
            }
        }
    }


    private func doSomethingBeforeBack(completion: @escaping (_ isEndedOk:Bool)->Void ) {
        UIView.animate(withDuration: 0.25, animations: { [weak self] in
            self?.vwTxt.alpha = 0
        }) { (isEnded) in
            completion(isEnded)
        }
    }

নেভিগেশনবার দেখুন শ্রেণিবদ্ধতা

অথবা আপনি এই পদ্ধতিটি একবার নেভিগেশনবারের ভিউ হায়ারার্কি অন্বেষণ করতে ব্যবহার করতে পারেন এবং _UIButtonBarButton ভিউতে অ্যাক্সেস পেতে, UIControl এ কাস্ট করা, লক্ষ্য-ক্রিয়াটি সরিয়ে ফেলতে এবং আপনার কাস্টম লক্ষ্যগুলি-ক্রিয়া যুক্ত করতে এই সূচকগুলি পেতে পারেন:

    private func debug_printSubviews(arrSubviews:[UIView]?, level:Int) {
        for (i,subVw) in (arrSubviews ?? []).enumerated() {
            var str = ""
            for _ in 0...level {
                str += "\t"
            }
            str += String(format: "%2d %@",i, "\(subVw.classForCoder)")
            print(str)
            debug_printSubviews(arrSubviews: subVw.subviews, level: level + 1)
        }
    }

    // Set directly the indexs
    private func setBtnBack_method2() {
        // Remove or comment the print lines
        debug_printSubviews(arrSubviews: navigationController?.navigationBar.subviews, level: 0)   
        let ctrl = navigationController?.navigationBar.subviews[1].subviews[0] as! UIControl
        print("ctrl.allTargets: \(ctrl.allTargets)")
        ctrl.removeTarget(ctrl.allTargets.first, action: nil, for: .allEvents)
        print("ctrl.allTargets: \(ctrl.allTargets)")
        ctrl.addTarget(self, action: #selector(backBarBtnAction), for: .touchUpInside)
        print("ctrl.allTargets: \(ctrl.allTargets)")
    }

0

আমি কল করে / ওভাররাইড করে viewWillDisappearএবং তার পরে এই জাতীয় স্ট্যাকটি অ্যাক্সেস করে এটি সম্পাদন করেছি navigationController:

override func viewWillDisappear(animated: Bool) {
    super.viewWillDisappear(animated)

    let stack = self.navigationController?.viewControllers.count

    if stack >= 2 {
        // for whatever reason, the last item on the stack is the TaskBuilderViewController (not self), so we only use -1 to access it
        if let lastitem = self.navigationController?.viewControllers[stack! - 1] as? theViewControllerYoureTryingToAccess {
            // hand over the data via public property or call a public method of theViewControllerYoureTryingToAccess, like
            lastitem.emptyArray()
            lastitem.value = 5
        }
    }
}

0

এইভাবে আমি নিজের সমস্যার জন্য এটি সমাধান করেছি

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    self.navigationItem.leftBarButtonItem?.action = #selector(self.back(sender:))
    self.navigationItem.leftBarButtonItem?.target = self
}

@objc func back(sender: UIBarButtonItem) {

}

0

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

ব্র্যান্ডন এ যেমন উপরে প্রস্তাবিত হয়েছে, আপনার UINavigationControllerDelegateযে ভিউ কন্ট্রোলারের সাথে ফিরে যেতে চান তার সাথে বাস্তবায়ন করতে হবে। একটি ভাল উপায় হ'ল একটি আনইন্ডাইড সেগ তৈরি করা যা আপনি ম্যানুয়ালি বা স্বয়ংক্রিয়ভাবে সঞ্চালন করতে পারেন এবং একই কোডটি কাস্টম সম্পন্ন বোতাম বা পিছনের বোতাম থেকে পুনরায় ব্যবহার করতে পারেন।

প্রথমে আপনার দর্শন নিয়ন্ত্রকটিকে আগ্রহী করে তুলুন (যাকে আপনি ফেরত দেখতে চান) সেটিতে নেভিগেশন নিয়ন্ত্রকের একটি প্রতিনিধি এতে viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()
    navigationController?.delegate = self
}

দ্বিতীয়ত, ওভাররাইড করা ফাইলের নীচে একটি এক্সটেনশন যুক্ত করুন navigationController(willShow:animated:)

extension PickerTableViewController: UINavigationControllerDelegate {

    func navigationController(_ navigationController: UINavigationController,
                              willShow viewController: UIViewController,
                              animated: Bool) {

        if let _ = viewController as? EditComicBookViewController {

            let selectedItemRow = itemList.firstIndex(of: selectedItemName)
            selectedItemIndex = IndexPath(row: selectedItemRow!, section: 0)

            if let selectedCell = tableView.cellForRow(at: selectedItemIndex) {
                performSegue(withIdentifier: "PickedItem", sender: selectedCell)
            }
        }
    }
}

যেহেতু আপনার প্রশ্নে একটি অন্তর্ভুক্ত রয়েছে UITableViewController, তাই আমি সারিটির সূচক পাথটি পাওয়ার জন্য একটি উপায় অন্তর্ভুক্ত করেছি যা ব্যবহারকারী ট্যাপ করেছেন।


0

আপনি আপনার ভিউকন্ট্রোলারের মতো কিছু করতে পারেন

override func navigationShouldPopOnBackButton() -> Bool {
    self.backAction() //Your action you want to perform.
    return true
}

সম্পূর্ণ উত্তরের জন্য যখন 'বার' বোতামটি একটি নাবারে টিপানো হয় তখন সনাক্তকরণ ব্যবহার করুন

আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.