Layout UIButtonBarButton布局在iPad而非iPhone上输入UITextView时出现警告
我有一个简单的反馈表单,它是TabBarController中两个ViewController之一。没有故事板,所有编程用户界面(UIKit),通用应用程序。在iPad上输入textView时,控制台会抛出布局警告:Layout UIButtonBarButton布局在iPad而非iPhone上输入UITextView时出现警告,layout,uikit,uitextview,swift5,Layout,Uikit,Uitextview,Swift5,我有一个简单的反馈表单,它是TabBarController中两个ViewController之一。没有故事板,所有编程用户界面(UIKit),通用应用程序。在iPad上输入textView时,控制台会抛出布局警告: "<NSAutoresizingMaskLayoutConstraint:0x2808aa5d0 h=--& v=--& _UIButtonBarButton:0x129e8c6d0.height == 0 (active)>&qu
"<NSAutoresizingMaskLayoutConstraint:0x2808aa5d0 h=--& v=--& _UIButtonBarButton:0x129e8c6d0.height == 0 (active)>",
"<NSLayoutConstraint:0x2808a9d60 V:|-(6)-[_UIUCBKBSelectionBackground:0x129e8d4e0] (active, names: '|':_UIButtonBarButton:0x129e8c6d0 )>",
"<NSLayoutConstraint:0x2808a9e00 _UIUCBKBSelectionBackground:0x129e8d4e0.bottom == _UIButtonBarButton:0x129e8c6d0.bottom - 6 (active)>"
“”,
"",
""
这不会发生在iPhone上。除此之外,该表单工作正常。我不知道这是从哪里来的,也不知道如何解决。任何提示,谢谢
更新;现在,在输入时,我的所有文本视图和文本字段上都会显示此信息。14.2事件
视图控制器代码:
import UIKit
import MessageUI
struct MailOption {
let url: URL!
let titel: String
}
class FeedbackViewController: UIViewController, MFMailComposeViewControllerDelegate ,UINavigationControllerDelegate {
//MARK: - Properties
let logoImageView = ProjectImageView(frame: .zero)
let appVersionLabel = ProjectTitleLabel(withTextAlignment: .center, andFont: UIFont.preferredFont(forTextStyle: .title3), andColor: .label, numberOfLines: 2)
let developerLabel = ProjectTitleLabel(withTextAlignment: .center, andFont: UIFont.preferredFont(forTextStyle: .footnote), andColor: .tertiarySystemBackground, numberOfLines: 1)
let feedbackTextView = ProjectTextView()
let spacerView = UIView()
let sendButton = ProjectButton(withBackgroundColor: .systemOrange, andTitle: "Send")
var feedbackTextViewPlaceholder = ProjectTextViewPlaceholderTextFor.feedback
let emailTo = ProjectEmailAddresses.g
var emailBody = ""
let emailSubject = "Feedback on \(Bundle.main.displayName ?? "Unknown"), version \(Bundle.main.version ?? "")"
//MARK: - ViewController Methods
override func viewDidLoad() {
super.viewDidLoad()
configureViewController()
configureView()
configureAppVersionLabel()
configureFeedbackTextView()
configureSendButton()
}
//MARK: - Actions
@objc private func endEditing() {
view.endEditing(true)
}
@objc func adjustForKeyboard(notification: Notification) {
//Reset to origin position
self.view.frame.origin.y = 0
if notification.name.rawValue == "UIKeyboardWillChangeFrameNotification" {
if feedbackTextView.isFirstResponder {
self.view.frame.origin.y -= feedbackTextView.frame.origin.y + 10
}
} else {
self.view.frame.origin.y = 0
}
}
@objc private func sendButtonTapped() {
//Extra check on feedback being present
guard let feedback = feedbackTextView.text, feedback.isNotEmpty else { return }
emailBody = feedback
let subjectEncoded = emailSubject.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!
let bodyEncoded = emailBody.addingPercentEncoding(withAllowedCharacters: .urlHostAllowed)!
let gMail = MailOption(url: URL(string: "googlegmail://co?to=\(emailTo)&subject=\(subjectEncoded)&body=\(bodyEncoded)"), titel: "GMail")
let outlook = MailOption(url: URL(string: "ms-outlook://compose?to=\(emailTo)&subject=\(subjectEncoded)&body=\(bodyEncoded)"), titel: "Outlook")
let spark = MailOption(url: URL(string: "readdle-spark://compose?recipient=\(emailTo)&subject=\(subjectEncoded)&body=\(bodyEncoded)"), titel: "Spark")
let availableUrls = [gMail, outlook, spark].filter { (mailOption) -> Bool in
return mailOption.url != nil && UIApplication.shared.canOpenURL(mailOption.url)
}
showEmailOptions(for: availableUrls)
}
//MARK: - Mail functionality
func showEmailOptions(for mailOptions: [MailOption]) {
//Create action sheet
let ac = UIAlertController(title: "Choose your preferred method of sending mail", message: nil, preferredStyle: .actionSheet)
//Add Apple Mail action if that is available
if MFMailComposeViewController.canSendMail() {
ac.addAction(UIAlertAction(title: "Apple Mail", style: .default, handler: { (_) in
self.sendAppleMail()
}))
}
//Add other available actions
for option in mailOptions {
ac.addAction(UIAlertAction(title: option.titel, style: .default, handler: { (_) in
UIApplication.shared.open(option.url, options: [:], completionHandler: { _ in
self.showSuccess()
})
}))
}
//Cancel action
ac.addAction(UIAlertAction(title: "Cancel", style: .cancel, handler: nil))
//Needed for iPads
if UIDevice.current.userInterfaceIdiom == .pad {
ac.popoverPresentationController?.sourceView = sendButton
ac.popoverPresentationController?.permittedArrowDirections = [.down, .up]
}
present(ac, animated: true)
}
func sendAppleMail() {
//we already checked for availability of the Mail App!
let composer = MFMailComposeViewController()
composer.mailComposeDelegate = self
composer.setToRecipients([emailTo])
composer.setSubject(emailSubject)
composer.setMessageBody(emailBody, isHTML: false)
present(composer, animated: true)
}
func mailComposeController(_ controller: MFMailComposeViewController, didFinishWith result: MFMailComposeResult, error: Error?) {
if result == .sent {
self.showSuccess()
}
controller.dismiss(animated: true)
}
private func showSuccess() {
self.presentProjectAlertOnMainThread(withTitle: "Feedback sent!", andMessage: "Thank you for your input!", andDismissButtonTitle: "OK", andConfirmButtonTitle: nil, completion: { _ in
self.feedbackTextView.text = ""
self.sendButton.isEnabled = false
})
}
//MARK: - UI & Layout
private func configureViewController() {
feedbackTextView.delegate = self
view.addGestureRecognizer(UITapGestureRecognizer(target: self, action: #selector(endEditing)))
let notificationCenter = NotificationCenter.default
notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillHideNotification, object: nil)
notificationCenter.addObserver(self, selector: #selector(adjustForKeyboard), name: UIResponder.keyboardWillChangeFrameNotification, object: nil)
}
private func configureView() {
let padding: CGFloat = 20
logoImageView.layer.cornerRadius = 5
logoImageView.contentMode = .scaleAspectFit
appVersionLabel.setContentHuggingPriority(.required, for: .vertical)
developerLabel.setContentHuggingPriority(.required, for: .vertical)
spacerView.translatesAutoresizingMaskIntoConstraints = false
let seperator = Separator(frame: .zero)
let stackView = UIStackView(arrangedSubviews: [logoImageView, appVersionLabel, developerLabel, seperator, feedbackTextView, spacerView, sendButton])
stackView.translatesAutoresizingMaskIntoConstraints = false
stackView.axis = .vertical
stackView.alignment = .center
stackView.spacing = 10
stackView.distribution = .fill
view.addSubview(stackView)
NSLayoutConstraint.activate([
stackView.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor, constant: padding),
stackView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
stackView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
stackView.bottomAnchor.constraint(equalTo: view.safeAreaLayoutGuide.bottomAnchor, constant: -padding),
logoImageView.heightAnchor.constraint(equalToConstant: 88),
logoImageView.widthAnchor.constraint(equalTo: logoImageView.heightAnchor),
logoImageView.centerXAnchor.constraint(equalTo: stackView.centerXAnchor),
seperator.leadingAnchor.constraint(equalTo: stackView.leadingAnchor, constant: padding),
seperator.trailingAnchor.constraint(equalTo: stackView.trailingAnchor, constant: -padding),
feedbackTextView.widthAnchor.constraint(equalTo: stackView.widthAnchor, constant: -(2 * padding)),
feedbackTextView.heightAnchor.constraint(equalTo: view.heightAnchor, multiplier: 0.33),
spacerView.heightAnchor.constraint(greaterThanOrEqualToConstant: 22),
spacerView.widthAnchor.constraint(equalTo: stackView.widthAnchor),
sendButton.widthAnchor.constraint(equalTo: stackView.widthAnchor, constant: -(2 * padding)),
sendButton.heightAnchor.constraint(equalToConstant: 44)
])
}
private func configureAppVersionLabel() {
guard let appName = Bundle.main.displayName, let appVersion = Bundle.main.version else {
appVersionLabel.text = "Unknown"
return
}
appVersionLabel.text = "\(appName)\n\(appVersion)"
developerLabel.text = "developer"
}
@objc private func configureFeedbackTextView() {
feedbackTextView.text = feedbackTextViewPlaceholder
feedbackTextView.textColor = feedbackTextView.text == ProjectTextViewPlaceholderTextFor.feedback ? .tertiaryLabel : .label
}
private func configureSendButton() {
sendButton.addTarget(self, action: #selector(sendButtonTapped), for: .touchUpInside)
sendButton.isEnabled = false
}
}
//MARK: - Delegate UITextView
extension FeedbackViewController: UITextViewDelegate {
func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
//2000 chars restriction
return textView.text.count + (text.count - range.length) <= 2000
}
func textViewDidBeginEditing(_ textView: UITextView) {
if textView.textColor == UIColor.tertiaryLabel {
textView.text = ""
textView.textColor = .label
}
}
func textViewDidEndEditing(_ textView: UITextView) {
if textView.text.isEmpty {
textView.text = ProjectTextViewPlaceholderTextFor.feedback
textView.textColor = .tertiaryLabel
feedbackTextViewPlaceholder = ""
} else {
feedbackTextViewPlaceholder = textView.text
}
}
func textViewDidChange(_ textView: UITextView) {
feedbackTextViewPlaceholder = textView.text
if let text = textView.text, text.isNotEmpty, text != ProjectTextViewPlaceholderTextFor.feedback {
sendButton.isEnabled = true
} else {
sendButton.isEnabled = false
}
}
}
导入UIKit
导入消息用户界面
结构邮件选项{
让url:url!
让我们来看看提特尔:字符串
}
类反馈ViewController:UIViewController、MFMailComposeViewController、UINavigationController、Elegate{
//标记:-属性
让logoImageView=ProjectImageView(帧:.0)
让appVersionLabel=ProjectTitleLabel(带TextAlignment:.center和Font:UIFont.preferredFont(forTextStyle:.title3)和Color:.label,行数:2)
让developerLabel=ProjectTitleLabel(带TextAlignment:.center和Font:UIFont.preferredFont(forTextStyle:.footnote)和Color:.tertiarySystemBackground,行数:1)
让feedbackTextView=ProjectTextView()
让视图=UIView()
让sendButton=ProjectButton(背景色:.systemOrange,标题:“发送”)
var feedbackTextViewPlaceholder=projecttextviewplaceholder.feedback
让emailTo=ProjectEmailAddresses.g
var emailBody=“”
让emailSubject=“关于\(Bundle.main.displayName??“未知”)的反馈”,版本\(Bundle.main.version??)
//MARK:-ViewController方法
重写func viewDidLoad(){
super.viewDidLoad()
configureViewController()
配置视图()
configureAppVersionLabel()
配置反馈文本视图()
configureSendButton()
}
//马克:行动
@objc专用函数endEditing(){
view.endEditing(真)
}
@objc func adjustForKeyboard(通知:通知){
//复位到原点位置
self.view.frame.origin.y=0
如果notification.name.rawValue==“UIKeyboardWillChangeFrameNotification”{
如果feedbackTextView.isFirstResponder{
self.view.frame.origin.y-=feedbackTextView.frame.origin.y+10
}
}否则{
self.view.frame.origin.y=0
}
}
@objc专用函数sendButtonTapped(){
//额外检查反馈是否存在
guard let feedback=feedbackTextView.text,feedback.isNotEmpty else{return}
emailBody=反馈
让subjectEncoded=emailSubject.addingPercentEncoding(允许使用以下字符:.urlHostAllowed)!
让bodyEncoded=emailBody.addingPercentEncoding(使用允许的字符:.urlHostAllowed)!
让gMail=MailOption(url:url)(字符串:“googlegmail://co?to=\(emailTo)&subject=\(subjectEncoded)&body=\(bodyEncoded)”),titel:“GMail”)
让outlook=MailOption(url:url)(字符串:“ms-outlook://compose?to=\(emailTo)&subject=\(subjectEncoded)&body=\(bodyEncoded)”),titel:“Outlook”)
让spark=mailpoption(url:url(string:readdle-spark://compose?recipient=\(emailTo)&subject=\(subjectEncoded)&body=\(bodyEncoded)”,titel:“Spark”)
让availableUrls=[gMail,outlook,spark].filter{(mailOption)->Bool-in
return mailpoption.url!=nil&&UIApplication.shared.canOpenURL(mailpoption.url)
}
showEmailOptions(适用于:availableUrls)
}
//标记:-邮件功能
func showEmailOptions(适用于mailOptions:[MailOption]){
//创建行动表
让ac=UIAlertController(标题:“选择您的首选发送邮件的方法”,消息:无,首选样式:。操作表)
//添加Apple Mail操作(如果可用)
如果MFMailComposeViewController.canSendMail(){
ac.addAction(UIAlertAction)(标题:“Apple Mail”,样式:。默认值,处理程序:{(u)in
self.sendappemail()
}))
}
//添加其他可用操作
对于mailOptions中的选项{
ac.addAction(UIAlertAction)(标题:option.titel,样式:。默认值,处理程序:{(389;)in
UIApplication.shared.open(option.url,options:[:],completionHandler:{in
self.showSuccess()
})
}))
}
//取消操作
ac.addAction(UIAlertAction(标题:“取消”,样式:。取消,处理程序:nil))
//iPad需要
如果UIDevice.current.userInterfaceIdiom==.pad{
ac.popoverPresentationController?.sourceView=sendButton
ac.popoverPresentationController?.permittedArrowDirections=[.down、.up]
}
当前(ac,动画:真)
}
func sendappemail(){
//我们已经检查了邮件应用程序的可用性!
让composer=MFMailComposeViewController()
composer.mailComposeDelegate=self
composer.setToRecipients([emailTo])
编写器.setSubject(emailSubject)
composer.setMessageBody(emailBody,isHTML:false)
现在(作曲家,动画:真)
}
func-mailcomosecontroller(u控制器:mfmailcomoseviewcontroller,didFinishWith结果:MFMailComposeResult,错误:error?){
如果结果==.sent{
self.showSuccess()
}
控制器。解除(动画:真)
}
私人func showSuccess(){
presentProjectAlertOnMainThread(标题为:“已发送反馈!”,消息为:“感谢您的输入!”,dismissButtonTile为“确定”,confirButtonTitle:nil,完成:{in
self.feedbackTextView.text=“”
self.sendButton.isEnabled=false
})
}
//标记:-用户界面和布局
公共关系