-
-
Notifications
You must be signed in to change notification settings - Fork 464
iOS Wrapper improvements #630
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
iOS Wrapper improvements #630
Conversation
- move `Package.swift` to root - use dynamic build - get rid of `unsafeFlags` - remove need of umbrella framework - adjust readme and gitignore files
- add `ZXingCppWrapper` as swift package dependency - embed `ZXingCppWrapper` framework in project - lower minimum deployment target to `iOS 13.0`
- start stream on background thread - use 32RGBA instead of 'old' yuv variant (nowadays devices stream native 32RGBA) - add more camera variants to enable macro mode on newer devices
@axxel ready for review and release, potentially 😏 |
@alexmanzer I recognized your PR (#624), feel free to give this one a review. I removed the duplication of having a separate project to build the XCFramework which is then used by SwiftPM. One can now use |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for the work done and the interest in merging our efforts. Since I'm not the author of most of the involved code here, I'll also ask those if they have any comments on your PR.
To those who had their hands on any of the iOS/macOS wrapper code before: would you care to comment on this PR? There are two changes that I'd like to specifically point to:
@parallaxe, @Alex-MSFT, @alexmanzer, @ChristianNorbertBraun, @ryantrem |
Just to clarify on these two points:
|
@axxel I will wait for feedback from the other guys and then also adjust the gitlab action. I've overlooked that one, sry! |
Additional remark: if there is need for a solely published XCFramework, I would rather use the new configuration with some tool like https://github.com/unsignedapps/swift-create-xcframework. |
CI was adjusted in 8f7f0e8, was a low-hanging fruit. |
First off, thanks @benjohnde for this PR. I discussed the consequences of the changes on our side with @alexmanzer. Our overall conclusion is: This is a very welcome pull request. Some of the decisions we made at the beginning are no longer relevant for ourself (i.e. having a build script that creates an xcframework that can then be distributed with Cocoapods - we are switching over to Swift Package Manager, and this PR makes this easier). But there is one change that would break our requirements: The change from a static library to a dynamic one. We build frameworks for customers that use ZXing internally. But this is an internal detail the customer should not care about. Our philosophy is to hand them over one framework, without any external dependencies. But with a dynamic library, they have to add ZXing as additional dependency. It may seem like a little detail, but for us, this is important. Also, from what I know, there are no real disadvantages of static libraries vs. dynamic ones. @benjohnde Do I overlook something that regards to dynamic vs. static? Would it be ok for you to change it to static? I'm not sure if Swift Package Manager may offer the possibility for the consumer of the package to choose between static or dynamic - if there is a way, it should be the best of both worlds. |
@alexmanzer @parallaxe That is true to a certain degree, as only Apple frameworks are being used, it does probably not make a huge difference but normally dynamic libraries are smaller, as you don't link (store) other libraries in that one file. I won't be very detailed here as there is enough literature out there, one quick link would probably be https://theswiftdev.com/deep-dive-into-swift-frameworks/ or https://belkadan.com/blog/2022/02/Dynamic-Linking-and-Static-Linking/ (besides the cheesy title, good read though). I can certainly feel the need for a static library sometimes, we also have that requirement for one of our customer (not related to zxing-cpp though). My idea would then be (I should have implemented it like that right from the start) to omit
Still don't know how you have used the library so far, for us the built framework was not compliant to the App Store guidelines. Have you distributed that via the App Store (or TestFlight) or used some hack to get it injected properly? The produced library was not usable for us. Maybe we did a mistake there. I always experienced the following two issues:
|
btw I love the discussion and effort to create a nice usable dependency 😃 |
Just realised, maybe you have mixed up both terms. Or I did a mistake here. You are describing the comparison between dynamic frameworks (Apple will strip code depending on the target device / platform) and static frameworks (the library contains everything to run independently on frameworks, which are available on the target side). |
Yes, we have some apps in the AppStore that use zxing-cpp, among others CodeScan and DigitalProductPassport . You are right, the thing with the unsafeFlags was also a thorn in our side, that only worked if you either select the branch or a commit directly. The versioning as it is actually intended with SPM (via tag) is unfortunately not possible with unsafe flags. Therefore in general I am very pleased with your changes. 🙏 But the second argument (with the "umbrella framework") is not valid at all, from my perspective. Maybe as a general comment to this PR: |
Ouh nice!
Thanks, I wasn't aware of that! We still get the warning 'Umbrella framework' though.
As the unsafeFlag issue existed, I created a new XCFramework with the Wrapper files which then umbrella'd the other one. So I resulted in |
…in swift pm - without the `type` attribute, it gets either linked statically or dynamically depending on the target
Also, since @benjohnde has not commented on #623 yet, please give this a quick thought, just in case the mentioned podspec question has any influence on the decisions made here. |
Hm, overall it's a question of how we/you want to proceed with iOS integration. Therefore, there are clearly two hearts beating in my chest:
However, in the short term (= next days/weeks) I can't take the time to create a *.podspec and test through all the configurations, even though that's probably not the biggest thing in the world. In general, CocoaPods should also have all the possibilities to build a framework from source during installation. Ultimately, however, this would also mean having to have another file (*.podspec) at root level. |
Sure, squash that one! I will fix the CI in a sec. I do totally agree on what @alexmanzer just stated, there are currently three "camps", CocoaPods, Carthage (still people are using that though) and SPM. For CocoaPods, what was described here is a possibility to go (using the Framework in a Pods reference). I would still rather go with the same approach like the
Depends on your usage, if your library (which uses zxing-cpp) is linked statically, then your deps also have to be linked statically (at least should be, otherwise you cannot guarantee your static library is working "statically", i.e. not relying on other libraries installed on your system). I am very open to have a discussion or a little pair-programming session on that, if there are issues arising because of my proposed changes! Lastly, if you really need that explicit |
@axxel I just lowered the |
@benjohnde Thanks for the changes, sounds good to me! Like @alexmanzer wrote, we have to figure out how to configure the static/dynamic-part at build time, but hopefully there will be a solution. Regarding your comment on static / dynamic libraries
Phuh, it's a complex topic, and Apple has it's own share of complexity on its own. So it would be no wonder if we are talking past each other at some point. 😉 I don't know if it is that important at this point to get this clear, but I give it a shot by outlining my understanding of the topic:
|
@parallaxe sry, my knowledge is probably just wrong, I will re-read some articles (e.g. https://bpoplauschi.github.io/2021/10/25/Advanced-static-vs-dynamic-libraries-and-frameworks.html). I had the assumption that dynamic should be favoured over static in apps. That was probably wrong. |
Dynamic frameworks are the default for apps and in general. My assumption is for this is, that this enables a faster iteration at development time (if all needed libraries are statically linked into the app, the linking step could take longer than the compilation step itself). Though, for ZXing with a binary size of <2MB per architecture, this should not be noticeable. |
@alexmanzer I had the same issue with |
Seems to have had no effect. I thought you can simply manually trigger a ci job on the Actions page, but I could not find it now. hm. Maybe you need to somehow activate GA on your fork and then any push from you triggers a ci run? |
@benjohnde Just tried some things here to find the problem with the build: If I execute
If I try to open the demo project with Xcode 14.3.1 it also throws this error: So it is really a problem of the already updated demo project. |
@benjohnde @axxel |
Co-authored-by: Alexander Manzer <alexander.manzer@kurzdigital.com>
- basically revert 2f0d820
Thanks a million for patch @alexmanzer! Works on my fork, so it should also turn green here @axxel! |
Ah, I did a mistake. I tried to use the macos-13 runner but forgot to update to Xcode 15. The provided patch solves both, Xcode 14 and Xcode 15 usage. Guess we are good to fuel that into the master ⛽ 🚀 ! |
🚀🚀🚀 So, thanks to all your work @benjohnde; together with some other iOS improvements (e.g. also this open pull request) the iOS usage of zxing-cpp really becomes very powerful and I think there is no reason to use the old zxingify-objc anymore. 💪🏻 |
@parallaxe I have to admit that my knowledge was wrong. As far as I understood it, dynamic frameworks are useful for development (if linking statically is time consuming) and environments, in which you want to change the underlying framework without compromising the target (i.e. in which the framework is being used) - like hot-swapping frameworks 😏 without re-deploying the whole application. It could also be useful, if the downside of linking statically would result in a dramatic increased app size. Apart from that, it seems that static is more useful in an app context. |
Thanks to all of you for this pretty intense collaboration! This is the first time two parties have been working together on something in this code base, where I was neither of those two parties. :) |
@axxel Thanks for merging into the master! 🙏 Merely for the sake of interest: When do you usually set a new version tag to this repo? (It would be cool to include the change from the other pull request, that would be really helpful for us.) |
Usually right before the next release. I understand that this might cause confusion when just grabbing HEAD and tag it with the latest release number even if the code changed. But even if I started introducing some |
@axxel When importing an SPM package into Xcode the package manage will care about the versions, but only if the repo has "semantic version tag", like 2.1.0. If you add a package in Xcode, you get this dialog: And the options for "Dependency Rules" are: ![]() So, Xcode SPM can only care about updates, when there is a version tag. And the fact that it's only possible with this PR here that you can even use the SPM like this would of course strengthen a new version tag. But of course, this mainly affects the iOS community |
So, it will always only pull individual commits that are tagged SemVer style. That totally makes sense. I'm Ok with making a new release soonish. |
The old wrapper had a few disadvantages which are solved by the following PR:
Package.swift
resides now in root, enabling people to includezxing-cpp
on iOS by just adding this repository as package dependency in XcodeunsafeFlags
are not used anymore, thus there is no need for injecting the framework manually in a hacky way