简体   繁体   中英

Programmatically control iPhone OS versions to enable functions for both OS 3.x and 4 - MFMessageComposeViewController problem

In order to support iPhone OS 3.x and 4.0 I programmatically control MFMessageComposeViewController functionality like this (use it only if the OS version is 4.0 or above):

// if iPhone OS version >= 4.0
if (os_version_num >= 4) {
   MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
   if([MFMessageComposeViewController canSendText])
   {
      controller.body = text;
      controller.recipients = [NSArray arrayWithObjects: nil];
      controller.messageComposeDelegate = self;
      [self presentModalViewController:controller animated:YES];
      [controller release];
   }
}

But, when I try to run it on iPhone 3.1.3 device, I immediately get the following error (even before application gets loaded):

dyld: Symbol not found: _OBJC_CLASS_$_MFMessageComposeViewController
  Referenced from: /var/mobile/Applications/7232C474-FAD5-4E28-ABC5-8520F62300B0/TextMe.app/TextMe
  Expected in: /System/Library/Frameworks/MessageUI.framework/MessageUI

Data Formatters temporarily unavailable, will re-try after a 'continue'. (Not safe to call dlopen at this time.)

What am I doing wrong?

You need to make sure you're doing a few things:

In your target's build settings:

  • set Base SDK to iPhone Device 4.0
  • set iPhone OS Deployment Target to iPhone OS 3.1.3 (or lower)

In your target's general settings, under Linked Libraries, change the "Type" next to MessageUI.framework to Weak.

Don't import <MessageUI/MFMessageComposeViewController.h> or it will crash on launch in 3.x. Just import <MessageUI/MessageUI.h>

I don't know what os_version_num is, but here's the code I use to test for the availability of MFMessageComposeViewController:

Class smsClass = (NSClassFromString(@"MFMessageComposeViewController"));
if (smsClass != nil && [MFMessageComposeViewController canSendText]) {
   MFMessageComposeViewController *controller = [[MFMessageComposeViewController alloc] init];
   controller.body = text;
   controller.recipients = [NSArray arrayWithObjects: nil];
   controller.messageComposeDelegate = self;
   [self presentModalViewController:controller animated:YES];
   [controller release];                
}
Class theClass = NSClassFromString(@"MFMessageComposeViewController");
MFMessageComposeViewController *controller = theClass ? [[theClass alloc] init] : nil;

You can use the type MFMessageComposeViewController as in:

MFMessageComposeViewController *controller;

But you cannot use the global object MFMessageComposeViewController as in:

[MFMessageComposeViewController alloc];

Instead use the class lookup so you are not dependent on the linker:

[NSClassFromString(@"MFMessageComposeViewController") alloc];

在目标参数中,只需将messageUI.framework设置为'weak'即可

If you import <MessageUI/MessageUI.h> and set weak reference to MessageUI framework, you can directly call:

   if ([MFMessageComposeViewController canSendText]) {
        controller.body = body;
        controller.recipients = [NSArray arrayWithObjects:number, nil];
        controller.messageComposeDelegate = self;
        [self presentModalViewController:controller animated:YES];
        [controller release]; 
    } else {
        [[UIApplication sharedApplication] openURL: [NSURL URLWithString:[NSString stringWithFormat:@"sms:%@",number]]];
    }

On iOS 3.1.2 you will get nil in the if clause and old method will be launched.

I was having the same problem, and solved it a different way:

On the Left hand-side of your XCode window,

  1. If you scroll down to the Bulls Eye with "Targets" and expand that

  2. Expand your

  3. < control > + < click > on "Link Binary With Libraries"

  4. Choose "Add" --> "Existing Frameworks"

  5. Choose "MessageUI.framework" and click on "Add"

That should add the Message UI to your app, tell me if it works.

What about if you have functions that you only want to include conditionally.

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

For example, if the function definition contained MFMessageViewController , how do you make this part conditional (that is, not cause a problem with OS 3.x). Or is it not a problem at all?

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM