#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
происходит сбой isnil
и приложения.
Может кто-нибудь, пожалуйста, помочь мне…
Ответ №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