I created a Objective C framework which i want to use in Swift Project. I want to expose only one header file in the framework.Following is my header file
//
// VideoPlayer.h
// DRMFrameworkObjc
//
// Created by Next on 01/08/17.
// Copyright © 2017 Next. All rights reserved.
//
#import <Foundation/Foundation.h>
#import "Streaming.h"
#import "LicenseManager.h"
#import <widevine_cdm_sdk_insecure_dev_sim/DashToHlsApiAVFramework.h>
#import <AVKit/AVKit.h>
#import <AVFoundation/AVFoundation.h>
#interface VideoPlayer : NSObject<StreamingDelegate>
#property(nonatomic) Streaming* streaming;
#property(nonatomic) AVPlayer* player;
#property(nonatomic) AVURLAsset* asset;
#property(nonatomic) NSArray* assetKeysRequiredToPlay;
#property(nonatomic) AVPlayerItem* playerItem;
-(void)initWithURl:(NSURL*)url playerInstance:(AVPlayer*)player controllerInstance:(UIViewController*) controller;
-(void)setupStreaming:(NSURL*)url controllerInstance:(UIViewController*) controller;
-(void)streamingReady:(NSNotification*)notification;
#end
So i added this header in the Umbrella header as below:
//
// DRMFrameworkObjc.h
// DRMFrameworkObjc
//
// Created by Next on 01/08/17.
// Copyright © 2017 Next. All rights reserved.
//
#import <UIKit/UIKit.h>
//! Project version number for DRMFrameworkObjc.
FOUNDATION_EXPORT double DRMFrameworkObjcVersionNumber;
//! Project version string for DRMFrameworkObjc.
FOUNDATION_EXPORT const unsigned char DRMFrameworkObjcVersionString[];
// In this header, you should import all the public headers of your framework using statements like #import <DRMFrameworkObjc/PublicHeader.h>
#import <DRMFrameworkObjc/VideoPlayer.h>
When i add this framework to Swift project I was getting "Could not build Objective C framework ..." and other error is "Streaming.h file not found..". I added the VideoPlayer.h file in bridging header. Why am i getting Streaming.h not found when i don't want it to expose? Is my method of creating Objective C framework wrong? Where am i wrong?
Related
Trying to get ObjC app project to call Swift function within ObjC static lib..........
My ObjC app project build gets build error for reference to a Swift function that is within an ObjC static lib (.a) that is imported into the app project.
The file Hub_lib-Bridging-Header.h has no code.
OBJ-C APP PROJECT..............................................
ViewController.mm within the ObjC app project...
#import "ViewController.h"
#import "Hub_lib.h"
#import "Hub_lib-Swift.h"
#import "hublib.hpp"
#interface ViewController ()
#end
#implementation ViewController
. . .
- (IBAction)run_simple_central:(id)sender {
[self BLE.start_central];
}
BLE.h within ObjC app project...........
#import <CoreBluetooth/CoreBluetooth.h>
#import "Hub_lib-Swift.h"
#interface BLE: NSObject
//< CBPeripheralManagerDelegate >
#property(strong, nonatomic) CBPeripheralManager* peripheralManager;
#property(strong, nonatomic) CBMutableCharacteristic* transferCharacteristic;
#property(strong, nonatomic) NSData* dataToSend;
#property(nonatomic, readwrite) NSInteger sendDataIndex;
-(void)start_central;
#end /* BLE_h */
BLE.m within app; a wrapper for call to swift..........................
#import "BLE.h"
#import "Hub_lib-Swift.h"
#interface BLE ()
#end
#implementation BLE
-(void)start_central
{
Hub_lib* BLE_central = [Hub_lib new];
[BLE_central centralManager.run_central];
}
made a test project to be able to replicate your errors.
You are close but you need to take care of how your static lib has its internal methods and classes exposed in its header so you can use them elsewhere.
let's begin with the Objective-C Static Library project. Hub_lib.h
#import <Foundation/Foundation.h>
// we want the lib header as clean as possible
// it will then be imported in your project with '#import <Hub_lib/Hub_lib.h>'
// auto-generated swift -> objc bridging header imported here will
// mess it up when imported somewhere else.
// so when using swift->objc bridging place next line in .m file instead
//#import "Hub_lib-Swift.h"
//#class BLE_Central; // pre-declaration of a later fully declared Class.
// as we moved the property into .m file we dont need it here.
#interface Hub_lib : NSObject
// to make this work you would need pre-declaration of BLE_Central, see above interface
//#property BLE_Central *ble; // placed in .m interface extension instead.
-(void)run_central;
#end
static lib counterpart / implementation Hub_lib.m
#import "Hub_lib.h"
#import "Hub_lib-Swift.h"
#interface Hub_lib ()
#property BLE_Central *ble_central;
#end;
#implementation Hub_lib
-(instancetype)init {
if (!(self=[super init])) return nil;
_ble_central = [[BLE_Central alloc] init];
return self;
}
-(void)run_central {
[_ble_central run_central];
}
#end
notice BLE_Central property is placed in the class interface extension and when you want to use swift module stuff that exposes back to objc you need to declare the auto-generated bridge somewhere (best done in .m file #import "Hub_lib-Swift.h")
your BLE_central.swift with its protocol method implementation
import Foundation
import UIKit
import CoreBluetooth
import os
var centralManager: CBCentralManager = CBCentralManager()
class BLE_Central: NSObject, CBCentralManagerDelegate, CBPeripheralDelegate {
func centralManagerDidUpdateState(_ central: CBCentralManager) {
os_log("centralManagerDidUpdateState")
}
var discoveredPeripheral: CBPeripheral?
var transferCharacteristic: CBCharacteristic?
var writeIterationsComplete = 0
var connectionIterationsComplete = 0
let defaultIterations = 5 // change this value based on test usecase
var data = Data()
// as you figured out before we need to expose to #objc
#objc public func run_central()
{
os_log("run_central")
// out-commented for testing purposes
//mobile_sys_hub_lib.centralManager = CBCentralManager(delegate: self, queue: nil, options: [CBCentralManagerOptionShowPowerAlertKey: true])
os_log("Scanning started")
}
}
As long no extra code from objc is used in swift inside the static lib, the
Hub_lib-Bridging-Header.h is empty
//
// Use this file to import your target's public headers that you would like to expose to Swift.
//
Next let's see how to import your static lib in your "sim backend UI" Objective-C Project app.
Goto "sim backend UI" App Target settings > General > Framework, Libraries, and.. > hit the + button and search for your compiled libHub_lib.a file. > select it > hit ok. Should be very much in your framework list by now.
Yes, thats not enough! You have to declare its header in your app project somewhere. Where exactly is up to you. Instead of implementing it multiple times we do the following in BLE.h
#import <Foundation/Foundation.h>
#import <CoreBluetooth/CoreBluetooth.h>
//#import "Hub_lib-Swift.h" // no no no no
#import <Hub_lib/Hub_lib.h> // much better. test-compile once if it is crying
NS_ASSUME_NONNULL_BEGIN
#interface BLE: NSObject
// <CBPeripheralManagerDelegate> // "//<Protocol>" will confuse doxygen
#property (strong, nonatomic) CBPeripheralManager* peripheralManager;
#property (strong, nonatomic) CBMutableCharacteristic* transferCharacteristic;
#property (strong, nonatomic) NSData* dataToSend;
#property (nonatomic, readwrite) NSInteger sendDataIndex;
-(void)start_central;
#end /* BLE_h */
NS_ASSUME_NONNULL_END
counterpart BLE.m
#import "BLE.h"
#implementation BLE
-(void)start_central
{
NSLog(#"invoked BLE start_central");
Hub_lib *Hub_central = [Hub_lib new];
[Hub_central run_central];
}
#end
Your ViewController.m or .mm makes use of BLE.h with its already imported static lib header
#import "ViewController.h"
#import "BLE.h"
#interface ViewController ()
#property (nonatomic) BLE *ble;
#end
#implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
UIButton *btn = [UIButton buttonWithType:UIButtonTypeSystem];
btn.frame = CGRectMake(100, 100, 200, 50);
[btn setTitle:#"run simple central" forState:(UIControlStateNormal)];
[btn setTitleColor:UIColor.greenColor forState:(UIControlStateNormal)];
btn.layer.backgroundColor = UIColor.orangeColor.CGColor;
btn.layer.cornerRadius = 5.0f;
[self.view addSubview:btn];
[btn addTarget:self action:#selector(run_simple_central:) forControlEvents:(UIControlEventTouchUpInside)];
}
- (IBAction)run_simple_central:(id)sender {
// BLE needs to be allocated to take effect.
if (!_ble) _ble = [[BLE alloc] init];
// testing.. should log "run_central" + "Scanning started"
[self.ble start_central];
}
#end
Made a testButton so you can see if the implementation invokes what you expect. Compile!
And? Aoutsch! Does not work. What happened?
If your App is a plain Objective-C project it doesn't know about swift yet and will complain in a weirdo way, possibly via something like
Link: Could not find or use auto-linked library 'swiftCoreImage'
Undefined symbol: value witness table for Builtin.UnknownObject*
Solution: Most easy way is to create a swift file in your app project and allow Xcode to make a bridging header for you. (Alternatively change project settings, search for "bridge" and go step by step thru the properties)
The swift file does not have to have special content.
//
// MakeProjectSwiftCompatible.swift
//
import Foundation
Compile again. now it should work because the partly implemented swift module from within your static lib can properly work when your Objc-App-Project is able to work with swift stuff.
Edit as you asked to work with Objective-C++/C++ in your static library things change a little bit.. so here some additional example code to proof it.
In Hub_lib project (targeting your "framework") add some files which will keep some random testing c++ code
//HubCPP.h
#import <Foundation/Foundation.h>
#include <vector>
NS_ASSUME_NONNULL_BEGIN
class SomeCPPClass
{
public:
SomeCPPClass(id<NSObject> obj, size_t size);
~SomeCPPClass();
id<NSObject> getBuffer() { return buffers[bufferIdx]; }
unsigned int getCurrentIdx();
private:
std::vector <id <NSObject>> buffers;
unsigned int bufferIdx;
bool isReady;
};
NS_ASSUME_NONNULL_END
To make Xcode know that you work with C++ you need to have implementation file ending with .mm and also need to change HubCpp.h "Identity and Type (right Xcode panel while file selected)" to C++ Header
// HubCpp.mm
#import "HubCPP.h"
SomeCPPClass::SomeCPPClass (id<NSObject> obj, size_t size) :
bufferIdx (0),
isReady(false)
{
uint8_t ringSize = 255;
assert (ringSize > 0);
for (uint8_t i = 0; i < ringSize; i++)
{
//buffers.push_back ();
bufferIdx = (unsigned int)size;
}
}
SomeCPPClass::~SomeCPPClass() {
// cleanup allocated stuff here.
}
unsigned int SomeCPPClass::getCurrentIdx() {
return bufferIdx;
}
Rename Hub_lib.m to .mm and change its import rules accordingly to the following ..
#import "Hub_lib.h"
#import <CoreBluetooth/CoreBluetooth.h> //needed because the -Swift.h bridge will cry in the next line
#import "Hub_lib-Swift.h"
#import "HubCPP.h"
lets change the proofing method in Hub_lib.mm so it really uses C++
-(void)run_central {
[_ble_central run_central];
SomeCPPClass *cpp = new SomeCPPClass(#"justSomeNSStringObject",2);
unsigned int idx = cpp->getCurrentIdx();
NSLog(#"objectiveCplusplus testIdx = %u", idx);
}
Compile Hub_lib (scheme). It should work by now and also accept the use of #import <vector>.
If this works go on and change your Objc-Project-App.
Switch your compile Scheme to target your Objc-App.
Change file name BLE.m to BLE.mm (makes it a Objective C++ Source)
Change file name BLE.h to BLE.hh (makes it a C++ header)
Change in BLE.mm #import "BLE.h to #import "BLE.hh
in ViewController.m kick out the line #import "BLE.h" and replace it into ViewController.h instead as #import "BLE.hh"
(In general its much easier to keep your compiler informed what language to expect in implementation when you place import headers in header files.)
Compile. Thats it! Your Objective-C++ static lib should properly work at this point.
Edit
You can find a ready made workspace for Xcode here...github: combine cpp swift and objective-c in static lib
Solution from StackO user: Asperi
Emptied top folder
Created workspace at top folder
1.1 Copied clean app and lib to top folder
Add ObjC lib .xcodeproj to workspace using Xcode > File > Add files ...
Add ObjC app .xcodeproj to workspace
Added dependency of sim_backend_UI to lib via workspace
a. app proj > General tab > Frameworks, Libs.. > +
b. Select lib .a
c. Add.
Add Some.swift (any swift file you want) to sim_backend_UI, just for the purpose Xcode add required system swift dynamic libraries (which will be needed for swift part in static library as well)... and confirm creating bridge in appeared dialog
a. new file > Swift > Some.swift
b. Create Bridging Header
c. Added to Some.swift ...
import Foundation
struct Some{}
Set Xcode active scheme to app and target device
Build
"succeeded"
Setup:
react-native v0.41.2
react-native-cli v2.0.1
xcode v8.2.1
node v6.9.5
I started using RN v0.41.2 and found that v0.40 introduced a namespace breaking change stating that all react imports should be prepended with React/.
But the documentation shows otherwise.
So, is doing this the only thing that I have to do:
// RNLib.h
#import "RCTBridgeModule.h"
#interface RNLib : NSObject <RCTBridgeModule>
#end
to
// RNLib.h
#import <React/RCTBridgeModule.h>
#interface RNLib : NSObject <RCTBridgeModule>
#end
Or do I have to do it for my imports as well:
// RNLib.m
#import "RNLib.h"
#implementation RNLib
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(helloWorld:(NSString *)world)
{
return [NSString stringWithFormat:#"hello %#", world];
}
#end
to
// RNLib.m
#import <React/RNLib.h>
#implementation RNLib
RCT_EXPORT_MODULE();
RCT_EXPORT_METHOD(helloWorld:(NSString *)world)
{
return [NSString stringWithFormat:#"hello %#", world];
}
#end
I'm currently unable to create a library and link it correctly (I've tried multiple things).
// somthing.m
#import "something.h"
This above line refers to something.h file which is present in same directory of the implementation file.
Only Modules from the React should be prepended with "React/RCTWhatever.h".
This has effective change in Header Search Paths of Xcode when you are linking the Native Libraries.
Thanks
I'm trying to use the SPUserResizableView created by Spoletto in github (https://github.com/spoletto/SPUserResizableView).
I imported the .h and .m files, created a bridge and added the delegates to my controller.
I think problem is that problem is that the library is very old and that's why I get many errors in the .h and .m files so I can't use the library.
Errors - http://postimg.org/gallery/3bq2ldo0m/
Can you help me setup the library in swift?
I also got the same error, Just add these two in SPUserResizableView.h
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
Your problem will be resolved.
You need to set up an Objective-C bridging header and then import it in there. To do this:
Drag and drop the .h and .m SPUserResizableView files into your project.
When Xcode asks if you want to create a bridging header, select 'Yes'.
Type in the new file called 'YOUR-PROJECT-NAME-bridging-header.h' this code:
#import SPUserResizableView.h
You should now be able to use it in Swift!
I got this working with Swift 4 by moving the variable declarations from the interface to the implementation, and removing the release and dealloc code.
SPUserResizableView.h changed to
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
typedef struct SPUserResizableViewAnchorPoint {
CGFloat adjustsX;
CGFloat adjustsY;
CGFloat adjustsH;
CGFloat adjustsW;
} SPUserResizableViewAnchorPoint;
#protocol SPUserResizableViewDelegate;
#class SPGripViewBorderView;
#interface SPUserResizableView : UIView {
}
//...
//(identical from this point on)
SPUserResizableView.m changed to
//...
//(identical up to)
//CGColorSpaceRelease(baseSpace), baseSpace = NULL;
CGColorSpaceRelease(baseSpace);
baseSpace = NULL;
#implementation SPUserResizableView
SPGripViewBorderView *borderView;
UIView *contentView;
CGPoint touchStart;
CGFloat minWidth;
CGFloat minHeight;
// Used to determine which components of the bounds we'll be modifying, based upon where the user's touch started.
SPUserResizableViewAnchorPoint anchorPoint;
id <SPUserResizableViewDelegate> delegate;
//#synthesize contentView, minWidth, minHeight, preventsPositionOutsideSuperview, delegate;
//...
//(this part identical)
- (void)dealloc {
[contentView removeFromSuperview];
}
#end
I would like some help with integrating interstitial ads from Applovin using Swift. Currently, I have managed to successfully integrate the SDK and initialize it using ALSdk.initializeSdk(). I have a folder in my project directory called Applovin which contains: headers folder (with all the .h files inside) and libApplovinSdk.a.
I have a BridgingHeader.h file in which I am importing the relevant frameworks
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <Chartboost/Chartboost.h>
#import <Chartboost/CBNewsfeed.h>
#import <CommonCrypto/CommonDigest.h>
#import <AdSupport/AdSupport.h>
#import <AVFoundation/AVFoundation.h>
#import<CoreTelephony/CTCallCenter.h>
#import<CoreTelephony/CTCall.h>
#import<CoreTelephony/CTCarrier.h>
#import<CoreTelephony/CTTelephonyNetworkInfo.h>
#import <CoreGraphics/CoreGraphics.h>
#import <CoreMedia/CoreMedia.h>
#import <MediaPlayer/MediaPlayer.h>
#import <SystemConfiguration/SystemConfiguration.h>
// Core SDK
#import "ALErrorCodes.h"
#import "ALSdk.h"
#import "ALSdkSettings.h"
#import "ALTargetingData.h"
#import "ALPostbackService.h"
#import "ALPostbackDelegate.h"
// Standard Ads
#import "ALAd.h"
#import "ALAdDisplayDelegate.h"
#import "ALAdLoadDelegate.h"
#import "ALAdRewardDelegate.h"
#import "ALAdService.h"
#import "ALAdSize.h"
#import "ALAdType.h"
#import "ALAdUpdateDelegate.h"
#import "ALAdVideoPlaybackDelegate.h"
#import "ALAdView.h"
#import "ALIncentivizedInterstitialAd.h"
#import "ALInterstitialAd.h"
// Native Ads
#import "ALNativeAd.h"
#import "ALNativeAdService.h"
#import "ALNativeAdPrecacheDelegate.h"
#import "ALNativeAdLoadDelegate.h"
In my AppDelegate i have the following methods, what do I need to put inside these methods?
func adService(adService: ALAdService, didLoadAd ad: ALAd) {
}
func adService(adService: ALAdService, didFailToLoadAdWithError code: Int32) {
}
I am attempting to show ads using the following code but ALInterstitialAd.isReadyForDisplay() is always false, I am probably missing something very obvious but I am not sure what it is, any help is appreciated, thanks!
if ALInterstitialAd.isReadyForDisplay() == true {
ALInterstitialAd.show()
} else {
println("No Applovin Ad available to show")
}
You likely need to enable "Test Mode" for your app in the AppLovin dashboard in order to force test ads to serve for your area. Please send any questions to support#applovin.com for further assistance.
Trying to use AFNetworkings ReachabilityStatusChanged but getting
"No visible #interface for HTTPCLIENT declares the selector setReachabilityStatusChangeBlock"
But HttpClient has that function. Anyone know why this is happening?
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:#"http://stat-api.herokuapp.com/"]];
[client setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status){
NSLog(#"%d", status);
}];
/// UPDATE ///////////
Here is my .pch file
#ifdef __OBJC__
#import <UIKit/UIKit.h>
#import <Foundation/Foundation.h>
#import <CoreData/CoreData.h>
#import "NSDate+Helper.h"
#import "NSEntityDescription+RKAdditions.h"
#import "UIAlertView+MKBlockAdditions.h"
#import "UIActionSheet+MKBlockAdditions.h"
#import "MKBlockAdditions.h"
#import "NSObject+MKBlockAdditions.h"
#import "NSString+Extra.h"
#import "UIView+Additions.h"
#import "ObjectiveSugar.h"
#import "NSNotificationCenter+UniqueNotif.h"
#import "STUIColor+Custom.h"
#import "NSObject+STNSObjectAdditions.h"
#import "UIView+Gradientcy.h"
#import "NSString+USStateMap.h"
#import "STUITextField.h"
#import "UIImage+UIImageCrop.h"
#import "UIBorderLabel.h"
#import <SystemConfiguration/SystemConfiguration.h>
#endif
Move
#import <SystemConfiguration/SystemConfiguration.h>
right after this line:
#ifdef __OBJC__
Are you sure you're using a version of AFNetworking that have this method?
Also, check this warning from the docs:
Warning: This method requires the SystemConfiguration framework.
Add it in the active target’s “Link Binary With Library” build phase, and add #import <SystemConfiguration/SystemConfiguration.h> to the header prefix of the project (Prefix.pch).