Передача переменной из функции распознавания жестов в IBAction

#swift #uicollectionview #uigesturerecognizer #return-type #ibaction

#swift #uicollectionview #uigesturerecognizer #возвращаемый тип #ibaction

Вопрос:

У меня есть простое приложение с CollectionView элементами и в нем. При длительном нажатии a cell появляется всплывающее UIView окно с a TextField и возможностью сохранить его в array соответствующем cell .

Вот код ( buttons и gestures были добавлены правильно в viewDidLoad() метод):

 class CollectionViewController: UIViewController, UICollectionViewDataSource, UICollectionViewDelegate  {
var longPressedPoint: CGPoint?

public var rowOfLongPressedItem: Int? = nil

func handleLongPress(longPressRecognizer: UILongPressGestureRecognizer)  -> Int      {
    print("LONG PRESS Gesture Recognized")
    notePopup.hidden = false
    longPressedPoint =  longPressRecognizer.locationInView(longPressRecognizer.view)
    var indexPathOfLongPressedCell = self.itemCollectionView.indexPathForItemAtPoint(longPressedPoint!)
    rowOfLongPressedItem = (indexPathOfLongPressedCell?.row)
    print("rowOfLongPressedItem -> .(rowOfLongPressedItem)")
    return rowOfLongPressedItem!
}

func saveNoteButtonTapped(rowOfLongPressedItem: Int) {
    print("rowOfLongPressedItem when Save button is tapped -> .(rowOfLongPressedItem)")       

    //Can’t go further down as rowOfLongPressedItem is NOT available from “handleLongPress” function…

    var selectedItem = ItemsList[rowOfLongPressedItem]
    selectedItem.counts  = 1
    var latest = selectedItem.counts - 1
    selectedItem.timestamp.append(NSDate())
    selectedItem.note.append(noteTextField.text)
    ItemsList[rowOfLongPressedItem] = selectedItem
    print(".(selectedItem.title) has been tapped .(selectedItem.counts)")
    print("The latest tap on .(selectedItem.title) is at .(selectedItem.timestamp[latest])")
    print("The note .(noteTextField.text) has been added")
    notePopup.hidden = true
}
}
  

Попытался решить проблему несколькими способами:

  • Определение переменной в контроллере представления в надежде, что функция вернет значение и сохранит его в глобальной переменной. Но позже Apple обнаружила, что «Функция не может иметь более высокий уровень доступа, чем ее типы параметров и возвращаемый тип, поскольку функция может использоваться в ситуациях, когда ее составляющие типы недоступны для окружающего кода». https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/AccessControl.html

  • Я попытался поместить код функции выбора кнопки в функцию длинного нажатия жеста, чтобы его возвращаемое значение было легко доступно. Но я не могу вызвать функцию выбора, поскольку она находится внутри другой функции.

  • Кроме того, я попытался вернуть значение функции длинного нажатия жеста и использовать его в IBAction кнопки сохранения. Однако для этого мне нужно handleLongPress снова вызвать, а затем longPressedPoint распознать как внутри кнопки сохранения. Следовательно, indexPathOfLongPressedCell происходит сбой is nil и приложения.

Может кто-нибудь, пожалуйста, помочь мне…

Ответ №1:

Предполагая, что вы хотите получить строку выбранной ячейки и присваиваете ее глобальной переменной rowOfLongPressedItem , вам не нужно разрешать handleLongPress возвращает значение Int .

ПРИМЕЧАНИЕ: это код Swift 3 (с той же концепцией):

 public var rowOfLongPressedItem: Int? = nil

override func viewDidLoad() {
    //...

    let longPressRecognizer = UILongPressGestureRecognizer(target: self, action: #selector(ViewController.assignRowOfLongPressedItem))

    itemCollectionView.addGestureRecognizer(longPressRecognizer)

    //...
}

func assignRowOfLongPressedItem(longPressRecognizer: UILongPressGestureRecognizer) {
    let longPressedPoint = longPressRecognizer.location(in: longPressRecognizer.view)
    var indexPathOfLongPressedCell = self.itemCollectionView.indexPathForItem(at: longPressedPoint)
    rowOfLongPressedItem = (indexPathOfLongPressedCell?.row)
    // if you long press the first row -for example-, the output should be: "rowOfLongPressedItem -> .Optional(0)"
    print("rowOfLongPressedItem -> .(rowOfLongPressedItem)")
}
  

Кроме того, вам не нужно разрешать saveNoteButtonTapped принимать rowOfLongPressedItem параметр. Обратите внимание, что rowOfLongPressedItem это необязательно, вы должны убедиться, что оно по-прежнему не равно нулю (вы можете использовать подход раннего выхода):

 func saveNoteButtonTapped(sender: UIButton) {
        guard let selectedCellRow = rowOfLongPressedItem else {
            print("rowOfLongPressedItem is nil!!")
            return
        }

        print("rowOfLongPressedItem when Save button is tapped -> .(selectedCellRow)")
        var selectedItem = ItemsList[selectedCellRow]

        selectedItem.counts  = 1
        var latest = selectedItem.counts - 1
        selectedItem.timestamp.append(NSDate())
        selectedItem.note.append(noteTextField.text)
        ItemsList[row] = selectedItem
        print(".(selectedItem.title) has been tapped .(selectedItem.counts)")
        print("The latest tap on .(selectedItem.title) is at .(selectedItem.timestamp[latest])")
        print("The note .(noteTextField.text) has been added")
        notePopup.hidden = true
}
  

Комментарии:

1. Это даже лучше. Это работает как шарм. Большое спасибо!

2. Спасибо, что предупредили меня, чтобы убедиться, что rowOfLongPressedItem это не nil так.

3. Хотя этот код работает, я пытаюсь понять, почему он работает. На основе «Функция не может иметь более высокий уровень доступа, чем ее типы параметров и возвращаемый тип, поскольку функция может использоваться в ситуациях, когда ее составляющие типы недоступны для окружающего кода». developer.apple.com/library/content/documentation/Swift /… этот код не должен работать, не так ли? Как assignRowOfLongPressedItem сохранить rowOfLongPressedItem , которая является глобальной переменной?

4. @Ahmad Кажется, вы пропустили это -> ItemsList[row] = selectedItem 😉

Ответ №2:

rowOfLongPressedItem доступно для обеих функций. Вам не нужно делать это параметром saveNoteButtonTapped .

 var rowOfLongPressedItem: Int? = nil

func handleLongPress(longPressRecognizer: UILongPressGestureRecognizer)  -> Int      {
    print("LONG PRESS Gesture Recognized")
    notePopup.hidden = false
    longPressedPoint =  longPressRecognizer.locationInView(longPressRecognizer.view)
    var indexPathOfLongPressedCell = self.itemCollectionView.indexPathForItemAtPoint(longPressedPoint!)
    rowOfLongPressedItem = (indexPathOfLongPressedCell?.row)
    print("rowOfLongPressedItem -> .(rowOfLongPressedItem)")
    return rowOfLongPressedItem!
}

func saveNoteButtonTapped() {

    guard let row = rowOfLongPressedItem else {
        return // rowOfLongPressedItem was nil
    }

    print("rowOfLongPressedItem when Save button is tapped -> .(row)")
    var selectedItem = ItemsList[row]

    selectedItem.counts  = 1
    var latest = selectedItem.counts - 1
    selectedItem.timestamp.append(NSDate())
    selectedItem.note.append(noteTextField.text)
    ItemsList[row] = selectedItem
    print(".(selectedItem.title) has been tapped .(selectedItem.counts)")
    print("The latest tap on .(selectedItem.title) is at .(selectedItem.timestamp[latest])")
    print("The note .(noteTextField.text) has been added")
    notePopup.hidden = true
}
  

Комментарии:

1. Спасибо за ваш ответ. Я не уверен, что rowOfLongPressedItem . Вот результат для моего существующего кода rowOfLongPressedItem -> .Optional(2) rowOfLongPressedItem when Save button is tapped -> .140667464596544 fatal error: Array index out of range (lldb) Также, я попытался добавить инструкцию guard, но получил эту ошибку » Initializer for conditional binding must have Optional type, not 'Int' Пожалуйста, помогите

2. Пожалуйста, проигнорируйте мой предыдущий комментарий. Однако я не удалял параметр в saveNoteButtonTapped() функции, одно небольшое изменение здесь: func saveNoteButtonTapped(sender: UIButton) Я внес это изменение и пометил ваш ответ как ответ. Большое спасибо за вашу помощь.

3. @EcoApps Добро пожаловать 🙂 Зачем вам нужен параметр sender? вы не используете ее нигде в функции

4. @EcoApps Это функция IBAction?

5. Нет, это функция выбора UIButton