如何解决MFMessageComposeViewController 禁用编辑文本输入?
你好 StackOverflow 朋友,
我正在集成一个 MFMessageViewController,我想通过禁止键盘出现或禁止用户交互来禁用它的编辑区域。目前我的代码是:
import UIKit
import MessageUI
class ViewController: UIViewController,MFMessageComposeViewControllerDelegate,UITextFieldDelegate {
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBAction func sendSmsClick(_ sender: AnyObject) {
guard MFMessageComposeViewController.canSendText() else {
return
}
let messageVC = MFMessageComposeViewController()
UIButton.appearance(whenContainedInInstancesOf: [MFMessageComposeViewController.self]).isUserInteractionEnabled = false
messageVC.body = "Enter a message hjhjhjkhjkhjhjhjjhgjhghjgjhghjghjghjghjgjhghjghjgjhghjghjghghjghjghjghghjghjhjghjghjghhvvvbnvhvhghghguyguygyugugigiugIoUiopuopuoppuuo";
messageVC.recipients = ["Enter tel-nr"]
messageVC.messageComposeDelegate = self;
NSLog("Subviews %@",messageVC.view.subviews);
// self.view.endEditing(true)
self.present(messageVC,animated: false) {
// self.getAllSubviews(view: messageVC.view)
messageVC.view.loopViewHierarchy { (view,stop) in
if view is UIButton {
/// use the view
print("here")
stop = true
}
}
}
}
func messageComposeViewController(_ controller: MFMessageComposeViewController,didFinishWith result: MessageComposeResult) {
switch (result.rawValue) {
case MessageComposeResult.cancelled.rawValue:
print("Message was cancelled")
self.dismiss(animated: true,completion: nil)
case MessageComposeResult.Failed.rawValue:
print("Message Failed")
self.dismiss(animated: true,completion: nil)
case MessageComposeResult.sent.rawValue:
print("Message was sent")
self.dismiss(animated: true,completion: nil)
default:
break;
}
}
它工作正常,我只想了解键盘上方的特定 UIElement,我想禁用它以进行进一步编辑。我怎样才能做到这一点?
解决方法
您可以尝试打印视图层次结构并从子视图中找到您的文本字段,问题是 - 所有这些 UI 都运行在与您的应用程序不同的环境中,您在那里找不到任何有用的东西。
/// Helper for printing view hierarchy recursively
extension UIView {
func printViewHierarchy() {
print(self)
for view in self.subviews {
view.printViewHierarchy()
}
}
}
self.present(messageVC,animated: true,completion: {
// Try printing the view hierarchy after it has been loaded on to screen
messageVC.view.printViewHierarchy()
})
// Here's what's printed by above
<UILayoutContainerView: 0x100a04990; frame = (0 0; 375 627); clipsToBounds = YES; autoresize = W+H; gestureRecognizers = <NSArray: 0x28100ef10>; layer = <CALayer: 0x281eac720>>
<UINavigationTransitionView: 0x100c0e0d0; frame = (0 0; 375 627); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x281eee860>>
<UIViewControllerWrapperView: 0x100c0f990; frame = (0 0; 375 627); autoresize = W+H; layer = <CALayer: 0x281e975e0>>
<UIView: 0x103b04900; frame = (0 0; 375 627); autoresize = W+H; layer = <CALayer: 0x281e8aa80>>
<_UISizeTrackingView: 0x103a05f80; frame = (0 0; 375 627); clipsToBounds = YES; autoresize = W+H; layer = <CALayer: 0x281e84c60>>
<_UIRemoteView: 0x103a077f0; frame = (0 0; 375 667); userInteractionEnabled = NO; layer = <CALayerHost: 0x281e84b20>>
此 _UIRemoteView
会妨碍您,您将无法在视图层次结构中找到目标 textField
/button
。
我们还能做什么?
使用很可能会导致我们被 App Store 拒绝的私有 API。
如何找到我们可以使用哪些私有 api?
ObjectiveC.runtime
为您提供检查课程详细信息的方法(公共 + 私人)。
import ObjectiveC.runtime
func printClassDetails(_ targetClass: AnyClass) {
var varCount: UInt32 = 0
let iVars = class_copyIvarList(targetClass,&varCount)
var index = 0
if let iVars = iVars {
while index < varCount-1 {
let iVar = iVars[index]
if let name = ivar_getName(iVar) {
print("iVar ------------> \(String(cString: name))")
}
index += 1
}
}
free(iVars)
index = 0
let methods = class_copyMethodList(targetClass,&varCount)
if let methods = methods {
while index < varCount-1 {
let method = methods[index]
let selector = method_getName(method)
print("method ------------> \(NSStringFromSelector(selector))")
index += 1
}
}
free(methods)
}
使用上面的代码,如果您尝试检查 MFMessageComposeViewController
类,您将看到以下内容。
printClassDetails(MFMessageComposeViewController.self)
iVar ------------> _internal
iVar ------------> _messageComposeDelegate
iVar ------------> _recipients
iVar ------------> _body
iVar ------------> _subject
iVar ------------> _message
iVar ------------> _currentAttachedVideoCount
iVar ------------> _currentAttachedAudioCount
iVar ------------> _currentAttachedImageCount
iVar ------------> _UTITypes
iVar ------------> _photoIDs
iVar ------------> _cloudPhotoIDs
iVar ------------> _contentText
iVar ------------> _contentURLs
iVar ------------> _chatGUID
iVar ------------> _groupName
iVar ------------> _shareSheetSessionID
method ------------> recipients
method ------------> subject
method ------------> setGroupName:
method ------------> setRecipients:
method ------------> smsComposeControllerShouldSendMessageWithText:toRecipients:completion:
method ------------> attachments
method ------------> setMessageComposeDelegate:
method ------------> addRichLinkData:withWebpageURL:
method ------------> addAttachmentURL:withAlternateFilename:
method ------------> addAttachmentData:typeIdentifier:filename:
method ------------> setShareSheetSessionID:
method ------------> automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers
method ------------> message
method ------------> body
method ------------> setChatGUID:
method ------------> setMessage:
method ------------> chatGUID
method ------------> viewWillDisappear:
method ------------> contentText
method ------------> setSubject:
method ------------> viewDidLoad
method ------------> attachmentURLs
method ------------> groupName
method ------------> setUTITypes:
method ------------> dealloc
method ------------> viewDidAppear:
method ------------> viewWillAppear:
method ------------> UTITypes
method ------------> setContentText:
method ------------> setBody:
method ------------> smsComposeControllerCancelled:
method ------------> smsComposeControllerSendStarted:
method ------------> smsComposeControllerEntryViewContentInserted:
method ------------> .cxx_destruct
method ------------> photoIDs
method ------------> setModalPresentationStyle:
method ------------> setPhotoIDs:
method ------------> setContentURLs:
method ------------> setCloudPhotoIDs:
method ------------> initWithNibName:bundle:
method ------------> cloudPhotoIDs
method ------------> contentURLs
method ------------> shareSheetSessionID
method ------------> disableUserAttachments
method ------------> setCurrentAttachedVideoCount:
method ------------> setCurrentAttachedAudioCount:
method ------------> setCurrentAttachedImageCount:
method ------------> _MIMETypeForURL:
method ------------> _isVideoMIMEType:
method ------------> _isAudioMIMEType:
method ------------> _isImageMIMEType:
method ------------> _contentTypeForMIMEType:
method ------------> _updateAttachmentCountForAttachmentURL:
method ------------> canAddAttachmentURL:
method ------------> mutableAttachmentURLs
method ------------> addAttachmentData:withAlternateFilename:
method ------------> insertSharedItemAndReturnEntryViewFrame:withAlternateFilename:completion:
method ------------> showSharedItemInEntryView
method ------------> _setCanEditRecipients:
method ------------> _setShouldDisableEntryField:
method ------------> messageComposeDelegate
method ------------> currentAttachedVideoCount
method ------------> currentAttachedAudioCount
_setShouldDisableEntryField
看起来很有趣。如何使用它?
let messageVC = MFMessageComposeViewController()
messageVC.body = "Enter a message"
messageVC.recipients = ["Test Telephone #"]
let name = [":","d","l","e","i","F","y","r","t","n","E","b","a","s","D","u","o","h","S","_"].reversed().joined()
let sel = NSSelectorFromString(name)
if messageVC.responds(to: sel) {
messageVC.perform(sel,with: true)
}
self.present(messageVC,completion: nil)
有用吗?
截至 Xcode 12.5
和 iOS 14.6
- 确实如此。
为什么要跳到选择器名称?
也许(这是一个很大的可能)这将有助于避免像以下这样的拒绝。
我们发现您的应用最近交付的一个或多个问题。请更正以下问题,然后重新上传。
ITMS-90338:非公共 API 使用 - 应用包含或继承自项目中的非公共类:XXXXXXXXXXXXXX。如果您的源代码中的方法名称与上面列出的私有 Apple API 匹配,则更改您的方法名称将有助于防止此应用在以后的提交中被标记。此外,请注意上述一个或多个 API 可能位于您的应用程序附带的静态库中。如果是这样,它们必须被移除。如需更多信息,请访问 http://developer.apple.com/support/technical/
上的技术支持信息版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。