我在让MFMessageCompose与Unity3D 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];
}
}
}发布于 2016-03-16 13:50:39
因此,这些:
-(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 ,确保你的delegateObject在内存中。在_SMSGO函数中,您没有将对象放入内存中。因此,当您在[delegateObject presentViewController:controller animated:YES];中调用delegateObject时,它会说“哦,我知道delegateObject是什么,但它等于什么都不是。事实上,它没有内存来执行任何事情!”这就是为什么你可能不会得到任何错误或异常。代码知道有一个静态对象,但是它还没有被设置为任何值。
解决方案:
首先,:(id)sender方法不需要IBAction,这更像是一个空方法,除非你真的想发送一些东西--所以把-(void)SMS:(id)sender{改成- (void) SMS { (间隔也很大)。它对眼睛没有好处)。
其次,将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)。但是,为什么能做到这一点呢?因为我们在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的超集,所以这是一个共同点。这里的所有内容都应该只调用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的方法,并在您的类的Awake或Start函数中从Unity运行此one time。这将设置你的静态对象一次,再也不会弄乱它了。简单地把它做成:
void _init() {
if ( !delegateObject ) {
delegateObject = [[Delegate alloc] init];
}
}!delegateObject和delegateObject == nil是一样的,但代码更简洁。两者都说“我们不知道dat是什么”--好了,现在我们有了delegateObject,我们可以自由地使用delegateObject进行下一次调用。
现在,当你调用[delegateObject SMS]时,它会转到- (void) SMS。当您调用self presentViewController时,它知道self引用的是iOS本机对象。如果你在extern "C"中调用presentViewController,它会说“……嗯,嗯。我根本不知道这是什么意思”--出于这个原因,我们在你的extern "C"部分使用了everything作为你的Delegate对象的交叉点。这就是extern的全部目的,就是在你的Obj-C东西中调用东西。
希望这能有所帮助。
https://stackoverflow.com/questions/36024759
复制相似问题