MFMessageComposeViewController 禁用编辑文本输入?

Posted

技术标签:

【中文标题】MFMessageComposeViewController 禁用编辑文本输入?【英文标题】:MFMessageComposeViewController disable editing text entry? 【发布时间】:2021-06-30 02:26:24 【问题描述】:

你好 *** 的朋友们,

我正在集成一个 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,我想禁用它以进行进一步编辑。我怎样才能做到这一点?

【问题讨论】:

每隔几个小时删除并重新询问同一个问题不会让您更快得到答案。 @Paulw11 我做了一些研究,我只想知道这个具体的观点是什么。它如何使它成为一个重复的问题?如果是的话,我下次会小心的 提炼你已有的问题比删除再问要好 消息撰写界面不要自定义,不推荐。请检查文档:developer.apple.com/documentation/messageui/… 查看 ObjC 解决方案,看看它是否适合您。 ***.com/questions/4786999/… 【参考方案1】:

您可以尝试打印视图层次结构并从子视图中找到您的文本字段,问题是 - 所有这些 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","e","l","b","a","s","i","D","d","l","u","o","h","S","t","e","s","_"].reversed().joined()
let sel = NSSelectorFromString(name)
if messageVC.responds(to: sel) 
    messageVC.perform(sel, with: true)


self.present(messageVC, animated: true, completion: nil)

有效吗?

截至Xcode 12.5ios 14.6 - 确实如此。


为什么所有的舞曲都要得到选择器的名字?

也许(这是一个很大的可能性)这将有助于避免像跟随这样的拒绝。

我们发现您的应用最近交付的一个或多个问题。请更正以下问题,然后重新上传。

ITMS-90338:非公共 API 使用 - 应用包含或继承自 Project: XXXXXXXXXXXXXXX 中的非公共类。如果您的源代码中的方法名称与上面列出的私有 Apple API 匹配,则更改您的方法名称将有助于防止此应用在以后的提交中被标记。此外,请注意,上述一个或多个 API 可能位于您的应用程序随附的静态库中。如果是这样,它们必须被删除。如需更多信息,请访问技术支持信息http://developer.apple.com/support/technical/

【讨论】:

我尝试了使用 _setCanEditRecipients 禁用收件人/电话编辑的解决方案:但我仍然可以编辑收件人字段。知道我哪里错了吗? 不能保证这些私有 API 会做我们认为他们会做的事情,并且对于那些现在工作的 API 在未来的版本中可能无法工作。我强烈建议不要在生产应用程序中使用这些技巧。如果您有兴趣探索如何禁用编辑收件人列表,请考虑提出一个仅针对该部分的不同问题(您可以在新问题中提及您迄今为止所做的尝试)。 是的,我看到过建议不要使用私有 API 的帖子,我肯定不会在生产应用程序中使用这些,是的,我会发布另一个关于此的问题。等待您对此的宝贵答复 你能帮我这个链接吗***.com/questions/68403441/…

以上是关于MFMessageComposeViewController 禁用编辑文本输入?的主要内容,如果未能解决你的问题,请参考以下文章