I'm trying to create an ObjC application that will control iTunes. I need a method that will return an array of all the playlists in iTunes.
I'm getting the most bizarre, unhelpful error message ever... First the code:
#import "MusicControl.h"
#import "iTunes.h"
#implementation MusicControl
- (SBElementArray *) playlists {
// Create iTunes Object
iTunesApplication *iTunes = [SBApplication applicationWithBundleIdentifier:#"com.apple.iTunes"];
NSArray *sources = [iTunes sources];
iTunesSource *librarySource = nil;
for (iTunesSource *source in sources) {
if ([source kind] == iTunesESrcLibrary) {
librarySource = source;
break;
}
}
return [librarySource userPlaylists];
}
#end
I have no idea whether the array return is working or not because, after doing some debugging, I found that where this is bombing out is the very first line where I create the iTunes object, which was copied and pasted from Apple's website...
The error I'm getting is:
Undefined symbols for architecture x86_64:
"_OBJC_CLASS_$_SBApplication", referenced from:
objc-class-ref in MusicControl.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
Any suggestion as the what the heck is going on?
This message (and similar ones) means that the linker is looking for some specific symbol, but can't find it. In your case it is SBApplication.
If you have not already done so, you should make sure that you have linked to the ScriptingBridge framework.
To add a framework, click on the project's icon at the top of the left hand bar in Xcode, then select Build Phases. If Link With Binary Libraries is not already expanded, do that and add the framework.
The same procedure can be used for plain libraries (a framework is really just a wrapper around a library, at least for the purpose of this discussion).
Related
I have a simple "Hello world" type program in Xcode and I'm trying to use an external library in that, but I'm getting compilation errors. The library is the Magtek edynamo macOS sdk:
https://www.magtek.com/Content/SoftwarePackages/1000004036.zip
(parent page is https://www.magtek.com/support/edynamo?tab=software; download is the macOS SCRA SDK)
This is my code:
#import "MTSCRA.h"
int main (int argc, const char * argv[])
{
MTSCRA* mtSCRALib = [[MTSCRA alloc] init];
return 0;
}
So basically I'm just importing the library and trying to instantiate one of its classes. Xcode doesn't show any inline compile errors anywhere, but when I try to build and run, it results in a variety of undefined symbol errors such as this:
Undefined symbols for architecture x86_64:
"_NSApplicationWillTerminateNotification", referenced from:
-[HIDManager init] in libMTSCRAOSX.a(HIDManager.o)
and warnings such as this:
ld: warning: object file (/path/HelloWorld/libMTSCRAOSX.a(MTSCRA.o)) was built for newer OSX version (10.12) than being linked (10.11)
(If I comment out the MTSCRA* mtSCRALib = [[MTSCRA alloc] init]; line, it runs fine.)
These are the steps I took to include the library in my Xcode project:
I dropped the MTSCRA.h and libMTSCRAOSX.a into my project directory.
From Build phases -> Link binary, I added libMTSCRAOSX.a.
Build Settings -> Library search paths is set to "$(inherited)" and "$(PROJECT_DIR)/HelloWorld"
This is my environment:
Macbook Pro 64-bit
OSX El Capitan 10.11.5
Xcode V8.2.1
Tried all the google solutions; nothing worked. Any help...can anyone else successfully import and use this library?
Solved this. Not sure if these are rookie mistakes, but I had two issues:
1) I also needed to include the library /Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX.sdk/usr/lib/libstdc++.6.0.9.tbd
2) I also had to import #import <Cocoa/Cocoa.h>. So:
#import "MTSCRA.h"
#import <Cocoa/Cocoa.h>
int main (int argc, const char * argv[])
{
MTSCRA* mtSCRALib = [[MTSCRA alloc] init];
return 0;
}
I have an Objective-C iOS app that is composed of a workspace (AuthPort.xcworkspace) with a project (AuthPort.xcodeproj) and an Objective-C SDK project ("ANet SDK.xcodeproj") which builds a library called “libAnet SDK.a”).
“libAnet SDK.a” is linked in with the AuthPort target Build Phases.
In the SDK, there are some categories on NSString which get built into “libAnet SDK.a”. They are named:
NSString+stringWithXMLTag.h and NSString+stringWithXMLTag.m
.
.
.
etc.
Some code in the AuthPort.xcodeproj calls code in the library which in turn calls these category methods.
It all works smoothly in the above Objective-C environment!
Now…I am re-writing the AuthPort code in Swift in a new workspace with a new project and also using the Objective-C SDK which builds “libAnet SDK.a”
So, I created a new Swift Xcode project called AuthPort.xcodeproj and added it to a new workspace called AuthPort.xcworkspace. I also added the authorize.net SDK ("ANet SDK.xcodeproj", written in Objective-C) to the project.
So far, so good. I created an AuthPort-Bridging-Header.h file and imported all the headers from the SDK (without the category headers - more on this later). I also linked in “libAnet SDK.a” in the Build Phases of the AuthPort target.
AuthPort builds and runs with no errors or warnings.
Now, in viewDidLoad of the primary view controller I added code to access library methods to register a new device with the company, authorize.net:
var r: MobileDeviceRegistrationRequest = MobileDeviceRegistrationRequest()
an.mobileDeviceRegistrationRequest(r)
These two calls are the same library methods in both Objective-C and Swift versions. The last method calls other library methods which call methods from the NSString category above.
When I put breakpoints in a category method in the Objective-C environment (all Objective-C code in app and library), the program breaks as expected and I can step through the code.
When I put breakpoints in a category method in the Swift environment (Swift app project with Objective-C library), the debugger never enters a category method. At one point in the execution, the app SIGABRT’s with the following:
2015-04-21 12:25:47.388 AuthPort[4743:2404231] +[NSString stringWithXMLTag:andValue:]: unrecognized selector sent to class 0x38450e18
2015-04-21 12:25:47.390 AuthPort[4743:2404231] * Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSString stringWithXMLTag:andValue:]: unrecognized selector sent to class 0x38450e18'
* First throw call stack:
(0x29a0a5a7 0x3792fc77 0x29a0f989 0x29a0d949 0x2993eb68 0xd9e4b 0xc301f 0xdd507 0xc4725 0xc44b1 0xb8f28 0xb9e60 0x2cf0eb65 0x2cf0e8d5 0x2d031c43 0x2d031ac7 0x2d03196b 0x2cf1b5f1 0x2d0357b3 0x2d03491f 0x2cf2433b 0x2cf159e1 0x2cf15003 0x2cf14e6b 0x2cf148ef 0x2cf121ef 0x2cf7c031 0x2d16e34f 0x2d170781 0x2d17b1a9 0x2d16f063 0x302880a1 0x299d125d 0x299d0521 0x299cecbf 0x2991bb51 0x2991b963 0x2cf72b8f 0x2cf6dc91 0xb5290 0x37ed8aaf)
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb)
The [NSString stringWithXMLTag:andValue:] is from the category added by the library onto NSString.
The library method stringOfXMLRequest calls the category method stringWithXMLTag:andValue:
- (NSString *) stringOfXMLRequest {
NSString *s = [NSString stringWithFormat:#""
#"<merchantAuthentication>"
#"%#" //name (optional)
#"%#" //fingerPrint type Object #"%#" //transactionKey or
#"%#" //sessionToken or
#"%#" //password
#"%#" //mobileDeviceId (optional)
#"</merchantAuthentication>",
(self.name ? [NSString stringWithXMLTag:#"name" andValue:self.name] : #""),
(self.fingerPrint ? [self.fingerPrint stringOfXMLRequest] : #""),
(self.transactionKey ? [NSString stringWithXMLTag:#"transactionKey" andValue:self.transactionKey] : #""),
(self.sessionToken ? [NSString stringWithXMLTag:#"sessionToken" andValue:self.sessionToken] : #""),
(self.password ? [NSString stringWithXMLTag:#"password" andValue:self.password] : #""),
(self.mobileDeviceId ? [NSString stringWithXMLTag:#"mobileDeviceId" andValue:self.mobileDeviceId] : #"")];
return s;
}
The SIGABRT doesn't happen until the second call is made to stringWithXMLTag:andValue: for the transitionKey.
The exact same library code is run in both environments.
Here’s the code from stringWithXMLTag:andValue: which is never seen in the debugger:
+ (NSString *)stringWithXMLTag:(NSString *)t andValue:(NSString *)v {
if (v == nil) {
return #"";
}
else {
v = [NSString stringWithEscapedXMLValue:v];
return [NSString stringWithFormat:#"<%#>%#</%#>", t, v, t];
}
}
The problem is solely within the library code where a library method calls another library method which calls a library category method which is never entered in the debugger in the Swift version.
I also tried adding the category header files in the bridging header and adding -ObjC and -all_load to the Other Linker Flags for AuthPort. No luck.
I’ve searched the net for 2 days with no luck. Hopefully one of you will have seen this behavior.
I'm building using Xcode 6.3 and iOS 8.3 (deploying on iOS 8.2).
Thanks.
Check that:
you've added you category to the Umbrella Framework of your Framework project. Use #import "your.h"
I've marked the .h file from the category as public. Select the .h > Identity and Type > Target Membership > Public
In your project, set correct Framework Search Paths
I keep getting this error when I try to build my project which uses reachability (the error only came up after I tried to implement reachability):
I read some other posts on the internet but nothing seemed to work. I added SystemConfiguration.framework (project, build phases, +), but that didn't work (I had already added it when the error came up). Here's how I implement the files:
#import <UIKit/UIKit.h>
#import "Reachability.h"
#interface catalogDetailView : UIViewController{
}
-(void)checkNetwork;
#end
Then in the .m:
#import "catalogDetailView.h"
-(void)checkNetwork{
if ([self reachable]) {
NSLog(#"Connected to Network");
}
else {
NSLog(#"Connection Failed");
}
}
-(BOOL)reachable {
Reachability *r = [Reachability reachabilityWithHostName:#"apple.com"];
NetworkStatus internetStatus = [r currentReachabilityStatus];
if(internetStatus == NotReachable) {
return NO;
}
return YES;
}
So if you could help that would be amazing!! Thanks ;)
Luke
You need to add Reachability.m to your target's "Compile Sources" build phase.
One way to do it:
Select Reachability.m in the project navigator, on the left side of the Xcode window. If you don't see it, choose the menu View > Navigators > Show Project Navigator.
Show the file inspector on the right side of the Xcode window. View > Utilities > Show File Inspector.
In the Target Membership section, check the checkbox next to your target.
I'll bet you that your 'compile sources list' does not contain reachability.m. Drag it in under the build phases tab to the list. I often find that when adding files to a project, Xcode often doesn't add the files your target's compile list (because the default is to not add them).
I'm trying to compile a trivial command-line tool with XCode:
#import <Cocoa/Cocoa.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
//NSSpeechSynthesizer *speeker = [[NSSpeechSynthesizer alloc] initWithVoice: nil];
NSLog(#"%#", [NSSpeechSynthesizer availableVoices]);
NSLog(#"Hello, World!");
[pool drain];
return 0;
}
and even thought I'm importing Cocoa.h, I'm getting a link error:
Undefined symbols:
"_OBJC_CLASS_$_NSSpeechSynthesizer",
referenced from:
objc-class-ref-to-NSSpeechSynthesizer
in byc.o ld: symbol(s) not found
collect2: ld returned 1 exit status
Anybody knows what's going on???
You imported the header, so compilation worked, but linking failed because you didn't link against a framework that provides NSSpeechSynthesizer. You need to link against either the Application Kit framework (in addition to Foundation) or the Cocoa umbrella framework (instead of Foundation).
Whichever framework you choose, add it to your Linked Frameworks group in your project's group tree (by right-clicking on the group and choosing “Add Existing Framework”), and make sure you also add it to your target.
I am working on an extension to Vienna to add the ability for third parties to write Objective-C plugins, but I am getting some runtime linker issues only when running in 64-bit mode (everything appears to work fine in 32-bit mode). My plugin, SynkPlugin, is loaded by the following code in Vienna.app:
NSArray * bundlePaths = [NSBundle pathsForResourcesOfType:#"bundle" inDirectory:[[Preferences standardPreferences] pluginsFolder]];
NSEnumerator * enumerator = [bundlePaths objectEnumerator];
NSString * bundlePath;
NSMutableArray * plugins = [NSMutableArray array];
while ( (bundlePath = [enumerator nextObject]) != nil )
{
NSBundle * pluginBundle = [NSBundle bundleWithPath:bundlePath];
Class principalClass = [pluginBundle principalClass];
id <ViennaPlugin, NSObject> plugin = [[principalClass alloc] init];
[plugins addObject:plugin];
[plugin release];
NSLog(#"Loaded plugin %# [main class: %#]", bundlePath, principalClass);
}
And in the console output, I get the following error message:
2010-07-09 08:55:40.128 Vienna[74065:a0f] Error loading /Users/dcrosta/Library/Application Support/Vienna/PlugIns/SynkPlugin.bundle/Contents/MacOS/SynkPlugin: dlopen(/Users/dcrosta/Library/Application Support/Vienna/PlugIns/SynkPlugin.bundle/Contents/MacOS/SynkPlugin, 265): Symbol not found: _OBJC_CLASS_$_Article
Referenced from: /Users/dcrosta/Library/Application Support/Vienna/PlugIns/SynkPlugin.bundle/Contents/MacOS/SynkPlugin
Expected in: flat namespace
in /Users/dcrosta/Library/Application Support/Vienna/PlugIns/SynkPlugin.bundle/Contents/MacOS/SynkPlugin
This error only happens when running in 64-bit mode, not 32-bit mode. Both Vienna and SynkPlugin are compiled with the "standard 32/64 universal" settings, and SynkPlugin has the additional linker flag "-undefined dynamic_lookup", which, it is my understanding, allows it to link to classes found in Vienna.app without having to compile code for those classes into its own binary.
The other references to this error on Stack Overflow have to do with UIKit differences between iPhone/iPod Touch and iPad -- in those cases, the frameworks are actually missing the classes on iPhone/iPod Touch. In my case, I'm certain that Vienna.app has the Article class within it somewhere, since it is built from identical code to the 32-bit version.
Has anyone seen an error like this before? Have any suggestions on where to look for more information? Thanks.
In the build settings of the Vienna target, under GCC 4.2 - Code Generation uncheck Symbols Hidden by Default (GCC_SYMBOLS_PRIVATE_EXTERN).