Why is checking [NSMetadataQuery class] crashing on iOS 4.2.1? - cocoa-touch

I'm attempting to use this approach, described by Marco Arment, for checking if a class exists before using it. With the correct settings, classes are automatically weak-linked when it's appropriate. As Marco describes, "you can safely subclass or have pointers to whatever you want (as long as you’re careful not to instantiate them when they’re not available)".
My app runs fine on iOS 5. I've followed the conditions mentioned at the link:
Base SDK is Latest iOS (iOS 5.1)
Deployment Target is iOS 4.0
Compiler for C/C++/Objective-C is Apple LLVM compiler 3.1 (also tried LLVM GCC 4.2)
Any time I reference NSMetadataQuery I'm making sure the class exists first:
if ([NSMetadataQuery class] != nil) …
Despite all this my app crashes immediately on launch if I try to run it on an iPod touch with iOS 4.2.1:
dyld: Symbol not found: _OBJC_CLASS_$_NSMetadataQuery
I've tried commenting out all the code any my app runs fine. As soon as I add back in a single reference to NSMetadataQuery, it crashes. I've even tried this:
if ([NSMetadataQuery class] != nil) NSLog(#"OK");
Simply including that line, and no other reference to NSMetadataQuery, crashes the app. Even more strange, checking for other iOS 5 classes doesn't cause any problems:
if ([UIDictationPhrase class] != nil) NSLog(#"OK");
That works fine, as expected.
I have been able to work around the problem using the uglier NSClassFromString() to make sure the class exists, but I'd love to know why the other approach isn't working.

I don't have an explanation to this but I ran into the same problem as you. No matter what I/you do, NSMetadataQuery just won't be weak linked...
Refer to this answer, which is really the best one in another question:
https://stackoverflow.com/a/8426591/129202
In short, other auto weak linking seems to work, it's just NSMetadataQuery* that you have to remove from source and replace with id. Instantiate the class with NSClassFromString() etc. No hiccups on other classes like UIDocument however so you can safely use those in the normal sweat free way.

NSMetadataQuery is available in iOS 5.0 and above, so any versions below that has no clue as to what it is. By merely using it in your code, the class name will be added to a symbol table and looked-up when the app launches.

Related

Write SDK version to binary when compiling from command line (macOS)

I am trying to detect whether the system is in dark mode.
I have already tried reading AppleInterfaceStyle from the user defaults i.e.
NSString *interfaceStyle = [[NSUserDefaults standardUserDefaults] stringForKey:#"AppleInterfaceStyle"];
BOOL isDark = [#"dark" caseInsensitiveCompare:interfaceStyle] == NSOrderedSame;
which works most of the time but has issues in Auto mode on Catalina.
Now from what I have read is that the more robust approach is to check the effectiveAppearance of NSApplication which looks like this:
NSApplication *app = [NSApplication sharedApplication];
NSAppearance *appearance = app.effectiveAppearance;
NSAppearanceName appearanceName = [appearance bestMatchFromAppearancesWithNames:#[NSAppearanceNameAqua, NSAppearanceNameDarkAqua]];
BOOL isDark = [appearanceName isEqualToString:NSAppearanceNameDarkAqua];
The problem with this approach is that the application I am writing this for manually sets its appearance property, which prevents the effectiveAppearance from using the system appearance.
I tried settings app.appearance = nil before checking the effectiveAppearance but it didn't help.
Now there also is [NSAppearance currentAppearance] which uses the appearance of the current thread. I'm not quite sure what this value resolves to if the thread hasn't set the value explicitly.
My big problem here is that I have no access to a machine running macOS to check my code, so I would highly appreciate if someone knows what to do here.
Edit: It looks like the issue is that the library isn’t compile against the correct version of the SDK. Or at least that version isn’t written to the library information.
From the documentation:
If you build your app against an earlier SDK but still want to support Dark Mode, include the NSRequiresAquaSystemAppearance key (with a value of NO) in your app's Info.plist file. Do so only if your app's appearance looks correct when running in macOS 10.14 and later with Dark Mode enabled.
I am already specifying the version through -mmacosx-version-min=10.14. From what I have found this issue is basically the same that I have, but I don’t quite understand what the solution is from the commit.
I guess it has something to do with the -isysroot and -platform_version. But I didn’t find any good reference for what they do and how they work.
My updated question would be:
How do -isysroot and -platform_version work and how do I use them to enable SDK specific functionality with my binaries?
The solution is quite simple. When manually compiling from the command line -mmacosx-version-min=10.14 needs to get passed to the compiler and the linker.

Some Parse methods not working in iOS SDK

I added the Parse SDK today (1.2.15) to an existing project which targets iOS7 and is built in Xcode5. I followed the instructions on https://parse.com/apps/quickstart#ios/native/existing exactly. Some things work, like creating and saving a PFObject. Certain functions however cannot be found by the compiler. For instance [PFUser enableAutomaticUser]; generates the error
AppDelegate.m:21:13: No known class method for selector 'enableAutomaticUser'
and [PFAnalytics trackAppOpenedWithLaunchOptions:launchOptions]; generates the error
AppDelegate.m:20:6: Use of undeclared identifier 'PFAnalytics'
Are the docs out of date and have these methods moved? I have tried restarting Xcode and cleaning my project. I can see the PFAnalytics.h file if I expand Parse.Framework in Xcode, and when I look at PFUser.h I can see a declaration of enableAutomaticUser;. Why can Xcode see some Parse classes and methods but not others?
My problem was that Framework Search Paths in Build Settings contained two directories, and one was invalid, resulting in this very strange behavior where some methods in Parse worked and others didn't.

Mobclix implementation methods conflict Xcode 4.5

Im implementing Mobclix in my app but got 2 method conflict warnings:
instance method 'mcScanCStyleComment:' in category from /Users/user/MyFolder/Myapp/Mobclix SDK/libMobclix.a(MobclixController.o) conflicts with same method from another category
instance method 'mcScanCPlusPlusStyleComment:' in category from /Users/user/Myfolder/Myapp/Mobclix SDK/libMobclix.a(MobclixController.o) conflicts with same method from another category
The app is running OK on simulator despite the warnings, but shows no test ads.
Any idea how to get rid of these warnings and show the ads?
Im using XCode 4.5.
Just heard back from Mobclix support. The warnings are apparently a known issue, and they recommend ignoring this issue until their next release.
As far as the ads not showing, I had the same problem until they pointed out that the size of ads weren't available for the device I was using. (Was trying to use the 320x50 ads on iPad, which they deprecated. They're using 468x60 ads now).

Weak linking popoverBackgroundViewClass to make it work in <5.0 IOS

Already checked this question: Weak linking UIPopoverBackgroundView
and already read: http://www.marco.org/2010/11/22/supporting-older-versions-of-ios-while-using-new-apis#fnref:1
I have a custom PopoverBackgroundView declared in a .h and implemented in a .m file. Then, in just one file, I instantiate it like this
self.settingsPopover.popoverBackgroundViewClass = [CustomPopoverBackgroundView class];
I´ve tried doing it like marco says in the link above:
if ([UIPopoverBackgroundView class] != nil) {
self.settingsPopover.popoverBackgroundViewClass = [CustomPopoverBackgroundView class];
}
But I get the same launch error when I run in a 4.3 ipad simulator
dyld: Symbol not found: _OBJC_CLASS_$_UIPopoverBackgroundView
My base sdk is IOS 5.1, and my target deployment is 5.1 as well. Im using LLVM compiler 4.0.
Any ideas? Thanks a lot!
Have you tried using respondsToSelector with the relevant UIPopoverController setBackgroundViewClass method? Remember that properties automatically generate setter and getter methods that you can use in addition to the normal property syntax.
The reason why you're still getting linker errors is because you're still trying to call a method on that class, which doesn't exist.
If it's a case that the entire class doesn't exist, Apple recommends using NSClassFromString(#"UIPopoverController") and checking if the returned result is nil.

iOS 5 TableView crashes

Something got changed at the new SDK and my code suddenly isn't working.
I created a new empty project and created only a UITableView in it.
I used the same code as i've been used to, except the compiler said that i do not need to use autorelease anymore, so i removed it.
Oh, and I replaced retain with strong as i was recommended.
When I run the app it shows the TableView like it should look, but the minute i touch anywhere on screen, like scrolling for example, it crashes with EXC_BAD_ACCESS error.
What do I miss??
You should post some more informations on where your program crashed! But I don't think the mentioned compiler warnings are the reason. You should have tried to run your project with the compiler by turning of ARC (automatic reference count) and see what happens. If you can go back, do that first.
Also maybe there went something wrong with the changes you made because of ARC . If you have not done the changes with the Xcode refactoring tool I recommend you doing so.
Therefor select in the Xcode Menu:
Edit > Refactor > Convert to Objectiv-C ARC...
It will go through your code and apply the changes. Apple recommends though that your project should work without crashes and warnings before using it.