【问题标题】:Making SMS ViewController pop up on iPhone using Unity3D使用 Unity3D 在 iPhone 上弹出 SMS ViewController
【发布时间】:2016-03-16 00:28:03
【问题描述】:

我无法让MFMessageComposeUnity3D iOS Plugin 合作。

我收到一个弹出按钮的警报窗口,但在访问MFMessageComposer 时出现错误。似乎无法正确弹出窗口的方法。

这是我的iOSBridge.h(如果需要,可以链接文件):

#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <MessageUI/MessageUI.h>

@interface Delegate : NSObject <UINavigationControllerDelegate, MFMessageComposeViewControllerDelegate>

@end

还有我的iOSBridge.mm 文件:

#import "iOSBridge.h"

@implementation Delegate


//Trying to still understand the meaning behind this line.  Why???
-(id)init
{
    return self;
}

//RATE US Button Numbers
//Not entirely sure What I did here but it still bring it up.  This section has nothing to do with SMS
-(void) alertView: (UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
    //Give back the number of the button

    NSString *inStr = [NSString stringWithFormat:@"%d", (int)buttonIndex];
    const char *cString = [inStr cStringUsingEncoding:NSASCIIStringEncoding];
    UnitySendMessage("Popup", "UserFeedBack", cString);
    NSLog(@"%li", (long)buttonIndex);
} // RATE US button number end

-(void)SMS:(id)sender{

    MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
    [controller setMessageComposeDelegate:self];

    if([MFMessageComposeViewController canSendText]){

        [controller setRecipients:[NSArray arrayWithObjects:nil]];
        [controller setBody:[NSString stringWithFormat:@"Text"]];

        //WHYYY do you not work
        //[self presentViewController:controller animated:YES];

        Delegate *appDelegate = UIApplication.sharedApplication.delegate;
        [appDelegate.window.rootViewController presentViewController:controller animated:YES completion:nil]
    }

}

@end

static Delegate* delegateObject;

extern "C"
{

//A method for unity can run
void _AddNotification(const char* title,
                  const char* body,
                  const char* cancelLabel,
                  const char* firstLabel,
                  const char* secondLabel)

{

//Don't have a full grasp of this delegateObject thing yet.
if(delegateObject ==nil){
    delegateObject = [[Delegate alloc]init];
}

//iOS Alert Pop up view RATE OUR GAME

UIAlertView *alert = [[UIAlertView alloc]
                      initWithTitle: [NSString stringWithUTF8String:title]
                      message:[NSString stringWithUTF8String:body] delegate:delegateObject
                      cancelButtonTitle:[NSString stringWithUTF8String:cancelLabel]
                      otherButtonTitles:[NSString stringWithUTF8String:firstLabel],[NSString stringWithUTF8String:secondLabel], nil];


    [alert show];
} //End of _AddNotification


//SMS Method for Unity to use
void _SMSGO(const char* Mbody){

        MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
        if([MFMessageComposeViewController canSendText]){

            NSString *s = [NSString stringWithFormat:@"%s", Mbody];
            controller.body = s;

            //Suppose to Brings up the SMS view not sure why it isnt working or how to make this work
            //If this can work its major progress

            [delegateObject presentViewController:controller animated:YES];
        }
    }
}

【问题讨论】:

    标签: ios objective-c c unity3d sms


    【解决方案1】:

    所以这些:

    -(void) alertView: (UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
    {
        NSString *inStr = [NSString stringWithFormat:@"%d", (int)buttonIndex];
        const char *cString = [inStr cStringUsingEncoding:NSASCIIStringEncoding];
        UnitySendMessage("Popup", "UserFeedBack", cString);
        NSLog(@"%li", (long)buttonIndex);
    }
    
    -(void)SMS:(id)sender{
    
        MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
        [controller setMessageComposeDelegate:self];
    
        if([MFMessageComposeViewController canSendText]){
    
            [controller setRecipients:[NSArray arrayWithObjects:nil]];
            [controller setBody:[NSString stringWithFormat:@"Text"]];
    
            //WHYYY do you not work
            //[self presentViewController:controller animated:YES];
    
            Delegate *appDelegate = UIApplication.sharedApplication.delegate;
            [appDelegate.window.rootViewController presentViewController:controller animated:YES completion:nil]
        }    
    }
    

    实际上根本没有通过您的网桥访问代码块。所以这里面什么都不会被触及。

    - (id) init 是类的初始化器。因此,为了从其他任何内容访问该文件中的任何内容,您必须先init 它。一个更简单的想法是:

    extern.c 是一个单独的文件。

    static Delegate *delObj;
    
    extern "C"
    {
        void _callMain (const char *hello) {
            /**
             * delObj is a static so it "Will be once it is" so it will be
             * in memory (mallocated) the moment you tell it to be something.
             */
            if (!delObj) {
    

    在这种情况下,我们希望该静态对象成为 Delegate 的实例(这不是一个特别好的名称来设置您的类,它会导致很多混乱)。我们通过调用init“启动”或初始化这个类,然后告诉它这是我们需要的对象,把它放到 read this

            delObj = [[Delegate alloc] init];
        }
    
        // Now we can call the function in the next file
        [delObj helloWorld];
    }
    

    Delegate.m - 将其视为不同的文件。您可以从extern.c 访问此文件,因为(实际上)它只是包含在同一个文件中。但这完全作为一个单独的实体。您必须从 extern.c

    访问此“文件
    @implementation Delegate
    
    // This is the function we call with [[Delegate alloc] init];
    -(id) init {
        // It simply returns itself - saying hey this is the object memory chunk in the heap you want to talk to.
        return self;
    }
    
    // This is the function we call with [delObj helloWorld];
    - (void) helloWorld {
        NSLog("Hello World"); // This will show up in your console.
    }
    

    所以上面的代码有两个函数,一个是说“这是你要找的内存对象”,一个是说“我是一个函数,让我们执行一些东西”。

    现在所有这些都已经列出,你没有打电话了:

    -(void) alertView: (UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
    

    -(void)SMS:(id)sender{
    

    通过您的extern "C"_AddNotification 工作的原因是因为你有代码在那里调用 UIAlertView AFTER 确保你的 delegateObject 在内存中。在您的 _SMSGO 函数中,您没有将对象放入内存中。所以当你在[delegateObject presentViewController:controller animated:YES]; 中调用delegateObject 时,它会说“哦,我知道delegateObject 但它等于没有。事实上它没有内存来执行任何东西!”这就是为什么您可能不会收到任何错误或异常的原因。代码知道有一个静态对象,但它还没有被设置为任何东西。

    解决方案:

    首先,void 方法不需要 :(id)sender 更多的是 IBAction 东西,除非你真的想发送一些东西 - 所以将 -(void)SMS:(id)sender{ 更改为 - (void) SMS { (也有漂亮的间距。它是 mo' 对眼睛更好)。

    其次,将SMS 中的所有内容替换为:

    - (void) SMS {
    
        MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
        [controller setMessageComposeDelegate:self];
    
        if([MFMessageComposeViewController canSendText]){
    
            [controller setRecipients:[NSArray arrayWithObjects:nil]];
            [controller setBody:[NSString stringWithFormat:@"Text"]];
    
            // We now know why we work!
            [self presentViewController:controller animated:YES];
        }    
    }
    

    但是等等!并且不要复制和粘贴。请务必理解您编写的每一行代码。

    这一行分配一个对象到内存中,在本例中为MFMessageComposeViewController 对象。然后初始化它。

    MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
    

    这一行设置了我们刚刚创建的对象 (controller) 的 delegate。但是为什么它可以做到这一点?因为我们在iOSBridge.h 文件中设置了MFMessageComposeViewControllerDelegate。这会告诉您 .mm 文件中的所有内容“嘿,如果我们碰巧在某处有一个 MFMessage 对象,它可能如果你愿意访问委托属性。” [controller setMessageComposeDelegate:self];

    if ( [MFMessageComposeViewController canSendText] ) 是人类可读的。

    [controller setRecipients:[NSArray arrayWithObjects:nil]];[controller setBody:[NSString stringWithFormat:@"Text"]]; 相同

    但是现在[self presentViewController:controller animated:YES]; 是我们需要潜入的。

    所以在 Unity 中,他们说“嘿,我们不需要处理每个可能被调用的本机函数”——因此他们为您创建了对 extern 功能的访问。这允许您从 UnityScript 方面与 Objective-C 对话。 Objective-C 只是 C 的超集,所以这是共同点。这里的一切都应该只调用函数in Delegate。上面的例子是假的extern.c 代码块。唯一要做的就是创建delegateObject 并调用一个函数。现在进行下一步。将_SMSGO 中的所有内容替换为:

    void _SMSGO (const char *mBody) { // I prefer char *name vs char* name but it doesn't matter
    
        [delegateObject SMS]; // add mBody as a parameter when you're ready. Handle the stringWithUTF8String on the Objective-C side of things. Yes, this is not the Obj-C side, this is the C side.
    
    }
    

    “但是等等......你只是 delegateObject 需要成为一个东西” - 是的。在您的 extern "C" 部分中创建另一个名为 _init 的方法,并在您的类的 AwakeStart 函数中从 Unity 运行此一次。这将设置您的静态对象一次,并且永远不会再弄乱它。简单地做:

    void _init() {
        if ( !delegateObject ) {
            delegateObject = [[Delegate alloc] init];
        }
    }
    

    !delegateObjectdelegateObject == nil 相同,但代码更简洁。两人都说“我们不知道 dat 是什么” - 好的,现在我们有了delegateObject,我们可以随意拨打delegateObject 进行下一次通话。

    现在,当您拨打 [delegateObject SMS] 时,它会转到 - (void) SMS。当您调用 self presentViewController 时,它知道 self 指的是 iOS 原生对象。如果您在extern "C" 中调用presentViewController,它会说“...嗯,嗯。我没有最模糊的概念这意味着什么” - 出于这个原因,我们在您的extern "C" 部分作为您的 Delegate 对象的交叉部分。这就是 extern 东西的全部目的,只是为了在你的 Obj-C 东西中调用东西。

    希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2014-10-13
      • 1970-01-01
      • 1970-01-01
      • 2019-06-28
      • 2012-12-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多