开发者

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) {
   MFMessageComposeViewCont开发者_JAVA技巧roller *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];


In your target parameters, simply set messageUI.framework to type '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?

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜