Uncaught Exception "NSRangeException" - PullRequest
       14

Uncaught Exception "NSRangeException"

0 голосов
/ 30 октября 2019

Я использовал WSTagsField Cocoapods, чтобы показать поле тегов на ViewController. Между прочим, если я отклоняю это viewcontroller, это показывает ошибку необнаруженного исключения. Это показывает причину, подобную этой.

[general] Caught exception during runloop's autorelease pool drain of client objects NSRangeException: Cannot remove an observer
<_NSKeyValueObservation 0x283af4ab0> for the key path "layer.bounds"
from <WSTagsField.WSTagsField 0x10484b400> because it is not
registered as an observer. userInfo: (null)

Terminating app due to uncaught exception 'NSRangeException', reason: 'Cannot remove an observer <_NSKeyValueObservation
0x283af4ab0> for the key path "layer.bounds" from
<WSTagsField.WSTagsField 0x10484b400> because it is not registered as
an observer.'

Поэтому я попытался добавить наблюдателя для WSTagsField, но я все еще не понимаю, как добавить наблюдателя ...

import UIKit
import WSTagsField
import IQKeyboardManagerSwift
import SelectionList
import Popover

class EditTagViewController: EditBaseViewController {
@IBOutlet weak var topTagContainer: UIStackView!
@IBOutlet weak var bottomTagContainer: UIStackView!

var sourceTag: WSTagsField!
var friendTag: WSTagsField!
var subjectTag: WSTagsField!
var categoryTag: WSTagsField!
var keywordTag: WSTagsField!

var keyboardHeight: CGFloat = 260
var originalFrame: CGRect = CGRect.zero

var selectionList: SelectionList = SelectionList(frame: .zero)

private var categories: [String] = Constant.categories
private var subjects: [String] = Constant.subjects

var selectedTag: WSTagsField!

override func viewDidLoad() {
super.viewDidLoad()
}

override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
IQKeyboardManager.shared.enable = false
originalFrame = self.view.frame
}

override func viewWillDisappear(_ animated: Bool) {
super.viewWillDisappear(animated)
IQKeyboardManager.shared.enable = true
NotificationCenter.default.removeObserver(self)
}

override func configureUI() {
super.configureUI()
sourceTag = tagView(with: "Source", color: #colorLiteral(red: 1, green: 0.7327780128, blue: 0.8007825017, alpha: 1))
friendTag = tagView(with: "Friend", color: #colorLiteral(red: 0.8057851195, green: 0.8834529519, blue: 0.9376013875, alpha: 1))

topTagContainer.addChild(view: sourceTag)
topTagContainer.addChild(view: friendTag)

subjectTag = tagView(with: "Subject", color: #colorLiteral(red: 0.4356668293, green: 0.8868191838, blue: 0.5134474635, alpha: 1))
categoryTag = tagView(with: "Category", color: #colorLiteral(red: 0.9838475585, green: 0.7406000495, blue: 1, alpha: 1))

keywordTag = tagView(with: "Keyword", color: #colorLiteral(red: 0.501960814, green: 0.501960814, blue: 0.501960814, alpha: 0.6020301496))
keywordTag.onDidChangeText = { [weak self] tagField, text in
self?.updateViewPosition(field: tagField)
}
keywordTag.textDelegate = self
keywordTag.numberOfLines = 3

bottomTagContainer.addChild(view: subjectTag)
bottomTagContainer.addChild(view: categoryTag)
bottomTagContainer.addChild(view: keywordTag)

NotificationCenter.default.addObserver(
self,
selector: #selector(keyboardWillShow),
name: UIResponder.keyboardWillShowNotification,
object: nil
)

NotificationCenter.default.addObserver(
self,
selector: #selector(keyboardWillHide),
name: UIResponder.keyboardWillHideNotification,
object: nil
)

let btnSubject = UIButton(action: #selector(onSubjectTapped(_:)), target: self)
self.view.addSubview(btnSubject)
btnSubject.snp.makeConstraints {
$0.edges.equalTo(subjectTag)
}

let btnCategory = UIButton(action: #selector(onCategoryTapped(_:)), target: self)
self.view.addSubview(btnCategory)
btnCategory.snp.makeConstraints {
$0.edges.equalTo(categoryTag)
}

selectionList.selectionImage = UIImage(named: "btn_circle_checked")
selectionList.deselectionImage = UIImage(named: "btn_circle_unchecked")
selectionList.rowHeight = 40
selectionList.tableView.separatorStyle = .none
selectionList.addTarget(self, action: #selector(selectionChanged), for: .valueChanged)
}

override func checkShareOptionEnabled() -> Bool {
guard let shareOption = self.note?.shareOption, super.checkShareOptionEnabled() == true else {
return false
}
return shareOption.tagEnabled
}

override func viewDidLayoutSubviews() {
super.viewDidLayoutSubviews()
selectionList.frame = CGRect(x: 0, y: 0, width: self.view.bounds.width - 32, height: 240)
}

private func tagView(with placeholder: String?, color: UIColor = #colorLiteral(red: 0.2549019754, green: 0.2745098174, blue: 0.3019607961, alpha: 1)) -> WSTagsField {
let tagsField = WSTagsField()
tagsField.layoutMargins = UIEdgeInsets(top: 2, left: 6, bottom: 2, right: 6)
tagsField.layer.cornerRadius = 6
tagsField.contentInset = UIEdgeInsets(top: 10, left: 10, bottom: 10, right: 10)
tagsField.spaceBetweenLines = 5.0
tagsField.spaceBetweenTags = 10.0
tagsField.font = .systemFont(ofSize: 14.0)
tagsField.backgroundColor = #colorLiteral(red: 0.9656763673, green: 0.965699017, blue: 0.9656868577, alpha: 1)
tagsField.tintColor = color
tagsField.textColor = #colorLiteral(red: 0.2549019754, green: 0.2745098174, blue: 0.3019607961, alpha: 1)
tagsField.fieldTextColor = #colorLiteral(red: 0.6000000238, green: 0.6000000238, blue: 0.6000000238, alpha: 1)
tagsField.selectedColor = #colorLiteral(red: 0.2392156869, green: 0.6745098233, blue: 0.9686274529, alpha: 1)
tagsField.selectedTextColor = #colorLiteral(red: 1.0, green: 1.0, blue: 1.0, alpha: 1.0)
tagsField.delimiter = ","
tagsField.isDelimiterVisible = false
tagsField.placeholder = placeholder ?? ""
tagsField.placeholderColor = #colorLiteral(red: 0.501960814, green: 0.501960814, blue: 0.501960814, alpha: 1)
tagsField.placeholderAlwaysVisible = true
tagsField.returnKeyType = .next
tagsField.acceptTagOption = .space
return tagsField
}

override func updateContent(with item: NoteItem) {
super.updateContent(with: item)

guard let value = item as? Tag else {
return
}

sourceTag.addTags(Array(value.source))
friendTag.addTags(Array(value.friend))
subjectTag.addTags(Array(value.subject))
categoryTag.addTags(Array(value.category))
keywordTag.addTags(Array(value.keyword))
}

func updateViewPosition(field: UIView) {
let rect = field.convert(field.bounds, to: self.view)

let distance = self.view.bounds.height - rect.maxY
if distance < keyboardHeight {
self.view.frame = CGRect(x: 0, y: distance - keyboardHeight + 40, width: self.view.bounds.width, height: self.view.bounds.height)
}
else {
self.view.frame = originalFrame
}
}

@objc func keyboardWillShow(_ notification: Notification) {
if let keyboardFrame: NSValue = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue {
let keyboardRectangle = keyboardFrame.cgRectValue
keyboardHeight = keyboardRectangle.height
}
}

@objc func keyboardWillHide(_ notification: Notification) {
self.view.frame = originalFrame
}
}

extension EditTagViewController {
@objc
func onSubjectTapped(_ sender: UIButton) {
IQKeyboardManager.shared.resignFirstResponder()

self.selectedTag = subjectTag
self.updateViewPosition(field: subjectTag)

let selectedOptions = (self.noteItem as? Tag)?.subject ?? []
showOption(for: subjects, selectedOptions: selectedOptions, sender: sender)
}

@objc
func onCategoryTapped(_ sender: UIButton) {
IQKeyboardManager.shared.resignFirstResponder()

self.selectedTag = categoryTag
self.updateViewPosition(field: categoryTag)

let selectedOptions = (self.noteItem as? Tag)?.category ?? []
showOption(for: categories, selectedOptions: selectedOptions, sender: sender)
}

@objc
func selectionChanged() {
if selectedTag == subjectTag {
subjectTag.removeTags()
subjectTag.addTags(selectionList.selectedIndexes.compactMap {subjects[$0]})
}
else {
categoryTag.removeTags()
categoryTag.addTags(selectionList.selectedIndexes.compactMap {categories[$0]})
}
}

func showOption(for options: [String], selectedOptions: [String], multiSelect: Bool = true, sender: UIButton) {
selectionList.items = options
selectionList.allowsMultipleSelection = multiSelect
selectionList.selectedIndexes = selectedOptions.compactMap {
options.firstIndex(of: $0)
}

var rect = selectionList.frame
rect.size.height = CGFloat(40 * min(selectionList.items.count, 6))
selectionList.frame = rect

let options = [
.type(.down),
.cornerRadius(6),
.animationIn(0.3),
.blackOverlayColor(#colorLiteral(red: 0, green: 0, blue: 0, alpha: 0.3)),
.dismissOnBlackOverlayTap(true)
] as [PopoverOption]
let popover = Popover(options: options, showHandler: nil, dismissHandler: nil)
popover.show(selectionList, fromView: sender)
popover.willDismissHandler = { [weak self] in
guard let weak_self = self else {
return
}
weak_self.view.frame = weak_self.originalFrame
}
}
}

Я хочу, чтобы он отклонил текущий viewcontroller без каких-либо сообщений об ошибках, связанных с наблюдателем. Теперь консоль XCode сообщает, что причина ошибки необработанного исключения состоит в том, что она не зарегистрирована в качестве наблюдателя.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...