How to access weak linked framework in iOS?
Asked Answered
W

4

4

I want to use Twitter framework for iOS 5, but be able to run my app in older OS.

I added weak referenced framework (i.e. set "optional" flag) in Xcode 4.2 Target settings. Base SDK is iOS 5, iOS deployment Target is iOS 3.2.

Next, I try to use Twitter framework:

#import <Twitter/Twitter.h>
...
    Class twClass = NSClassFromString(@"TWTweetComposeViewController");
    if (!twClass) // Framework not available, older iOS
    {
        [self shareWithTwitterPriorIOS5];
        return;
    }

    if ([TWTweetComposeViewController canSendTweet]) // Check if twitter is setup and reachable
    {
        TWTweetComposeViewController* twc = [[TWTweetComposeViewController alloc] init];
//        [twc addURL:[NSURL URLWithString:@"http://mail.ru"]];
//        [twc addImage:[UIImage imageNamed:@"Some image.png"]]
        [twc setInitialText:textToShare];
        [viewController presentViewController:twc animated:YES completion:^{
            // Optional
        }];
        [twc release];
        // Assume twc is ARC released or call [twc release];
    }
    else
    {

    // Twitter account not configured, inform the user
}

It run well on iOS 5 simulator. As soon as I try to use simulator or real device with older OS version, I get error "Twitter/Twitter.h" file not found (in compile time). If I remove "#import" directive, I get a couple of errors TWTweetComposeViewController class not found.

If I comment all twitter-related code, I get linker error: "ld: framework not found Twitter". Ld command caused error:

Ld /Users/mikhailkeskinov/Library/Developer/Xcode/DerivedData/Dictionary-eiyrziajmltuglfzgtnjxffkojwi/Build/Products/Debug-iphoneos/Dictionary.app/Dictionary normal armv6
    cd /Developer/WorkShop/XDictionary/trunk
    setenv IPHONEOS_DEPLOYMENT_TARGET 3.2
    setenv PATH "/Developer/Platforms/iPhoneOS.platform/Developer/usr/bin:/Developer/usr/bin:/usr/bin:/bin:/usr/sbin:/sbin"
    /Developer/Platforms/iPhoneOS.platform/Developer/usr/bin/clang -arch armv6 -isysroot /Developer/Platforms/iPhoneOS.platform/Developer/SDKs/iPhoneOS3.2.sdk -L/Users/mikhailkeskinov/Library/Developer/Xcode/DerivedData/Dictionary-eiyrziajmltuglfzgtnjxffkojwi/Build/Products/Debug-iphoneos "-L/Developer/WorkShop/XDictionary/trunk/Dictionary/Twitter+OAuth/Libraries & Headers" -F/Users/mikhailkeskinov/Library/Developer/Xcode/DerivedData/Dictionary-eiyrziajmltuglfzgtnjxffkojwi/Build/Products/Debug-iphoneos -filelist /Users/mikhailkeskinov/Library/Developer/Xcode/DerivedData/Dictionary-eiyrziajmltuglfzgtnjxffkojwi/Build/Intermediates/Dictionary.build/Debug-iphoneos/Dictionary.build/Objects-normal/armv6/Dictionary.LinkFileList -dead_strip -miphoneos-version-min=3.2 -lxml2 -framework AVFoundation -framework UIKit -framework Foundation -framework CoreGraphics -lOAuth -weak_framework Twitter -o /Users/mikhailkeskinov/Library/Developer/Xcode/DerivedData/Dictionary-eiyrziajmltuglfzgtnjxffkojwi/Build/Products/Debug-iphoneos/Dictionary.app/Dictionary

What is wrong in here?

Winterwinterbottom answered 20/12, 2011 at 19:20 Comment(0)
W
5

After 5 hours, tons silly documentation reader, changing all target & project settings etc. I at least come to solution. Turns out it is pretty easy, when you know it. Probably, my answer will save somebody's day.

enter image description here

As you can see, real device destination ("mkeskinov's iPod") doubled. I never pay attention at this fact. It looks like it just doubled by some mistake, but it is not. If you select "Product\Edit Schemes" & open Destination list (on the top of window), you can clearly see the difference:

enter image description here

What I need to do to successfully compile app for real device - just select second option. It will compile for iOS 5 and then run on real device with OS 4. First option means that it will be compile for iOS 4, and if you have any references to Frameworks, which is not presented in iOS 4 (never mind, weak references or strong) - you get compile time error.

Winterwinterbottom answered 21/12, 2011 at 15:20 Comment(2)
Yes, you saved me from your fate! In my case there was no difference between the two items in the scheme editor, but switching did the trick. I may have triggered this by installing an older iOS SDK in a newer Xcode. Documenting/sharing your self-answer is always a good thing. Thanks.Borneol
Apple fixed this problem in XCode 4.3. The answer above for XCODE v. 4.2Winterwinterbottom
O
4

Your code is probably fine.

You absolutely want to build your app against the iOS5 SDK. The binary you produce will run on older iOS versions (provided your target SDK is an older version, as you have indicated).

Your code is correctly checking for iOS5 capabilities and doing the right thing, and you are correctly weak linking to the Twitter framework. It is these techniques that allows your app (built against the latest SDK) to run without crashing on older iOS versions.

Orlina answered 20/12, 2011 at 21:36 Comment(3)
But how can I run my code on real device with older OS? I expected, that setting Base SDK = 5.0 should cause Xcode to build always against iOS5 SDK.Winterwinterbottom
You need to have a device with an older version. :-) You can test this with the simulator though. Just use the 4.3 simulator, and your app should run (built against the iOS5 SDK) just fine. All the iOS5-specific features that you are checking exist, will not, of courtse, under the 4.3 simulator, but your app should run just fine.Orlina
Finally, I found how to compile against iOS 5. It is pretty easy, when you know (I posted my own answer).Winterwinterbottom
U
1

Add this to your header file .h:

#import <Twitter/TWTweetComposeViewController.h>

Here is what I have used for my app:

if ([TWTweetComposeViewController class])
{
   //can tweet
} else
{
   //can't tweet
} 
Undercool answered 20/12, 2011 at 20:23 Comment(3)
And you use #import <Twitter/Twitter.h> at the top of .m file, right? This #import cause compile-time error for some reason.Winterwinterbottom
So. Can you connect device with older OS version to you MAC and run you app on this device using Xcode 4? If your answer is YES, please let me know, how you do it. I get compile error every time I try use older OS version.Winterwinterbottom
Glad to see you solved the problem. I got sidetracked a little so did not see your question.Undercool
F
0

Instead of using import, you should reference the TWTweetComposeViewController class using the Class object you got from NSClassFromString(), e.g. [twClass canSendTweet] instead of [TWTweetComposeViewController canSendTweet].

Fiend answered 20/12, 2011 at 20:12 Comment(1)
If I do so, I'll get a couple of warrings like "Class method +canSendTweet not found" or "Instance method -setInitialText: not found". Don't like it. And the biggest problem - I still can't run my code under older OS, because of linked error (see edited question above).Winterwinterbottom

© 2022 - 2024 — McMap. All rights reserved.