`[[NSBundle mainBundle] bundleIdentifier]` is nil when running XCTest - xctest

Even when it is defined in the "...Tests" target Info.plist, the identifier remains nil. I need it to have a valid value for a third party lib.

This is because unit tests don't load your application bundle or even the unit test bundle as the main bundle.
For more info on this see
NSURL to file path in test bundle with XCTest
XCTest fails when calling [NSBundle mainBundle]
Now we can hack around this by including a category on NSBundle in your unit test project. The Objective-C category hack also works for swift unit tests because Bundle is bridged to NSBundle, just make sure you have a bridged header for your unit test project.
You can then have it search for the correct main bundle, but if you just want a quick and dirty way to have a valid bundle identifier then use the following
#interface NSBundle (BundleIdentifier)
-(NSString *)bundleIdentifier;
#end
#implementation NSBundle (BundleIdentifier)
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wobjc-protocol-method-implementation"
-(NSString *)bundleIdentifier
{
return #"com.yourcompany.yourapp.unitTests";
}
#pragma clang diagnostic pop
#end
Now all that is left is to include the header file in your unit test so that the category loads up.

Related

Disable diagnostics for framework defining a module

I recently updated an existing framework wrapping a C library to define a module (DEFINES_MODULE = YES in Xcode Build Settings).
The library isn't written by me so I'd like to avoid making changes if at all possible. Some of the library headers contain a few small errors, typically in the documentation. For example:
/**
* A function that does something.
* \param handle An object handle
* \param parameter A parameter value
* \return A status code
*/
int some_function(void *handle, double value);
When compiling the framework the compiler emits a warning:
Parameter 'parameter' not found in the function declaration
When using the framework from Objective-C, before compiling the framework as a module, I could disable diagnostics selectively at the site of the include:
#import <framework/header.h> // Generates a warning similar to the one above
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation"
#import <framework/header.h> // Warning is suppressed
#pragma clang diagnostic pop
When the framework defines a module there seems to be no way to disable diagnostics, whether the framework is imported as a module or not:
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation"
#import framework; // Generates a warning
#pragma clang diagnostic pop
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wdocumentation"
#import <framework/header.h> // Generates a warning as well
#pragma clang diagnostic pop
Is there a non-global way to suppress warnings when importing frameworks that define modules?

Programatically checking for NSBundle in macOS

I am building my application for macOS using CMake. My application can either be MACOSX_BUNDLE i.e. generated as a .app through CMake or it can even be a Unix-style executable.
Is there a programmatic way in Obj-C to check if the executable is Unix-Style or NSBundle?
Assuming you use Foundation and Objective-C in both binaries it is possible to check using NSBundle properties, because bundle instance itself will created on both cases (it just references to folder around executing binary), but bundle info will be present only on macOS.
So here is possible approach:
if (nil != [[NSBundle mainBundle] bundleIdentifier]) {
// macOS code here
} else {
// linux code here
}

Objective-C Class Not Found In Swift Bridging Header

I am updating our Cordova framework and I am stuck on getting a particular Objective-C plugin class to work.
In my old (un-updated) project everything works just fine. I have a BridgingHeader.h file, its properly referenced in the build settings. However in my new updated project it can no longer find only one Objective-C class (PushPlugin.m).
What's strange is its finding all other Objective-C classes just fine, its just the PushPlugin.m it can't find.
Here is my BridgingHeader:
#import <Cordova/CDV.h>
#import <objc/runtime.h>
#import <Parse/PFObject.h>
#import <Parse/PFSubclassing.h>
#import <Parse/Parse.h>
#import <objc/message.h>
#import "GPUImage.h"
#import "PushPlugin.h" // This one is not found
#import "CDVParsePlugin.h"
And when I try to use PushPlugin I get not found error:
//AppDelegate.swift
let pushHander:PushPlugin = getCommandInstance("PushPlugin") as! PushPlugin
// ERROR: PushPlugin not found
To be extra certain, the PushPlugin file is referenced in the Compile Sources. And my BridgingHeader is properly referenced in the build settings.
Do you have any idea why one specific Objective-C class is not being found?
Update
So to be clear, there is no error reporting the BridgingHeader file. Its only when I try to use the PushPlugin that I encounter the error (meaning its not importing properly).
As suggested I ran a commandline build I got a build failed with these reasons:
** BUILD FAILED **
The following build commands failed: CompileSwift normal arm64
/Users/user/Desktop/mobile-cordova-upgrade/app/platforms/ios/App/Classes/AppDelegate.swift
CompileSwiftSources normal arm64 com.apple.xcode.tools.swift.compiler
(2 failures)

Apple Mach-O Linker Error when Run simulator with Facebook SDK

I have added Facebook SDK Framework into my Xcode 6.
Then I import it to my AppDelegate.h file.
Then I put this code [FBLoginView class]; into this function
(BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
And when I clicked on Run Simulator I get this:
I'm a newbie and so confuse about what the error is. Please give me solutions.
This error usually occurs either when you don't have the correct frameworks (might be missing one) or when you don't have the right thing in linker flags.
Go to the main page for the app (on the navigation thing on the left click on your apps name or the top section) -> Build Settings and under Linker Flags, make sure there is nothing in your Other Linker Flags. I had this same error when I had -ObjC in my other Linker Flags.
Good luck

Unit Test build failing when importing MagicalRecord

I have a project setup using the UnitTest template provided by Apple. Too I added MagicalRecord to Prefix header. When I am running on the device and Simulator everything is working fine.
Except the Unit Tests, when I am compiling for the unit tests the build failed with the following command: 'CoreData+MagicalRecord.h' file not found . This happens in the prefix header.
prefix.pch
//
// Prefix header for all source files of the '123tv' target in the '123tv' project
//
#import <Availability.h>
#ifndef __IPHONE_3_0
#warning "This project uses features only available in iOS SDK 3.0 and later."
#endif
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import "Environments.h"
#import "CoreData+MagicalRecord.h"
#import "PBLog.h"
#endif
Has anyone an idea?
Make sure that the Header Search Paths is set up correctly for your test target.
I generally use CocoaPods which will automate this stuff for you
Try to run command (1) in terminal, then add import in step (2)
In your project directory
run pod update
You should now be able to add
#import <MagicalRecord/CoreData+MagicalRecord.h>
to any of your target's source files and begin using MagicalRecord!