Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

How can we use swift instead of objective Objective-C ? #221

Open
kiki-le-singe opened this issue Jan 12, 2020 · 9 comments · May be fixed by #353
Open

How can we use swift instead of objective Objective-C ? #221

kiki-le-singe opened this issue Jan 12, 2020 · 9 comments · May be fixed by #353
Labels
enhancement New feature or request help wanted Extra attention is needed

Comments

@kiki-le-singe
Copy link

Hello !

First, thanks for this project, it's very nice !

I would like to use swift language instead of Objective-C, is it possible to generate a swift example ?

thanks a lot

@brodycj brodycj added enhancement New feature or request help wanted Extra attention is needed labels Jan 30, 2020
@brodycj
Copy link
Owner

brodycj commented Jan 30, 2020

Contribution would be much welcome. This would likely have to be an option in both CLI and the library API, which would be subject to review.

@mateioprea
Copy link

mateioprea commented Feb 6, 2020

Hi,

I managed to use swift like this:

  1. Delete the .h header file in the newly created module (you don't need it if you're using swift only)

  2. I've created a new swift file that defines my class. Create the bridging header when xcode prompts you to do so.

  3. For exporting swift classes use:

@interface RCT_EXTERN_MODULE(DummyModule, NSObject)
RCT_EXTERN_METHOD(dummy) //this is for exporting a swift exposed method
@end
  1. If you want to add a dynamic framework, be sure you're adding it manually by copy/pasting the .framework file into project folder, not via Xcode. After that, add $(PROJECT_DIR) to the Framework Search Paths, in build settings.

  2. If you're using this module with a React Native project that doesn't have any swift files, please be aware that you need to create a bridging header either by creating a dummy swift file and let Xcode create that for you or do it manually.

Let me know if you have any questions.

Edit. This is my podspec file:

require "json"

package = JSON.parse(File.read(File.join(__dir__, "package.json")))

Pod::Spec.new do |s|
  s.name         = "react-native-redacted-sdk"
  s.version      = package["version"]
  s.summary      = package["description"]
  s.description  = <<-DESC
                  react-native-redacted-sdk
                   DESC
  s.homepage     = "https://github.com/redacted/react-native-redacted-sdk"
  s.license      = "MIT"
  # s.license    = { :type => "MIT", :file => "FILE_LICENSE" }
  s.authors      = { "Matei Oprea" => "redacted" }
  s.platforms    = { :ios => "9.0" }
  s.source       = { :git => "https://github.com/redacted/react-native-redacted-sdk.git", :tag => "#{s.version}" }

  s.source_files = "ios/**/*.{h,m,swift}"
  s.vendored_frameworks = 'ios/redacted.framework'
  s.swift_version = '5.0'
  s.requires_arc = true

  s.dependency "React"
  # ...
  # s.dependency "..."
end

@brodycj
Copy link
Owner

brodycj commented Feb 6, 2020

Thanks @mateioprea! I guess I should pick up on Swift programming - someday:)

@kashifaliquazi
Copy link

@mateioprea Greetings,
I am really new to iOS objective c and Swift and trying to pull what you have mentioned in Comments.

I have created my Swift file which looks like this:

`import UIKit
import ARKit

class File: UIViewController, ARSCNViewDelegate, ARSessionDelegate {

var sceneView: ARSCNView!
var session: ARSession!
override func viewDidLoad() {
    super.viewDidLoad()
    
    // Set up scene with content.
    sceneView = ARSCNView();
    sceneView.frame = view.bounds;
    self.view.insertSubview(sceneView, at: 0);
    
    sceneView.delegate = self;
    session.delegate = self;
    //automatically adds lights to a scene
    sceneView.autoenablesDefaultLighting = true;
}

}
`
I have created bridging header as prompted by Xcode but that file is empty do we need to add anythin to it.

Also as of now, we have .h and .m file how will we expose this swift class to React native.(You have mentioned in your comments but it is not very clear from it).

Thanks in advance.

@mateioprea
Copy link

@kashifaliquazi if you're talking about the react native module created using create-react-native-module, try something like this:

Add the following lines to your swift file:

@objc(File)
class File: NSObject {
    
    @objc
    override static func requiresMainQueueSetup() -> Bool {
        return false
    }
    
    @objc func testFn() {
        print("This is a test function")
    }
}

In the .m file in your project add the following lines:

#import "React/RCTBridgeModule.h"
@interface RCT_EXTERN_MODULE(File, NSObject)
RCT_EXTERN_METHOD(testFn)
@end

In the React Native project use:

import React, {Component} from 'react';
import {NativeModules} from 'react-native';
let {File} = NativeModules;

export default class TestComponent extends Component {
	constructor(props) {
		super(props);
	}

	componentDidMount() {
		File.testFn();
	}
}

you should see "This is a test function" logged in either Xcode or React Native console.

@kashifaliquazi
Copy link

@mateioprea Thank you so much for the response.
It worked like a charm.

We are able to call Swift code from React Native, But we are not able to change ViewControler for the Swift Class.
Here is the brief of what we are trying to achieve:
From React Native App get into AR(Augmented Reality) Mode.
We have a separate iOS Project written in Swift which shows some 3d Models in AR Mode using AR kit.

Here is How AppDelegate looks like in actual iOS:

`#import "AppDelegate.h"

#import <React/RCTBridge.h>
#import <React/RCTBundleURLProvider.h>
#import <React/RCTRootView.h>

@implementation AppDelegate

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
    RCTBridge *bridge = [[RCTBridge alloc] initWithDelegate:self launchOptions:launchOptions];
    RCTRootView *rootView = [[RCTRootView alloc] initWithBridge:bridge
    moduleName:@"reactArTest"
    initialProperties:nil];

    rootView.backgroundColor = [[UIColor alloc] initWithRed:1.0f green:1.0f blue:1.0f alpha:1];

    self.window = [[UIWindow alloc] initWithFrame:[UIScreen mainScreen].bounds];
    UIViewController *rootViewController = [UIViewController new];
    rootViewController.view = rootView;
    self.window.rootViewController = rootViewController;
    [self.window makeKeyAndVisible];
    return YES;
    }

  • (void) goToNativeView {
    dispatch_async(dispatch_get_main_queue(), ^{
    UIViewController *vc = [UIStoryboard storyboardWithName:@"Main" bundle:nil].instantiateInitialViewController;
    self.window.rootViewController = vc;
    });
    }

  • (NSURL *)sourceURLForBridge:(RCTBridge *)bridge
    {
    #if DEBUG
    return [[RCTBundleURLProvider sharedSettings] jsBundleURLForBundleRoot:@"index" fallbackResource:nil];
    #else
    return [[NSBundle mainBundle] URLForResource:@"main" withExtension:@"jsbundle"];
    #endif
    }

@end`

When We try to replicate this Code to out react-native-librery(One we created) build fails at

self.window.rootViewController = vc; // This Gives error.

As I am understanding we are not able to reference uiControler than we have in actual acess to
"AppDelegate.m".

We are able to make it work when created Bridge in iOS folder of main React app and adding

  • (void) goToNativeView {
    dispatch_async(dispatch_get_main_queue(), ^{
    UIViewController *vc = [UIStoryboard storyboardWithName:@"Main" bundle:nil].instantiateInitialViewController;
    self.window.rootViewController = vc;
    });
    }

This code in AppDelegate.m file.

Can you tell us what getting wrong here or maybe any other way to go to AR Mode(using AR Kit) from our created React-Native library .

Any help would be much appriciated.

Thanks,

Thanks,

@mateioprea
Copy link

@kashifaliquazi why don't you use https://viromedia.com/viroar ? Its MIT licensed.

@brodycj
Copy link
Owner

brodycj commented May 11, 2020

Support is now in progress, see #353. I hope to finish it in the next 2-4 weeks or so.

@brodycj brodycj unpinned this issue May 19, 2020
@TfADrama
Copy link

TfADrama commented Jun 5, 2020

Hi guys,

I made the exact same steps posted here to have swift files working on the lib, but when i execute the example project i get this error: (On iphone 11 simulator)

Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_File", referenced from:
      objc-class-ref in libreact-native-melion.a(Melion.o)
      __OBJC_$_CATEGORY_File_$_RCTExternModule in libreact-native-melion.a(Melion.o)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Then i tried to run on the device (iphone X) and i got the same error but for arm64.

HELP!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request help wanted Extra attention is needed
Projects
None yet
Development

Successfully merging a pull request may close this issue.

5 participants