微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

如何访问私有 API 框架中的方法并将值传递给它?

如何解决如何访问私有 API 框架中的方法并将值传递给它?

首先 - 我知道私有框架/API 不会让我进入 AppStore,这仅供私人使用/研究。

因此,出于研究目的,我选择了 MFMessageComposer,我想禁用对从代码传递的任何输入的编辑。

我试着把我的手放在这个上面,我用下面的方式编码。我所做的是采用私有框架的路径并访问名为 CKSMSComposeController 的特定类,该类具有上述方法。我引用了 ChatKit.framework https://github.com/nst/iOS-Runtime-Headers/blob/master/PrivateFrameworks/ChatKit.framework/CKSMSComposeController.h

class dump

这是我的代码

#import "ViewController.h"
#import <MessageUI/MessageUI.h>

@interface ViewController ()<MFMessageComposeViewControllerDelegate>

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    // Here I load the CKSMSController class

    NSBundle *b = [NSBundle bundleWithPath:@"/System/Library/PrivateFrameworks/ChatKit.framework"];
    BOOL success = [b load];
    NSLog(@"Result %@",success ? @"YES" : @"NO");
    Class CKSMSComposeController = NSClassFromString(@"CKSMSComposeController");
     // Passing no to setCanEditRecipients so as to disable the Editing of recepients
     id si = [[CKSMSComposeController alloc] valueForKey:@"init"];
     SEL sel = NSSelectorFromString(@"setCanEditRecipients:");

    if ([CKSMSComposeController respondsToSelector:sel]) {
        BOOL myBool = NO;
        NSNumber *passedValue = [NSNumber numberWithBool:myBool];
    [CKSMSComposeController performSelector:sel withObject:passedValue];
    }
    NSLog(@"ID is%@",si);

}


- (IBAction)sendMessage:(UIButton *)sender {
    if([MFMessageComposeViewController canSendText]) {
        MFMessageComposeViewController *messageController = [[MFMessageComposeViewController alloc] init]; // Create message VC
        messageController.messageComposeDelegate = self; // Set delegate to current instance

        NSMutableArray *recipients = [[NSMutableArray alloc] init]; // Create an array to hold the recipients
        [recipients addobject:@"555-555-5555"]; // Append example phone number to array
        messageController.recipients = recipients; // Set the recipients of the message to the created array

        messageController.body = @"Example message"; // Set initial text to example message

        dispatch_async(dispatch_get_main_queue(),^{ // Present VC when possible
            [self presentViewController:messageController animated:YES completion:NULL];
        });
    }
}

- (void)messageComposeViewController:(MFMessageComposeViewController *)controller didFinishWithResult:(MessageComposeResult)result {
    [self dismissViewControllerAnimated:YES completion:NULL];
}

@end

我将 NSLog(@"Result %@",success ? @"YES" : @"NO"); 的日志设为 YES,但即使将 NO 传递给上面的选择器,我仍然无法禁用收件人的编辑

有人能告诉我我是否以正确的方式传递参数吗? 因为 -(void)setCanEditRecipients:(BOOL)arg1;` 这是一个私有方法框架接受 bool 作为参数,我在上面的代码中传递 NO

这仅用于私有框架的内部研究。我哪里做错了?。请告诉

解决方法

类方法以 + 开头,实例方法以 - 中的 Objective-C 开头。

// Following is an instance method because it starts with `-`
- (void)setCanEditRecipients:(bool)arg1;

以上方法不适用于以下代码。

Class CKSMSComposeController = NSClassFromString(@"CKSMSComposeController");
SEL sel = NSSelectorFromString(@"setCanEditRecipients:");

// `CKSMSComposeController` is a class - NOT an instance
if ([CKSMSComposeController respondsToSelector:sel]) {
    // will not enter if's body
}

最重要的是 - 您不应该创建自己的实例并对其进行自定义。您应该对系统在屏幕上显示的实例进行自定义。

这是你可以尝试的方法 -

- (void) showMessageComposeViewController {
    if ([MFMessageComposeViewController canSendText]) {
        MFMessageComposeViewController* messageController = [[MFMessageComposeViewController alloc] init];
        messageController.recipients = @[@"555-555-5555"];
        messageController.body = @"Example message";
        
        [self presentViewController:messageController animated:YES completion:^{
            
            // Allow enough time for the UI to be loaded fully
            dispatch_after(1,dispatch_get_main_queue(),^{
                // Since `MFMessageComposeViewController` is a `UINavigationController`,we can access it's first view controller like this
                UIViewController* targetVC = messageController.viewControllers.firstObject;
                
                // Check if the instance is of correct class type
                if ([targetVC isKindOfClass:NSClassFromString(@"CKSMSComposeController")]) {
                    
                    SEL sel1 = NSSelectorFromString(@"setCanEditRecipients:");
                    if ([targetVC respondsToSelector:sel1]) {
                        // put breakpoint here to check whether this line is executed
                        [targetVC performSelector:sel1 withObject:@NO];
                    }
                    
                    SEL sel2 = NSSelectorFromString(@"setTextEntryContentsVisible:");
                    if ([targetVC respondsToSelector:sel2]) {
                        // put breakpoint here to check whether this line is executed
                        [targetVC performSelector:sel2 withObject:@NO];
                    }
                }
            });
        }];
    }
}

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。