问题描述
使用iOS14.0.1,Swift5.3,Xcode12.0.1,
Using iOS14.0.1, Swift5.3, Xcode12.0.1,
我对这个问题感到绝望:
I am desperate with this problem:
在iOS12和iOS13上,我的应用程序运行良好.
With iOS12 and iOS13, my App was working nicely.
但是现在有了iOS14,没有UIButton,没有UISwitch,没有segue -在我的Modal ViewController中什么也没起作用.
But now with iOS14, no UIButton, no UISwitch, no segue - nothing is working in my Modal ViewController.
我不知道苹果在UIKit中做了什么更改才能发生此问题? !!!!
I have no idea what Apple changed in UIKit for this problem to occur ???? !!!!
请帮助!
我的Modal ViewController如下所示:
My Modal ViewController is presented as follows:
@objc func settingsBtnPressed(_ sender: UIButton) {
let settingsVC = SettingsViewController()
settingsVC.backDelegate = self
let navController = UINavigationController(rootViewController: settingsVC)
navController.navigationBar.barStyle = .black
navController.navigationBar.tintColor = .white
navController.navigationBar.prefersLargeTitles = true
navController.navigationBar.backgroundColor = UIColor.clear
navController.presentationController?.delegate = self
self.present(navController, animated: true)
}
class SettingsViewController: UICollectionViewController, UICollectionViewDelegateFlowLayout {
let cellId = "cellID"
init() {
let collectionViewFlowLayout = UICollectionViewFlowLayout()
collectionViewFlowLayout.estimatedItemSize = CGSize(width: UIScreen.main.bounds.width, height: 1)
super.init(collectionViewLayout: collectionViewFlowLayout)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
super.viewDidLoad()
// ...
collectionView.register(SettingsCollectionViewCell.self, forCellWithReuseIdentifier: cellId)
}
override func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return 1
}
override func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! SettingsCollectionViewCell
cell.setup(titlesFirstSection: titlesFirstSection, iconsFirstSection: iconsFirstSection, onStatesFirstSection: onStatesFirstSection, )
return cell
}
}
class SettingsCollectionViewCell: UICollectionViewCell {
var SettingsStackView = UIStackView()
var attries: UICollectionViewLayoutAttributes!
var myContentHeight: CGFloat = 0.0
var firstSettingsSectionView: MenuSwitchListSectionView?
let elementHeight: CGFloat = 44.0
let separatorLineThickness: CGFloat = 1.0
let sectionViewBackgroundColor = ImageConverter.UIColorFromRGB(0x2C2C2E, alpha: 1.0)
override init(frame: CGRect) {
super.init(frame: frame)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func setup(titlesFirstSection: [String],
iconsFirstSection: [UIImage?]?,
onStatesFirstSection: [Bool]) {
myContentHeight = UIScreen.main.bounds.height - 120
initFirstSettingsSectionView(titles: titlesFirstSection, icons: iconsFirstSection, onStates: onStatesFirstSection)
SettingsStackView = VerticalStackView(arrangedSubviews: [
UIView(),
firstSettingsSectionView! as UIView,
UIView()
], spacing: 10.0, alignment: .center )
contentView.addSubview(SettingsStackView)
contentView.isUserInteractionEnabled = true
setConstraints(nrOfItemsFirstSection: titlesFirstSection.count)
}
fileprivate func initFirstSettingsSectionView(titles: [String], icons: [UIImage?]?, onStates: [Bool]) {
firstSettingsSectionView = MenuSwitchListSectionView(frame: .zero,
elementHeight: elementHeight,
separatorLineThickness: separatorLineThickness,
backgroundColor: sectionViewBackgroundColor,
titles: titles,
icons: icons,
onStates: onStates
)
firstSettingsSectionView?.switchMutatedDelegate = self
firstSettingsSectionView?.assignDelegate()
}
fileprivate func setConstraints(nrOfItemsFirstSection: Int) {
contentView.translatesAutoresizingMaskIntoConstraints = false
SettingsStackView.translatesAutoresizingMaskIntoConstraints = false
firstSettingsSectionView?.translatesAutoresizingMaskIntoConstraints = false
SettingsStackView.anchor(top: safeAreaLayoutGuide.topAnchor, leading: contentView.leadingAnchor, bottom: nil, trailing: contentView.trailingAnchor)
let totalHeightFirstSection: CGFloat = elementHeight * CGFloat(nrOfItemsFirstSection) + separatorLineThickness * CGFloat(nrOfItemsFirstSection - 1)
firstSettingsSectionView?.leadingAnchor.constraint(equalTo: contentView.leadingAnchor, constant: 8.0).isActive = true
firstSettingsSectionView?.heightAnchor.constraint(equalToConstant: totalHeightFirstSection).isActive = true
firstSettingsSectionView?.widthAnchor.constraint(equalToConstant: contentView.bounds.width - 16.0).isActive = true
}
class MenuSwitchElementStackView: UIStackView {
weak var switchMutatedDelegate: SwitchMutatedDelegate?
let imgViewWidth: CGFloat = 23.0
override init(frame: CGRect) {
super.init(frame: frame)
}
convenience init(frame: CGRect, text: String, icon: UIImage?, onState: Bool, switchID: Int) {
self.init(frame: frame)
composeStackView(text: text, icon: icon, onState: onState, switchID: switchID)
}
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
fileprivate func composeStackView(text: String, icon: UIImage?, onState: Bool, switchID: Int) {
// StackView properties
axis = .horizontal
alignment = .center
spacing = 23.0
var iconImgView: UIImageView?
// create Icon
if let icon = icon {
iconImgView = UIImageView()
iconImgView?.image = icon
iconImgView?.contentMode = .scaleAspectFit
}
// create Title
let titleLabel = UILabel()
titleLabel.font = AppConstants.Font.ListSectionElementTitleFont
titleLabel.text = text
titleLabel.textColor = .white
titleLabel.tintColor = .white
titleLabel.heightAnchor.constraint(equalToConstant: 19.0).isActive = true
// create choice TextLbl
let mySwitch = UISwitch()
mySwitch.tag = switchID
mySwitch.setOn(onState, animated: false)
mySwitch.addTarget(self, action: #selector(MenuSwitchElementStackView.switchChanged(_:)), for: UIControl.Event.valueChanged)
// text stackView creation
if let iconImgView = iconImgView {
addArrangedSubview(iconImgView)
}
addArrangedSubview(titleLabel)
addArrangedSubview(mySwitch)
// set Constraints
setConstraints(iconImgView, titleLabel, mySwitch)
}
@objc func switchChanged(_ mySwitch: UISwitch) {
switchMutatedDelegate?.switchChanged(isOn: mySwitch.isOn, switchID: mySwitch.tag)
}
fileprivate func setConstraints(_ iconImgView: UIImageView?, _ titleLabel: UILabel, _ mySwitch: UISwitch) {
translatesAutoresizingMaskIntoConstraints = false
iconImgView?.translatesAutoresizingMaskIntoConstraints = false
titleLabel.translatesAutoresizingMaskIntoConstraints = false
mySwitch.translatesAutoresizingMaskIntoConstraints = false
iconImgView?.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 0.0).isActive = true
iconImgView?.widthAnchor.constraint(equalToConstant: 24.0).isActive = true
iconImgView?.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
titleLabel.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
mySwitch.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
mySwitch.leadingAnchor.constraint(equalTo: trailingAnchor, constant: -64.0).isActive = true
}
}
class MenuSwitchListSectionView: UIView {
var sectionElementsStackView: MenuSwitchListSectionWithElementsStackView?
weak var switchMutatedDelegate: SwitchMutatedDelegate?
override init(frame: CGRect) {
super.init(frame: frame)
}
convenience init(frame: CGRect,
elementHeight: CGFloat,
separatorLineThickness: CGFloat,
backgroundColor: UIColor,
titles: [String],
icons: [UIImage?]?,
onStates: [Bool]) {
self.init(frame: frame)
composeView(elementHeight: elementHeight, separatorLineThickness: separatorLineThickness, backgroundColor: backgroundColor, titles: titles, icons: icons, onStates: onStates)
}
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func assignDelegate() {
self.sectionElementsStackView?.switchMutatedDelegate = switchMutatedDelegate
sectionElementsStackView?.assignDelegate()
}
fileprivate func composeView(elementHeight: CGFloat, separatorLineThickness: CGFloat, backgroundColor: UIColor, titles: [String], icons: [UIImage?]?, onStates: [Bool]) {
// create background View
let totalHeight: CGFloat = elementHeight * CGFloat(titles.count) + separatorLineThickness * CGFloat(titles.count - 1)
let backGroundView = ListSectionBackgroundView(frame: .zero, height: totalHeight, backgroundColor: backgroundColor)
// create stackView
sectionElementsStackView = MenuSwitchListSectionWithElementsStackView(frame: CGRect(x: 0.0, y: 0.0, width: UIScreen.main.bounds.width, height: totalHeight), elementHeight: elementHeight, separatorLineThickness: separatorLineThickness, titles: titles, icons: icons, onStates: onStates)
// add background and stackView to self
addSubview(backGroundView)
addSubview(sectionElementsStackView!)
// set Constraints
translatesAutoresizingMaskIntoConstraints = false
backGroundView.translatesAutoresizingMaskIntoConstraints = false
sectionElementsStackView?.translatesAutoresizingMaskIntoConstraints = false
backGroundView.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
backGroundView.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
backGroundView.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
backGroundView.heightAnchor.constraint(equalToConstant: totalHeight).isActive = true
sectionElementsStackView?.centerYAnchor.constraint(equalTo: centerYAnchor).isActive = true
sectionElementsStackView?.leadingAnchor.constraint(equalTo: leadingAnchor, constant: 16.0).isActive = true
sectionElementsStackView?.trailingAnchor.constraint(equalTo: trailingAnchor, constant: -10.0).isActive = true
}
}
class MenuSwitchListSectionWithElementsStackView: UIStackView {
weak var switchMutatedDelegate: SwitchMutatedDelegate?
var elementStackView: MenuSwitchElementStackView?
var elements: [MenuSwitchElementStackView]?
var titles: [String]? // needed for gesture callback
override init(frame: CGRect) {
super.init(frame: frame)
}
convenience init(frame: CGRect,
elementHeight: CGFloat,
separatorLineThickness: CGFloat,
titles: [String],
icons: [UIImage?]?,
onStates: [Bool]) {
self.init(frame: frame)
self.titles = titles // needed for gesture callback
composeStackView(elementHeight: elementHeight, separatorLineThickness: separatorLineThickness, titles: titles, icons: icons, onStates: onStates)
}
required init(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
func assignDelegate() {
if let elements = elements {
for element in elements {
element.switchMutatedDelegate = switchMutatedDelegate
}
}
}
fileprivate func composeStackView(elementHeight: CGFloat, separatorLineThickness: CGFloat, titles: [String], icons: [UIImage?]?, onStates: [Bool]) {
// stackView properties
axis = .vertical
alignment = .leading
spacing = 0.0
// create stackView elements
elements = (0..<titles.count).map { (idx) -> MenuSwitchElementStackView in
if icons?.count ?? 0 > 0 {
elementStackView = MenuSwitchElementStackView(frame: .zero, text: titles[idx], icon: icons?[idx], onState: onStates[idx], switchID: idx)
} else {
elementStackView = MenuSwitchElementStackView(frame: .zero, text: titles[idx], icon: nil, onState: onStates[idx], switchID: idx)
}
elementStackView?.isUserInteractionEnabled = true
elementStackView?.tag = idx
return elementStackView!
}
var singleLines = [UIView]()
let lineThickness: CGFloat = separatorLineThickness
// compose the stackView
if let elements = elements {
for (idx, view) in elements.enumerated() {
// add element to stackView
addArrangedSubview(view)
if idx < titles.count - 1 {
// add single Line to stackView
let singleLineView = UIView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: lineThickness))
singleLineView.backgroundColor = ImageConverter.UIColorFromRGB(0x606060, alpha: 1.0)
singleLines.append(singleLineView)
addArrangedSubview(singleLineView)
}
}
}
// set constraints
translatesAutoresizingMaskIntoConstraints = false
if let elements = elements {
for (idx, element) in elements.enumerated() {
element.translatesAutoresizingMaskIntoConstraints = false
element.leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
element.trailingAnchor.constraint(equalTo: trailingAnchor).isActive = true
element.heightAnchor.constraint(equalToConstant: elementHeight).isActive = true
if idx < titles.count - 1 {
singleLines[idx].translatesAutoresizingMaskIntoConstraints = false
singleLines[idx].topAnchor.constraint(equalTo: element.bottomAnchor).isActive = true
singleLines[idx].heightAnchor.constraint(equalToConstant: lineThickness).isActive = true
if icons?.count ?? 0 > 0 {
if let _ = icons?[idx] {
singleLines[idx].leadingAnchor.constraint(equalTo: leadingAnchor, constant: 39.0).isActive = true
}
} else {
singleLines[idx].leadingAnchor.constraint(equalTo: leadingAnchor).isActive = true
}
singleLines[idx].trailingAnchor.constraint(equalTo: trailingAnchor, constant: 9.0).isActive = true
}
}
}
}
}
class ListSectionBackgroundView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
}
convenience init(frame: CGRect, height: CGFloat = 60.0, backgroundColor: UIColor) {
self.init(frame: frame)
composeView(height: height, backgroundColor: backgroundColor)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
fileprivate func composeView(height: CGFloat, backgroundColor: UIColor) {
// View properties
self.backgroundColor = backgroundColor
self.layer.cornerRadius = 10.0
self.layer.masksToBounds = true
self.clipsToBounds = true
// set Constraints
setConstraints(height)
}
fileprivate func setConstraints(_ height: CGFloat) {
self.translatesAutoresizingMaskIntoConstraints = false
self.heightAnchor.constraint(equalToConstant: height).isActive = true
}
}
推荐答案
我终于找到了解决方案.
I finally found a solution.
是UIView扩展名"anchor"在我的代码中由于某种原因在iOS14下不再起作用.
It was the UIView-extension "anchor" in my code that no longer works under iOS14 for some reason.
因此,如果我使用扩展名并执行以下操作-那么ViewHierarchy中的所有UIControl均无法正常工作(即不再执行target-actions,switch-didChanges等)
Therefore, if I use the extension and do the following - then any UIControls in my ViewHierarchy do not work (i.e. no target-actions, switch-didChanges, etc will no longer kick-in)
SettingsStackView.anchor(top: safeAreaLayoutGuide.topAnchor, leading: contentView.leadingAnchor, bottom: contentView.bottomAnchor, trailing: contentView.trailingAnchor)
但是,如果我没有UIView扩展名,那么一切都会很好:
However, if I do it without the UIView-extension, then everything works fine:
SettingsStackView.translatesAutoresizingMaskIntoConstraints = false
SettingsStackView.topAnchor.constraint(equalTo: contentView.safeAreaLayoutGuide.topAnchor).isActive = true
SettingsStackView.leadingAnchor.constraint(equalTo: contentView.leadingAnchor).isActive = true
SettingsStackView.bottomAnchor.constraint(equalTo: contentView.bottomAnchor).isActive = true
SettingsStackView.trailingAnchor.constraint(equalTo: contentView.trailingAnchor).isActive = true
也许有人可以告诉我,iOS14为什么会出现这种新行为?
Maybe somebody can tell me why this new behaviour came up with iOS14 ???
这篇关于iOS14:没有UIControl在UIKit Modal ViewController中工作了的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!