rhdeck / react-native-swift-cli

CLI Interface for creating/linking Swift-based React Native Native Modules
MIT License
32 stars 2 forks source link

Is it possible to support cocoa touch framework with swift? #1

Open wuxudong opened 6 years ago

wuxudong commented 6 years ago

It works like magic for static lib. but I don't know what it did, can you explain a little bit about the underlying magic?

and is it possible to support cocoa touch framework with swift?

rhdeck commented 6 years ago

Yes, Swift is supported by Apple as a first-class language. Pick your feature, go to apple documentation, and pick Swift from the Language drop-down (in the upper-right when viewed on a desktop).

Thank you for the kind words!

wuxudong commented 6 years ago

Actually, I tried but failed.

I am working on react-native-charts-wrapper.

Now the user need to copy code to their app, and that is bad.

There is a pull request which turn it to a static library, but because this library depends on two frameworks Charts and SwiftyJSON, so that PR copy Charts and SwiftyJSON code to this library, which is not perfect.

I tried to convert it to Cocoa touch framework, but never pass the compilation.

Can you provide any swift react native framework demo? I can not find any in github.

Great thanks.

rhdeck commented 6 years ago

Well, 2 things:

  1. Your 3rd party libraries might be better deployed as Cocoapods. react-native-pod makes this pretty easy and leverages react-native link. I recently made a library that uses pods and swift that you might feel useful for reference: react-native-tesseract
  2. Your project looks very cool!
wuxudong commented 6 years ago

The main problem is not 3rd party libraries, but is react-native. I tried a simplified project. lib is the framework, and app is the hosting test app.
It complains like this.

screen shot 2018-04-27 at 10 29 26 pm

The swift framework can not use bridging header. I imported the

#import <React/RCTBridgeModule.h>
#import <React/RCTEventEmitter.h>
#import <React/RCTViewManager.h>
#import <React/RCTConvert.h>
#import <React/RCTUtils.h>

in the umbrella header. but it complains Include of non-modular header inside framework module 'lib':

Any suggestion?

rhdeck commented 6 years ago

You are attempting to copy my code to make it easy to deploy to a swift-based SL to your framework project. These are different targets with different surface areas.

react-native-mdm deploys a swift-based framework and an OC SL that bridges the functionality. The bridge (separate from a bridging header) is necessary because the RN hooks you are looking for are not exposed to the framework. It was all they could do with XCode 7/8.

But the hack-ish nature of that bridge is why I create static libraries for my Swift-based RN plugins. XCode 9 allows them to work without framework hacks. And to make that easy for others I released react-native-swift and react-native-swift-cli!

So I recommend building as a swift-based SL. Since most of the good stuff is in a single MyViewManager.swift file, I think the port shouldn't be too painful.

wuxudong commented 6 years ago

I don't quite get it... I am still quite new to iOS and Xcode. and have no experience of object-c.

MyViewManager.swift is just a demo.

import Foundation
@objc(MyViewManager)
class MyViewManager: RCTViewManager {
    //MARK: RCTViewManager key methods
    override func view() -> UIView {
        let newView = UIView()
        newView.backgroundColor = UIColor.green
        return newView
    }
    override class func requiresMainQueueSetup() -> Bool {
        return false;
    }
}

What I am trying to do is a demo hosting app and a demo cocoa touch framework wrapping react native UIView in swift.

If there are any examples , please let me know.

Great Thanks.

rhdeck commented 6 years ago

I appreciate that there are a number of moving parts here. Swift-OC interop isn't completely seamless (that's why I made tools!). Also, the documentation you find on the web is going to talk a lot about making frameworks for Swift, and SLs for OC. The key is that this is no longer operative as of 6 months ago. XCode 9 lets you make SLs with Swift. And it works pretty well. It's what I recommend,and what I try to make easier with RNSC. Then you can add whatever code you like - in Swift - and have it easily deploy to RN.

The tesseract library I linked upthread is an example of this. And I made a template, react-native-template-tesseractocr, to demonstrate how it fits into a deployable app too, which you might find helpful as a reference.

wuxudong commented 6 years ago

Swift static library is good, but is it possible to import framework in static library?

That is what did:

  1. react-native-swift init rnlib

  2. react-native-swift makeapp rnapp rnlib ,it will hang at :

     rnpm-install info Linking mylib ios dependency 
     rnpm-install info Platform 'ios' module mylib has been successfully linked 
     Writing to  /Users/wuxudong/tmp/rnapp/ios/RNPlaceholder.swift
     Starting with  RNPlaceholder.swift

    and if you type enter, then it will continue :

    Done. To edit your project in xcode, type "react-native xcode"
    Note that if you want to deploy a cocoapod in this app (e.g. after running addpod on your module), you should "yarn add react-native-pod"

    then leave rnapp/ios/RNPlaceholder.swift blank. Is this behavior expected?

  3. cd rnapp

  4. yarn add react-native-pod

  5. react-native addpod SwiftyJSON

  6. react-native link

  7. an error occurred : RuntimeError - [Xcodeproj] Consistency issue: no parent for object RNPlaceholder.swift: SourcesBuildPhase, SourcesBuildPhase, SourcesBuildPhase, SourcesBuildPhase

  8. open ios/rnapp.xcworkspace

  9. It compiles correctly.

  10. Now I want to use SwiftyJSON in rnlib. I add import SwiftyJSON in rnlibBasicViewManager. add SwiftyJSON.framework in rnlib->Build Phases->Link Binary with Libraries.

  11. Compile fails: No such module 'SwiftyJSON'

Because rnlib want to use SwiftyJSON, and it is a cocoa touch framework. Is it possible to import framework in static library?

screen shot 2018-04-28 at 2 48 37 pm
wuxudong commented 6 years ago

I find a topic about Adding FacebookSDK.framework into my own Static library, the solution needs a lot tedious work.

It is not easy to use 3rd framework in static library.

wuxudong commented 6 years ago

I tried react-native init mytestapp --template tesseractocr

In rn-Bridging-Header.h , there is #import "TesseractOCR.h".

but in SwiftyJSON, there is only one swift file, no such headers. Any workaround?

rhdeck commented 6 years ago

I looked into this a little.

Most germanely, there is an open issue on SwiftyJSON about the "module not found" error in XCode 9.3. I haven't looked deeply, but I also got an XCode error about his Swift file being written in Swift 2, which is fully disallowed by XCode 9.3, so won't be interpreted. I suspect this problem is the crux of the open issue, but either way it is an issue with the pod and not with your code or with RNSC. (I wish it were the latter - would mean I could help!)

The other noise you got falls in two categories: 1) A Pod error from the fact that the placeholder file has no group associated with it. This is an outstanding issue with my react-native-swift package, but while it makes some verbose output, it doesn't actually affect runtime, so I think a red herring. 2) The "pressing enter" thing is annoying , and definitely buried in one of my RN pre/postlink hooks. Also on my list. 3) The tesseract thing is because the Tesseract Pod is Objective-C based, and we use the bridging header for that interop. A Swift-based Pod would just use the import statement like you were attempting.

Finally, I would observe that SwiftyJSON is just one file, and ISC/MIT licensed. One option is to just copy in his code as a private member of your SL. No need for an import statement in that case, or the CocoaPods complexity. (Though you may want to use Pods for other parts of your project). Just make sure to give proper credit to meet the terms of the license (and be a mensch).

Hope some of that helps!

wuxudong commented 6 years ago

I tested other pure swift frameworks like Charts/Alamofire, none of import [pure swift module] work in the static library, so I don't think it is a problem of SwiftyJSON. (I already add recursive ../../../build ../../../ios/Pods to Framework Search Paths)

For those OC frameworks, it works with #import <XXXXOC.h> in the bridging header (and also add recursive ../../../ios/Pods to Header Search Paths)

At this moment, it seems copy these framework source code is the only choice.

rhdeck commented 6 years ago

I have done more more homework, and realized that your issue is really about the same bete noire I have been fighting for the last week. This is not about RNSC in particular, but getting a handle on it is key to making it more generally useful. So I am looking into it.

At the core is this question: what are the preconditions for being able to reference one swift module from another via the import statement. And it seems to be all over the place. The static library thing makes is more corner-y, but it applies to core code changes as well. Doesn't work until it works. What causes it to cross that line is the question mark and I am investigating.

SO I am sorry that I do not have a great answer for you now, but your questionhas pushed me harder toward getting a better answer. I will post to this issue when I have news.

nazrdogan commented 5 years ago

is there any solution for this ? I also facing same issue.

rhdeck commented 5 years ago

Nazir is this a pod you are trying to import? Which one? On Sun, Oct 21, 2018 at 3:22 PM Nazır Doğan notifications@github.com wrote:

is there any solution for this. I also facing same issue.

— You are receiving this because you modified the open/close state.

Reply to this email directly, view it on GitHub https://github.com/rhdeck/react-native-swift-cli/issues/1#issuecomment-431696353, or mute the thread https://github.com/notifications/unsubscribe-auth/ALov_wrHk7L5jONziWbISvOOWx1CWalTks5unMlggaJpZM4TqI9B .

nazrdogan commented 5 years ago

nope, PaymentHighway pods. I think its not about pod specific. the problem is import Swift pod into RN module for me.

rhdeck commented 5 years ago

Thanks! This is an issue where some pods work and others do not, so understanding more pods that have issues helps triangulate what they have in common to figure out the root cause.

On Sun, Oct 21, 2018 at 3:26 PM Nazır Doğan notifications@github.com wrote:

nope, PaymentHighway pods. I think its not about pod specific. the problem is import Swift pod into RN module for me.

— You are receiving this because you modified the open/close state.

Reply to this email directly, view it on GitHub https://github.com/rhdeck/react-native-swift-cli/issues/1#issuecomment-431696636, or mute the thread https://github.com/notifications/unsubscribe-auth/ALov_6PTj_FOteIGy8SlcSVfcyjcK1ldks5unMpGgaJpZM4TqI9B .

nazrdogan commented 5 years ago

I solved my issue. I installed required library with Carthage and added "Link Binary with Libraries" . now it can find and use.

rhdeck commented 5 years ago

Added to build phases in app or your module SL? On Tue, Oct 23, 2018 at 2:29 AM Nazır Doğan notifications@github.com wrote:

I solved my issue. I installed required library with Carthage and added "Link Binary with Libraries" . now it can find and use.

— You are receiving this because you modified the open/close state.

Reply to this email directly, view it on GitHub https://github.com/rhdeck/react-native-swift-cli/issues/1#issuecomment-432111004, or mute the thread https://github.com/notifications/unsubscribe-auth/ALov_2LbS7gGP4M_BKsUiqTBidjKgvsAks5unrdPgaJpZM4TqI9B .

nazrdogan commented 5 years ago

in module. I cant give them right from app. I see somewhere. its says you need to add to in app. but I m not sure how can do that. I tried many things.