যখন কোনও উপাদান সক্রিয় হয় তখন কীভাবে সূচকপথ পাবেন?


107

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

var point = Int()
func buttonPressed(sender: AnyObject) {
    let pointInTable: CGPoint =         sender.convertPoint(sender.bounds.origin, toView: self.tableView)
    let cellIndexPath = self.tableView.indexPathForRowAtPoint(pointInTable)
    println(cellIndexPath)
    point = cellIndexPath!.row
    println(point)
}

আমি কি বিন্দু ভেরিয়েবলের পরিবর্তে সূচিপথের জন্য নির্বাচন করব? বা আমার এটি কোথায় ব্যবহার করা উচিত?
ভিনসেন্ট

উত্তর:


167

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

guard let cell = sender.superview?.superview as? YourCellClassHere else {
    return // or fatalError() or whatever
}

let indexPath = itemTable.indexPath(for: cell)

কারণ ভিউ হায়ারার্কির মধ্যে একটি টেবিলভিউতে সাবউভিউ হিসাবে এমন কোষ রয়েছে যা পরবর্তীকালে তাদের নিজস্ব 'বিষয়বস্তু মতামত' থাকে তাই এ কারণেই আপনার নিজের কক্ষটি পাওয়ার জন্য আপনাকে অবশ্যই এই বিষয়বস্তুর দৃশ্যের তদারকি করতে হবে। এর ফলস্বরূপ, যদি আপনার বোতামটি সরাসরি ঘরের কনটেন্ট ভিউয়ের পরিবর্তে কোনও সাবউউতে থাকে তবে আপনাকে এটি অ্যাক্সেস করতে আরও অনেক স্তর আরও গভীরতরভাবে যেতে হবে go

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

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

আপনার সেল শ্রেণিতে একটি বন্ধের সম্পত্তি রাখুন, বোতামটির ক্রিয়া পদ্ধতিতে এই অনুরোধ করুন।

class MyCell: UITableViewCell {
    var button: UIButton!

    var buttonAction: ((Any) -> Void)?

    @objc func buttonPressed(sender: Any) {
        self.buttonAction?(sender)
    }
}

তারপরে, আপনি যখন নিজের ঘরটি তৈরি করবেন তখন আপনি cellForRowAtIndexPathআপনার বন্ধের জন্য একটি মূল্য নির্ধারণ করতে পারেন।

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! MyCell
    cell.buttonAction = { sender in
        // Do whatever you want from your button here.
    }
    // OR
    cell.buttonAction = buttonPressed(closure: buttonAction, indexPath: indexPath) // <- Method on the view controller to handle button presses.
}

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


4
ভাল বিক্ষোভ. আমি একজন সক্ষম বিকাশকারী, আমি প্রতিশ্রুতি দিয়েছি;) - আমার উত্তরটি সংশোধন করেছে।
জ্যাকব কিং

12
এটি কোনও বোতাম থেকে সেলটি পাওয়ার উপযুক্ত উপায় নয়। বছরের পর বছর ধরে একটি ঘরের লেআউট পরিবর্তিত হয়েছে এবং যখন এরকম কোডটি কাজ করতে ব্যর্থ হয় তখন। এই পদ্ধতির ব্যবহার করবেন না।
rmaddy

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

4
@ পিন্টুরাজপুট আপনি কি আমার সাথে আপনার দৃষ্টিভঙ্গি বর্ণনা করতে পারবেন? আপনি সম্ভবত এটি দেখছেন কারণ আপনার বোতামটি ঘরের সামগ্রীর দৃশ্যের সরাসরি উপদর্শন নয়।
জ্যাকব কিং

4
@ জিমুতলু আমি সম্পূর্ণরূপে একমত, আমি উত্তরে এটি জানিয়েছি। আমি আরও অনেক দৃust় সমাধানের প্রস্তাব দিয়েছিলাম। আমি আসল জায়গায় রেখে যাওয়ার কারণটি হ'ল কারণ আমি মনে করি যে অন্যান্য ডেভস ইস্যুগুলিকে সম্পূর্ণভাবে ডজ করার চেয়ে একটি অ্যাপ্রোচ দিয়ে দেখানো ভাল, এটি তাদেরকে আপনার দেখা কিছুই শেখায় না। :)
জেকব কিং

61

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

এটি ভিউ হায়ারার্কি বা tagসম্পত্তির ব্যবহার নেভিগেট করার সম্ভাব্য নাজুক পদ্ধতিরও এড়িয়ে চলে , কোষের সূচীগুলি পরিবর্তিত হলে (সন্নিবেশ, মোছা বা পুনঃক্রমের ফলাফল হিসাবে) এতে সমস্যা দেখা দেয়

সেলসুব্লাস.সুইফ্ট

protocol CellSubclassDelegate: class {
    func buttonTapped(cell: CellSubclass)
}

class CellSubclass: UITableViewCell {

@IBOutlet var someButton: UIButton!

weak var delegate: CellSubclassDelegate?

override func prepareForReuse() {
    super.prepareForReuse()
    self.delegate = nil
}

@IBAction func someButtonTapped(sender: UIButton) {
    self.delegate?.buttonTapped(self)
}

ViewController.swift

class MyViewController: UIViewController, CellSubclassDelegate {

    @IBOutlet var tableview: UITableView!

    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        let cell = tableView.dequeueReusableCellWithIdentifier("Cell", forIndexPath: indexPath) as! CellSubclass

        cell.delegate = self

        // Other cell setup

    } 

    //  MARK: CellSubclassDelegate

    func buttonTapped(cell: CellSubclass) {
        guard let indexPath = self.tableView.indexPathForCell(cell) else {
            // Note, this shouldn't happen - how did the user tap on a button that wasn't on screen?
            return
        }

        //  Do whatever you need to do with the indexPath

        print("Button tapped on row \(indexPath.row)")
    }
} 

buttonTappedপ্রতিনিধি ফাংশন এবং দেখুন নিয়ামক হয়। আমার উদাহরণস্বরূপ, someButtonTappedকক্ষে অ্যাকশন পদ্ধতিটি রয়েছে
Paulw11

@ পলউ ১১ ১১ আমি পেয়েছি সেলটিতে কোনও সদস্যের বোতাম নেই এই পদ্ধতিতে@IBAction func someButtonTapped(sender: UIButton) { self.delegate?.buttonTapped(self) }
ইআই ক্যাপ্টেন

4
এটি একটি দুর্দান্ত সমাধান (তদারকির দিকে তাকিয়ে থাকা ট্যাগটি ব্যবহার করে বর্তমানে দুটি বেশি ভোট দিয়ে দুটির মতো খারাপের কাছাকাছি কোথাও নেই) তবে এটি অতিরিক্ত অতিরিক্ত কোড যুক্ত হওয়ার মতো বলে মনে হয়।
বিপাপা

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

4
@ পোলউ 11 আমি প্রথমে ভেবেছিলাম এটি অনেকটা কোড, তবে আমি আগে যা ব্যবহার করেছি তার থেকে অনেক বেশি দৃ res়প্রবণ প্রমাণিত। এই শক্তিশালী সমাধান পোস্ট করার জন্য আপনাকে ধন্যবাদ।
অ্যাড্রিয়ান

54

আপডেট : বোতামটি ধারণ করে এমন কক্ষের সূচিপত্র পাওয়া (বিভাগ এবং সারি উভয়):

বোতাম পজিশন ব্যবহার করা

আপনার buttonTappedপদ্ধতির অভ্যন্তরে, আপনি বোতামটির অবস্থানটি ধরে নিতে পারেন, এটি টেবিলভিউতে স্থানাঙ্কে রূপান্তর করতে পারেন, তারপরে সেই স্থানাঙ্কের সারিটির সূচিপত্রটি পান।

func buttonTapped(_ sender:AnyObject) {
    let buttonPosition:CGPoint = sender.convert(CGPoint.zero, to:self.tableView)
    let indexPath = self.tableView.indexPathForRow(at: buttonPosition)
}

দ্রষ্টব্য : কখনও কখনও সেখানে কোনও টেবিলভিউ সেল থাকা সত্ত্বেও view.convert(CGPointZero, to:self.tableView)আপনি যখন ফাংশনটি ব্যবহার করেন তখন nilকোনও বিন্দুতে একটি সারি সন্ধান করে ফলাফলটি ব্যবহার করার সময় আপনি একটি প্রান্তের ক্ষেত্রে যেতে পারেন । এটির সমাধানের জন্য, উত্স থেকে সামান্য অফসেট এমন একটি বাস্তব স্থানাঙ্ককে পাশ করার চেষ্টা করুন, যেমন:

let buttonPosition:CGPoint = sender.convert(CGPoint.init(x: 5.0, y: 5.0), to:self.tableView)

পূর্ববর্তী উত্তর: ট্যাগ সম্পত্তি ব্যবহার করে (কেবল সারি প্রদান করে)

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

ইন cellForRowAtIndexPath:আপনি ট্যাগ সম্পত্তি সেট করুন:

button.tag = indexPath.row
button.addTarget(self, action: "buttonClicked:", forControlEvents: UIControlEvents.TouchUpInside)

তারপরে, buttonClicked:ফাংশনে, আপনি সেই ট্যাগটি সূচী করুন যেখানে বোতামটি অবস্থিত সূচিপথের সারিটি ধরতে হবে:

func buttonClicked(sender:UIButton) {
    let buttonRow = sender.tag
}

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


4
এটি করার একটি দুর্দান্ত উপায় এবং আমি আপনার প্রতিবেদকটি কিছুটা শুরু করার জন্য এটিকে উত্সাহিত করব, তবে কেবল ত্রুটিটি হ'ল এটির প্রয়োজন হলে সূচকপথটিও অ্যাক্সেস দেয় না। দুর্দান্ত উত্তর যদিও!
জ্যাকব কিং

ধন্যবাদ জ্যাকব! আমি প্রতিনিধি কর্মের প্রশংসা করি। আপনি যদি (ট্যাগ সম্পত্তিটি পুনরায় সেট না করে ) indexPath.sectionঅতিরিক্ত হিসাবে পেতে চান তবে আপনি কেবল ট্যাগটি পরিবর্তন করতে পারেন এবং তারপরে ফাংশনে আপনি ব্যবহার করে এবং উভয়ই অ্যাক্সেস করতে পারবেন । indexPath.rowindexPath.sectioncellForRowAtIndexPath:button.tag = indexPathbuttonClicked:sender.tag.rowsender.tag.section
আয়রন জন বনি

4
এটি কি নতুন বৈশিষ্ট্য, কারণ আমি নিশ্চিত যে ট্যাগের সম্পত্তিটি টাইপ না করে কোন অওবজেক্ট টাইপ না করে তা মনে আছে, যদি না তা দ্রুত সুইড ২.৩ এ পরিবর্তন হয়?
জ্যাকব রাজা

@ জ্যাকবকিং আপনি ঠিক বলেছেন! আমার খারাপ আমি মন্তব্যটি লেখার সময় পুরোপুরি ব্যবধান রেখেছিলাম এবং ভাবছিলাম যে ট্যাগটি টাইপ করা হয়েছে অ্যানোবজেক্ট। ডার্প - আমার কিছু মনে করবেন না। আপনি যদি ট্যাগ হিসাবে ইন্ডেক্সপথটি পাস করতে পারেন তবে এটি কার্যকর হবে ...
আয়রন জন

4
সত্যই ভাল হয় না। একটি জিনিসের জন্য, এটি কেবল টেবিল ভিউগুলিতে কাজ করবে যেখানে একক বিভাগ রয়েছে।
বিপাপা

16

যেকোন দৃশ্যের জন্য সেলটি আনতে ইউআইটিএবলভিউতে একটি এক্সটেনশন ব্যবহার করুন:


টেবিল ভিউতে বার্তা প্রেরণকারী ডেলিগেট সম্পত্তি সহ কাস্টম সেল টাইপ সেট আপ করার বিষয়ে পলউ 11 এর উত্তর দেওয়া ভাল উপায়, তবে এটি সেট আপ করার জন্য নির্দিষ্ট পরিমাণের কাজ প্রয়োজন।

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

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

আমি ইউআইটিএবলভিউতে একটি এক্সটেনশন তৈরি করেছি যা আপনাকে টেবিল ভিউ সেলটিতে থাকা কোনও দৃশ্যের জন্য সূচিপথ পেতে দেয়। এটি Optionalএমন কোনও ফেরত দেয় যা শূন্য হয় যদি বাস্তবে পাস করা ভিউটি কোনও টেবিল ভিউ সেলের মধ্যে না পড়ে। এটির সম্পূর্ণরূপে এক্সটেনশন উত্স ফাইলের নীচে। আপনি সহজেই এই ফাইলটি আপনার প্রকল্পে রাখতে পারেন এবং তারপরে indexPathForView(_:)কোনও ভিউ থাকা ইনডেক্সপথটি সন্ধান করার জন্য অন্তর্ভুক্ত পদ্ধতিটি ব্যবহার করতে পারেন ।

//
//  UITableView+indexPathForView.swift
//  TableViewExtension
//
//  Created by Duncan Champney on 12/23/16.
//  Copyright © 2016-2017 Duncan Champney.
//  May be used freely in for any purpose as long as this 
//  copyright notice is included.

import UIKit

public extension UITableView {
  
  /**
  This method returns the indexPath of the cell that contains the specified view
   
   - Parameter view: The view to find.
   
   - Returns: The indexPath of the cell containing the view, or nil if it can't be found
   
  */
  
    func indexPathForView(_ view: UIView) -> IndexPath? {
        let center = view.center
        let viewCenter = self.convert(center, from: view.superview)
        let indexPath = self.indexPathForRow(at: viewCenter)
        return indexPath
    }
}

এটি ব্যবহার করতে, আপনি কেবল কোনও ঘরে থাকা একটি বোতামের জন্য আইবিএક્શનে পদ্ধতিটি কল করতে পারেন:

func buttonTapped(_ button: UIButton) {
  if let indexPath = self.tableView.indexPathForView(button) {
    print("Button tapped at indexPath \(indexPath)")
  }
  else {
    print("Button indexPath not found")
  }
}

(দ্রষ্টব্য যে indexPathForView(_:)কেবলমাত্র সেই অনন্য স্ক্রিনটি এমন কোনও সেল দ্বারা অন্তর্ভুক্ত করা ভিউ অবজেক্টটি কার্যকর হলে ফাংশনটি কাজ করবে That's এটি যুক্তিসঙ্গত, যেহেতু অন স্ক্রিনে নেই এমন দৃশ্যটি কোনও নির্দিষ্ট ইন্ডেক্সপথের অন্তর্ভুক্ত নয়; সম্ভবত এটি সম্ভবত যখন এতে থাকা ঘরটি পুনর্ব্যবহার করা হয় তখন কোনও আলাদা সূচিপথকে বরাদ্দ করুন)

সম্পাদনা:

আপনি এমন একটি ওয়ার্কিং ডেমো প্রকল্প ডাউনলোড করতে পারেন যা গিথুব থেকে উপরের এক্সটেনশনটি ব্যবহার করে: টেবিলভিউএক্সটেনশন.git


ধন্যবাদ আমি কোনও কক্ষের পাঠ্যদর্শনের সূচিপত্রটি পেতে এক্সটেনশনটি ব্যবহার করেছি - নিখুঁতভাবে কাজ করে।
জেরেমি অ্যান্ড্রুজ

9

জন্য Swift2.1

আমি এটি করার একটি উপায় পেয়েছি, আশা করি, এটি সাহায্য করবে।

let point = tableView.convertPoint(CGPoint.zero, fromView: sender)

    guard let indexPath = tableView.indexPathForRowAtPoint(point) else {
        fatalError("can't find point in tableView")
    }

ত্রুটি চললে এর অর্থ কী? এটি টেবিল ভিউতে পয়েন্টটি খুঁজে না পাওয়ার কিছু কারণ কী?
ওওপ্রোগ

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

9

সুইফট 4 সমাধান:

আপনার ঘরে একটি বোতাম (মাই বাটন) বা অন্য কোনও দৃশ্য রয়েছে। সেলফোর্ডে ট্যাগ বরাদ্দ করুনএর মতো

cell.myButton.tag = indexPath.row

এখন আপনি আলতো চাপুন বা অন্য কোনও। এটি এ জাতীয়ভাবে বের করুন এবং স্থানীয় ভেরিয়েবলে সংরক্ষণ করুন।

currentCellNumber = (sender.view?.tag)!

এর পরে আপনি নির্বাচিত বোতামের সূচকপথ পেতে এই বর্তমানসেলনम्बरটি যে কোনও জায়গায় ব্যবহার করতে পারেন।

উপভোগ করুন!


এই পদ্ধতির কাজ করে, কিন্তু দেখুন ট্যাগগুলি ভঙ্গুর, আমার উত্তরে উল্লিখিত হিসাবে। একটি সাধারণ পূর্ণসংখ্যার ট্যাগ কোনও বিভাগযুক্ত টেবিল দর্শনের জন্য কাজ করবে না, উদাহরণস্বরূপ। (একটি সূচিপত্র এটি 2 পূর্ণসংখ্যার।) আমার পদ্ধতির সর্বদা কার্যকর হবে এবং বোতামে কোনও ট্যাগ ইনস্টল করার দরকার নেই (বা অন্যান্য টেপযোগ্য দৃশ্য।)
ডানকান সি

আপনি সহজেই বিভাগ এবং সারি / আইটেমটিকে একটি পূর্ণসংখ্যায় সঞ্চয় করতে পারেন। আমার উত্তর দেখুন ...
mramosch

6

সুইফ্ট 4-এ, কেবল এটি ব্যবহার করুন:

func buttonTapped(_ sender: UIButton) {
        let buttonPostion = sender.convert(sender.bounds.origin, to: tableView)

        if let indexPath = tableView.indexPathForRow(at: buttonPostion) {
            let rowIndex =  indexPath.row
        }
}

সবচেয়ে পরিষ্কার উত্তর, নির্বাচিত করা উচিত। কেবলমাত্র লক্ষণীয় বিষয় হ'ল এটি tableViewএকটি আউটলেট ভেরিয়েবল যা এই উত্তরটি কাজ করার পূর্বে উল্লেখ করা দরকার।
10000 রবিপুল 21

মোহন মত কাজ !!
পার্থপ্যাটেল ১১০৫

4

খুব সরল সূচক পাথ দ্রুত সুইচিং 4, 5

let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! Cell
cell.btn.tag = indexPath.row
cell.btn.addTarget(self, action: "buttonTapped:", forControlEvents: 
UIControlEvents.TouchUpInside)

বিটিএন ইনডেক্সপথ কীভাবে পাবেন তা ক্লিক করুন:

func buttonTapped(_ sender: UIButton) {
     print(sender.tag)  
}

3

যেহেতু ইভেন্ট হ্যান্ডলার প্রেরককে বোতাম নিজেই, আমি বোতাম এর ব্যবহার করতে চাই tagসূচক মধ্যে সক্রিয়া সঞ্চয় করতে সম্পত্তি cellForRowAtIndexPath

তবে আরও কিছু কাজ করে আমি সম্পূর্ণ অন্যভাবে করব। আপনি যদি কোনও কাস্টম সেল ব্যবহার করেন, আমি কীভাবে সমস্যার সাথে যোগাযোগ করব:

  • কাস্টম টেবিল ঘরে একটি 'ইন্ডেক্সপ্যাথ' সম্পত্তি যুক্ত করুন
  • এটি সূচনা cellForRowAtIndexPath
  • টিপ হ্যান্ডলারটি ভিউ কন্ট্রোলার থেকে ঘর বাস্তবায়নে সরান
  • সূচকের পথটি অতিক্রম করে, ট্যাপ ইভেন্ট সম্পর্কিত দর্শন নিয়ামককে অবহিত করার জন্য প্রতিনিধি প্যাটার্নটি ব্যবহার করুন

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

আমি মনে করি এটি এক্স বিভাগ সহ কোনও ঘরটির সূচকপথটি পাওয়ার সেরা উপায়, তবে আমি এমভিসি পদ্ধতির বুলেট পয়েন্টের প্রয়োজন দেখতে পাচ্ছি না
এডওয়ার্ড

2

ডেলিগেট কলব্যাক ব্যবহারের জন্য পলউ 11 এর পরামর্শ দেখার পরে, আমি এটিতে কিছুটা বিস্তারিত / আরও কিছু বলতে চাই, অনুরূপ পরামর্শ। আপনি যদি প্রতিনিধি প্যাটার্নটি ব্যবহার না করতে চান তবে আপনি নিম্নরূপে দ্রুতগতিতে ক্লোজারগুলি ব্যবহার করতে পারেন:

আপনার সেল শ্রেণি:

class Cell: UITableViewCell {
    @IBOutlet var button: UIButton!

    var buttonAction: ((sender: AnyObject) -> Void)?

    @IBAction func buttonPressed(sender: AnyObject) {
        self.buttonAction?(sender)
    }
}

আপনার cellForRowAtIndexPathপদ্ধতি:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! Cell
    cell.buttonAction = { (sender) in
        // Do whatever you want from your button here.
    }
    // OR
    cell.buttonAction = buttonPressed // <- Method on the view controller to handle button presses.
}

2

মডেল ক্লাস ব্যবহার করে টেবিলভিউ এবং সংগ্রহভিউতে যে কোনও ঘর পরিচালনা করার জন্য আমি খুব সহজ উপায়টি খুঁজে পেয়েছি এবং এটি সম্পূর্ণরূপে একটি কাজ।

এখন এটি পরিচালনা করার জন্য আরও অনেক ভাল উপায় আছে। এটি সেল এবং মান পরিচালনার জন্য কাজ করবে।

এখানে আমার আউটপুট (স্ক্রিনশট) তাই এটি দেখুন:

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

  1. মডেল শ্রেণি তৈরি করা এটি খুব সহজ , দয়া করে নীচের পদ্ধতিটি অনুসরণ করুন। নাম সহ সুইফ্ট ক্লাস তৈরি করুন RNCheckedModel, নীচে কোডটি লিখুন।
class RNCheckedModel: NSObject {

    var is_check = false
    var user_name = ""

    }
  1. আপনার সেল ক্লাস তৈরি করুন
class InviteCell: UITableViewCell {

    @IBOutlet var imgProfileImage: UIImageView!
    @IBOutlet var btnCheck: UIButton!
    @IBOutlet var lblName: UILabel!
    @IBOutlet var lblEmail: UILabel!
    }
  1. এবং পরিশেষে আপনার মডেল বর্গ ব্যবহার UIViewController যখন আপনি আপনার ব্যবহার UITableView
    class RNInviteVC: UIViewController, UITableViewDelegate, UITableViewDataSource {


    @IBOutlet var inviteTableView: UITableView!
    @IBOutlet var btnInvite: UIButton!

    var checkArray : NSMutableArray = NSMutableArray()
    var userName : NSMutableArray = NSMutableArray()

    override func viewDidLoad() {
        super.viewDidLoad()
        btnInvite.layer.borderWidth = 1.5
        btnInvite.layer.cornerRadius = btnInvite.frame.height / 2
        btnInvite.layer.borderColor =  hexColor(hex: "#512DA8").cgColor

        var userName1 =["Olivia","Amelia","Emily","Isla","Ava","Lily","Sophia","Ella","Jessica","Mia","Grace","Evie","Sophie","Poppy","Isabella","Charlotte","Freya","Ruby","Daisy","Alice"]


        self.userName.removeAllObjects()
        for items in userName1 {
           print(items)


            let model = RNCheckedModel()
            model.user_name = items
            model.is_check = false
            self.userName.add(model)
        }
      }
     @IBAction func btnInviteClick(_ sender: Any) {

    }
       func tableView(_ tableView: UITableView, numberOfRowsInSection 
       section: Int) -> Int {
        return userName.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: InviteCell = inviteTableView.dequeueReusableCell(withIdentifier: "InviteCell", for: indexPath) as! InviteCell

        let image = UIImage(named: "ic_unchecked")
        cell.imgProfileImage.layer.borderWidth = 1.0
        cell.imgProfileImage.layer.masksToBounds = false
        cell.imgProfileImage.layer.borderColor = UIColor.white.cgColor
        cell.imgProfileImage.layer.cornerRadius =  cell.imgProfileImage.frame.size.width / 2
        cell.imgProfileImage.clipsToBounds = true

        let model = self.userName[indexPath.row] as! RNCheckedModel
        cell.lblName.text = model.user_name

        if (model.is_check) {
            cell.btnCheck.setImage(UIImage(named: "ic_checked"), for: UIControlState.normal)
        }
        else {
            cell.btnCheck.setImage(UIImage(named: "ic_unchecked"), for: UIControlState.normal)
        }

        cell.btnCheck.tag = indexPath.row
        cell.btnCheck.addTarget(self, action: #selector(self.btnCheck(_:)), for: .touchUpInside)

        cell.btnCheck.isUserInteractionEnabled = true

    return cell

    }

    func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
        return 80

    }

    @objc func btnCheck(_ sender: UIButton) {

        let tag = sender.tag
        let indexPath = IndexPath(row: tag, section: 0)
        let cell: InviteCell = inviteTableView.dequeueReusableCell(withIdentifier: "InviteCell", for: indexPath) as! InviteCell

        let model = self.userName[indexPath.row] as! RNCheckedModel

        if (model.is_check) {

            model.is_check = false
            cell.btnCheck.setImage(UIImage(named: "ic_unchecked"), for: UIControlState.normal)

            checkArray.remove(model.user_name)
            if checkArray.count > 0 {
                btnInvite.setTitle("Invite (\(checkArray.count))", for: .normal)
                print(checkArray.count)
                UIView.performWithoutAnimation {
                    self.view.layoutIfNeeded()
                }
            } else {
                btnInvite.setTitle("Invite", for: .normal)
                UIView.performWithoutAnimation {
                    self.view.layoutIfNeeded()
                }
            }

        }else {

            model.is_check = true
            cell.btnCheck.setImage(UIImage(named: "ic_checked"), for: UIControlState.normal)

            checkArray.add(model.user_name)
            if checkArray.count > 0 {
                btnInvite.setTitle("Invite (\(checkArray.count))", for: .normal)
                UIView.performWithoutAnimation {
                self.view.layoutIfNeeded()
                }
            } else {
                 btnInvite.setTitle("Invite", for: .normal)
            }
        }

        self.inviteTableView.reloadData()
    }

    func hexColor(hex:String) -> UIColor {
        var cString:String = hex.trimmingCharacters(in: .whitespacesAndNewlines).uppercased()

        if (cString.hasPrefix("#")) {
            cString.remove(at: cString.startIndex)
        }

        if ((cString.count) != 6) {
            return UIColor.gray
        }

        var rgbValue:UInt32 = 0
        Scanner(string: cString).scanHexInt32(&rgbValue)

        return UIColor(
            red: CGFloat((rgbValue & 0xFF0000) >> 16) / 255.0,
            green: CGFloat((rgbValue & 0x00FF00) >> 8) / 255.0,
            blue: CGFloat(rgbValue & 0x0000FF) / 255.0,
            alpha: CGFloat(1.0)
        )
    }
    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()

    }

     }

1

আমি টেবিল ভিউ থেকে পয়েন্ট পেতে কনভার্টপয়েন্ট পদ্ধতি ব্যবহার করেছি এবং সূচিপথটি পেতে এই পয়েন্টটি সূচকপথফোরআউপয়েন্ট পদ্ধতিতে পাস করেছি

 @IBAction func newsButtonAction(sender: UIButton) {
        let buttonPosition = sender.convertPoint(CGPointZero, toView: self.newsTableView)
        let indexPath = self.newsTableView.indexPathForRowAtPoint(buttonPosition)
        if indexPath != nil {
            if indexPath?.row == 1{
                self.performSegueWithIdentifier("alertViewController", sender: self);
            }   
        }
    }

1

আইবিএশন কল করতে # নির্বাচক ব্যবহার করার চেষ্টা করুন cell সেলফোরোউটিইন্ডেক্সপথে

            cell.editButton.tag = indexPath.row
        cell.editButton.addTarget(self, action: #selector(editButtonPressed), for: .touchUpInside)

আপনি এডিটপথটি পদ্ধতিতে সম্পাদনা বাটনপ্রেসডের ভিতরে সূচকপথটি অ্যাক্সেস করতে পারবেন

func editButtonPressed(_ sender: UIButton) {

print(sender.tag)//this value will be same as indexpath.row

}

সর্বাধিক উপযুক্ত উত্তর
অমলেন্দু কর

না, ট্যাগগুলি বন্ধ থাকবে যখন ব্যবহারকারী কক্ষগুলি যুক্ত বা সরিয়ে ফেলবে।
Koen

@ কোয়েন: আপনি যদি টেবিলটি পুনরায় লোড করেন না তবে -োকানো বা মুছে ফেলার পরে ;-)
মরমোশ

1

আমার ক্ষেত্রে আমার একাধিক বিভাগ রয়েছে এবং বিভাগ এবং সারি সূচক উভয়ই গুরুত্বপূর্ণ, সুতরাং এই জাতীয় ক্ষেত্রে আমি সবেমাত্র ইউআইবুটনে একটি সম্পত্তি তৈরি করেছি যা আমি সেল ইন্ডেক্সপ্যাথটি এভাবে সেট করেছিলাম:

fileprivate struct AssociatedKeys {
    static var index = 0
}

extension UIButton {

    var indexPath: IndexPath? {
        get {
            return objc_getAssociatedObject(self, &AssociatedKeys.index) as? IndexPath
        }
        set {
            objc_setAssociatedObject(self, &AssociatedKeys.index, newValue, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
        }
    }
}

তারপরে বৈশিষ্ট্যটি সেলফোরআউটিতে সেট করুন:

func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("Cell") as! Cell
    cell.button.indexPath = indexPath
}

তারপরে হ্যান্ডেলট্যাপএक्शनটিতে আপনি সূচকপথটি এই জাতীয়ভাবে পেতে পারেন:

@objc func handleTapAction(_ sender: UIButton) {
    self.selectedIndex = sender.indexPath

}

1

সুইফট 4 এবং 5

প্রোটোকল প্রতিনিধি ব্যবহার করে পদ্ধতি 1

উদাহরণস্বরূপ, আপনার UITableViewCellনামের সাথে একটি রয়েছেMyCell

class MyCell: UITableViewCell {
    
    var delegate:MyCellDelegate!
    
    @IBAction private func myAction(_ sender: UIButton){
        delegate.didPressButton(cell: self)
    }
}

এখন একটি তৈরি করুন protocol

protocol MyCellDelegate {
    func didPressButton(cell: UITableViewCell)
}

পরবর্তী পদক্ষেপ, এর একটি এক্সটেনশন তৈরি করুন UITableView

extension UITableView {
    func returnIndexPath(cell: UITableViewCell) -> IndexPath?{
        guard let indexPath = self.indexPath(for: cell) else {
            return nil
        }
        return indexPath
    }
}

আপনার UIViewControllerপ্রোটোকলটি প্রয়োগ করুনMyCellDelegate

class ViewController: UIViewController, MyCellDelegate {
     
    func didPressButton(cell: UITableViewCell) {
        if let indexpath = self.myTableView.returnIndexPath(cell: cell) {
              print(indexpath)
        }
    }
}

ক্লোজার ব্যবহার করে পদ্ধতি 2

ভিতরে UIViewController

override func viewDidLoad() {
        super.viewDidLoad()
       //using the same `UITableView extension` get the IndexPath here
        didPressButton = { cell in
            if let indexpath = self.myTableView.returnIndexPath(cell: cell) {
                  print(indexpath)
            }
        }
    }
 var didPressButton: ((UITableViewCell) -> Void)

class MyCell: UITableViewCell {

    @IBAction private func myAction(_ sender: UIButton){
        didPressButton(self)
    }
}

দ্রষ্টব্য: - আপনি যদি UICollectionViewসূচিপথ পেতে চান তবে এটি ব্যবহার করতে UICollectionView extensionএবং উপরের পদক্ষেপগুলি পুনরাবৃত্তি করতে পারেন

extension UICollectionView {
    func returnIndexPath(cell: UICollectionViewCell) -> IndexPath?{
        guard let indexPath = self.indexPath(for: cell) else {
            return nil
        }
        return indexPath
    }
}

0

সুইফটে ৩. ব্রেসগুলির একটি দীর্ঘ শৃঙ্খলা এড়িয়ে গার্ড স্টেটমেন্টগুলিও ব্যবহৃত হয়েছিল।

func buttonTapped(sender: UIButton) {
    guard let cellInAction = sender.superview as? UITableViewCell else { return }
    guard let indexPath = tableView?.indexPath(for: cellInAction) else { return }

    print(indexPath)
}

এটি কাজ করবে না। বোতামটির তত্ত্বাবধান সেল হবে না।
rmaddy

এটি কাজ করে। আপনার কেবলমাত্র যত্ন সহকারে হওয়া উচিত হ'ল প্রত্যেকের দৃষ্টিভঙ্গি স্ট্যাকটি আলাদা। এটি প্রেরক.সুপারভিউ, প্রেরক.সুপারভিউ.সুপারভিউ বা প্রেরক.সুপারভিউ.সুপারভিউ.সুপারভিউ হতে পারে। তবে এটি সত্যই ভাল কাজ করে।
শন

0

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

সেক্ষেত্রে আমাদের সেল অবজেক্ট না পাওয়া পর্যন্ত আমাদের সুপারভিউ সন্ধান করা উচিত।

সুপারভিউ দ্বারা সেল অবজেক্ট পাওয়ার ফাংশন

func getCellForView(view:UIView) -> UITableViewCell?
{
    var superView = view.superview

    while superView != nil
    {
        if superView is UITableViewCell
        {
            return superView as? UITableViewCell
        }
        else
        {
            superView = superView?.superview
        }
    }

    return nil
}

এখন আমরা নীচের মত বাটন টেপে সূচিপত্র পেতে পারি

@IBAction func tapButton(_ sender: UIButton)
{
    let cell = getCellForView(view: sender)
    let indexPath = myTabelView.indexPath(for: cell)
}

0
// CustomCell.swift

protocol CustomCellDelegate {
    func tapDeleteButton(at cell: CustomCell)
}

class CustomCell: UICollectionViewCell {
    
    var delegate: CustomCellDelegate?
    
    fileprivate let deleteButton: UIButton = {
        let button = UIButton(frame: .zero)
        button.setImage(UIImage(named: "delete"), for: .normal)
        button.addTarget(self, action: #selector(deleteButtonTapped(_:)), for: .touchUpInside)
        button.translatesAutoresizingMaskIntoConstraints = false
        return button
    }()
    
    @objc fileprivate func deleteButtonTapped(_sender: UIButton) {
        delegate?.tapDeleteButton(at: self)
    }
    
}

//  ViewController.swift

extension ViewController: UICollectionViewDataSource {

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: customCellIdentifier, for: indexPath) as? CustomCell else {
            fatalError("Unexpected cell instead of CustomCell")
        }
        cell.delegate = self
        return cell
    }

}

extension ViewController: CustomCellDelegate {

    func tapDeleteButton(at cell: CustomCell) {
        // Here we get the indexPath of the cell what we tapped on.
        let indexPath = collectionView.indexPath(for: cell)
    }

}

0

সারি এবং বিভাগগুলির জন্য একটি একক ট্যাগ ব্যবহার করা

সারি / আইটেম এবং একই সময়ে একটি টেবিলভিউ / সংগ্রহভিউয়ের বিভাগটি প্রেরণের জন্য ট্যাগগুলি ব্যবহার করার একটি সহজ উপায় রয়েছে।

এনকোড IndexPath আপনার UIView.tag জন্য cellForRowAtIndexPath :

buttonForCell.tag = convertIndexPathToTag(with: indexPath)

আপনার টার্গেট সিলেক্টারে আপনার প্রেরকের কাছ থেকে সূচিপথটি ডিকোড করুন:

    @IBAction func touchUpInsideButton(sender: UIButton, forEvent event: UIEvent) {

        var indexPathForButton = convertTagToIndexPath(from: sender)

    }

এনকোডার এবং ডিকোডার:

func convertIndexPathToTag(indexPath: IndexPath) -> Int {
    var tag: Int = indexPath.row + (1_000_000 * indexPath.section)
    
    return tag
}

func convertTagToIndexPath(from sender: UIButton) -> IndexPath {
    var section: Int = Int((Float(sender.tag) / 1_000_000).rounded(.down))
    var row: Int = sender.tag - (1_000_000 * section)

    return IndexPath(row: row, section: section)
}

প্রদত্ত যে আপনি একটি 32 বিট ডিভাইসে 4294967296 সারি / আইটেমের বেশি প্রয়োজন নেই ;-) যেমন

  • 100_000 আইটেম / সারি সহ 42949 বিভাগ
  • 1_000_000 আইটেম / সারি সহ 4294 বিভাগ - ( উপরের উদাহরণের মতো) )
  • 10_000_000 আইটেম / সারি সহ 429 বিভাগ

—-

সতর্কতা: মনে রাখবেন যে আপনার টেবিলভিউ / সংগ্রহভিউতে সারি / আইটেমগুলি মুছতে বা সন্নিবেশ করার সময় আপনার সারণি / আইটেমগুলি আপনার সন্নিবেশ / মোছার পয়েন্টের পরে পুনরায় লোড করতে হবে যাতে আপনার বোতামগুলির ট্যাগ নম্বরগুলি আপনার মডেলের সাথে সিঙ্ক করে রাখে।

—-

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