How to create a cocoapod with .swift? - swift

I know how to work with cocoapods in a new swift project?
But how can i create my own cocoapod using swift?
pod lib lint produces this error:
- NOTE | [xcodebuild] warning: no rule to process file '/Pod/Classes/SomeClass.swift' of type text for architecture armv7
Edit:
Just found this swift branch:
https://github.com/CocoaPods/CocoaPods/tree/swift

Cocoapods now supports swift : Pod-Authors-Guide-to-CocoaPods-Frameworks

Although Swift is officially supported, there are no official templates available for Swift and documentation is still slim. Here's a step-by-step tutorial for creating CocoaPods in Swift that may help though.
Essentially the steps are:
Create a git repo
Create your Xcode workspace
Add an iOS/OSX example project
Add Swift framework and make it as a dependency to your example project
Create your pod spec file, here's an example for a Swift pod:
Pod::Spec.new do |s|
s.name = "MySwiftPod"
s.version = "0.1"
s.summary = "This is my amazing Swift CocoaPod!"
s.description = <<-DESC
This is my long description here... yada, yada.
DESC
s.homepage = "http://basememara.com/how-to-create-a-cocoapod-with-swift/"
s.screenshots = "www.example.com/screenshots_1.gif", "www.example.com/screenshots_2.gif"
s.license = { :type => "MIT", :file => "LICENSE" }
s.author = { "Basem Emara" => "some#example.com" }
s.social_media_url = "https://twitter.com/basememara"
s.platform = :ios, "8.0"
s.source = { :git => "https://github.com/basememara/cocoapods-swift-sample.git", :tag => s.version }
s.source_files = "MySwiftPod/MySwiftPod/*.swift"
end

Related

flutter_stripe custom stripe-ios local dependency

I would like to use a modify version of stripe_ios library in flutter_stripe library to include a missing functionality I added.
for that I downloaded both libraries and copy them inside a packages directory of my flutter app.
then inside pubspec.yaml I declared the library like that:
flutter_stripe:
path: packages/stripe
then in flutter_stripe library folder I edited stripe_ios/ios/stripe_ios.podspec to make Stripe library reference point to my modified version:
Pod::Spec.new do |s|
s.name = 'stripe_ios'
s.version = '0.0.1'
s.summary = 'A new flutter plugin project.'
s.description = <<-DESC
A new flutter plugin project.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email#example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.dependency 'Flutter'
s.dependency 'Stripe'
s.subspec 'Stripe' do |ss|
ss.source_files = '../../library/StripeIos/Stripe'
end
s.platform = :ios, '11.0'
# Flutter.framework does not contain a i386 slice.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'i386' }
s.swift_version = '5.0'
end
But it seems it's not working correctly and when I do pod install from ios folder it seems to download version 21.13.0 of Stripe ios library instead.
any idea how to achieve this correctly ?

How to add .a libraries on flutter plugin via podspec

I am trying to include .a files on the iOS side of the plugin. Below is my file structure.
Now when I try to add .a files via vendored_libraries on podspec, pod install is successfully completed. And when I compile the code, I get Library Not Found -lAccuraFace
I tried to add the .a file on the Link Binary With Libraries section on the build phase on the Pod target. It's still the same, how can I define the podspec in such a way that the .a file is included and linked automatically.
Here is my podspec file for the plugin
Pod::Spec.new do |s|
s.name = 'accuraemirates'
s.version = '0.0.1'
s.summary = 'A new Flutter plugin.'
s.description = <<-DESC
A new Flutter plugin.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email#example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.dependency 'Flutter'
s.public_header_files = 'Classes/*{.h}'
s.private_header_files = 'Classes/CodeScan/**/*{.h,.cpp,.a}'
s.platform = :ios, '8.0'
s.preserve_paths = 'opencv2.framework'
s.xcconfig = {
'OTHER_LDFLAGS' => '-framework opencv2 -lAccuraFace',
}
s.ios.vendored_frameworks = 'opencv2.framework', "CoreVideo.framework", "Foundation.framework", "CoreGrpahics.framework",
"Accelerate.framework", "CoreMedia.framework", "CoreImage.framework", "QuartzCore.framework", "AudioToolbox.framework", "CoreData.framework", "SystemConfiguration.framework"
s.ios.vendored_libraries = 'Classes/Framework/*{.a}', "libz.1.dylib", "c++", "stdc++"
# Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
s.swift_version = '5.0'
end
Here is the root podfile
ENV['COCOAPODS_DISABLE_STATS'] = 'true'
project 'Runner', {
'Debug' => :debug,
'Profile' => :release,
'Release' => :release,
}
def parse_KV_file(file, separator='=')
file_abs_path = File.expand_path(file)
if !File.exists? file_abs_path
return [];
end
generated_key_values = {}
skip_line_start_symbols = ["#", "/"]
File.foreach(file_abs_path) do |line|
next if skip_line_start_symbols.any? { |symbol| line =~ /^\s*#{symbol}/ }
plugin = line.split(pattern=separator)
if plugin.length == 2
podname = plugin[0].strip()
path = plugin[1].strip()
podpath = File.expand_path("#{path}", file_abs_path)
generated_key_values[podname] = podpath
else
puts "Invalid plugin specification: #{line}"
end
end
generated_key_values
end
target 'Runner' do
use_frameworks!
use_modular_headers!
# Flutter Pod
copied_flutter_dir = File.join(__dir__, 'Flutter')
copied_framework_path = File.join(copied_flutter_dir, 'Flutter.framework')
copied_podspec_path = File.join(copied_flutter_dir, 'Flutter.podspec')
unless File.exist?(copied_framework_path) && File.exist?(copied_podspec_path)
# Copy Flutter.framework and Flutter.podspec to Flutter/ to have something to link against if the xcode backend script has not run yet.
# That script will copy the correct debug/profile/release version of the framework based on the currently selected Xcode configuration.
# CocoaPods will not embed the framework on pod install (before any build phases can generate) if the dylib does not exist.
generated_xcode_build_settings_path = File.join(copied_flutter_dir, 'Generated.xcconfig')
unless File.exist?(generated_xcode_build_settings_path)
raise "Generated.xcconfig must exist. If you're running pod install manually, make sure flutter pub get is executed first"
end
generated_xcode_build_settings = parse_KV_file(generated_xcode_build_settings_path)
cached_framework_dir = generated_xcode_build_settings['FLUTTER_FRAMEWORK_DIR'];
unless File.exist?(copied_framework_path)
FileUtils.cp_r(File.join(cached_framework_dir, 'Flutter.framework'), copied_flutter_dir)
end
unless File.exist?(copied_podspec_path)
FileUtils.cp(File.join(cached_framework_dir, 'Flutter.podspec'), copied_flutter_dir)
end
end
# Keep pod path relative so it can be checked into Podfile.lock.
pod 'Flutter', :path => 'Flutter'
# Plugin Pods
# Prepare symlinks folder. We use symlinks to avoid having Podfile.lock
# referring to absolute paths on developers' machines.
system('rm -rf .symlinks')
system('mkdir -p .symlinks/plugins')
plugin_pods = parse_KV_file('../.flutter-plugins')
plugin_pods.each do |name, path|
symlink = File.join('.symlinks', 'plugins', name)
File.symlink(path, symlink)
pod name, :path => File.join(symlink, 'ios')
end
end
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['ENABLE_BITCODE'] = 'NO'
end
end
end
Is it not possible to add/link .a libraries from podspec file on a flutter plugin.
Finally found the issue..
Pod::Spec.new do |s|
# other obvious values
s.source_files = 'Classes//*{.h,.a,.swift,.mm,.m,.hpp}'
s.resources = 'Resources//'
s.static_framework = true
s.public_header_files = "Classes/VideoCamera/VideoCameraWrapperDelegate.h", "Classes/VideoCamera/VideoCameraWrapper.h",'Classes/.h',
s.private_header_files = 'Classes/CodeScan//{.h,.cpp,.hpp}'
s.platform = :ios, '8.0'
s.preserve_paths = 'opencv2.framework', 'Classes/Framework/.a'
s.xcconfig = {
# here on LDFLAG, I had to set -l and then the library name (without lib prefix although the file name has it).
'OTHER_LDFLAGS' => '-framework opencv2 -lc++ -lAccuraFace -lAccuraEmirate -lDocRecog -lz',
'USER_HEADER_SEARCH_PATHS' => '"${PROJECT_DIR}/.."/',
"LIBRARY_SEARCH_PATHS" => '"${PROJECT_DIR}/.."/*',
}
s.vendored_frameworks = 'opencv2.framework' # Various framworks you need
# Here the name of the library can include lib as the file name has it too.
s.vendored_libraries = 'AccuraFace','libAccuraEmirate','libDocRecog'
end
Notice two values here OTHER_LDFLAGS and vendored_libraries. Although I have same file, they need names with and without lib prefix. Weird but worked.
You definitely CAN add .a libraries, try to check the following configuration path
TARGETS->Build Settings->Search Paths-> Library Search Paths
Right there, add path where .a library was located.
Here is a valid path configuration demo:
==========================================================================
UPDATE
For flutter plugin
As for ship as flutter plugin ,file with .a suffix is actually static library, here is a snippet for how to do it in a .podspec file:
s.subspec 'Core' do |sc|
sc.ios.library = 'z'
sc.frameworks = 'SystemConfiguration', 'QuartzCore', 'CoreText', 'WebKit'
sc.source_files = 'AppboyKit/headers/AppboyKitLibrary/*.h', 'AppboyKit/ABKIdentifierForAdvertisingProvider.m', 'AppboyKit/ABKModalWebViewController.m', 'AppboyKit/ABKNoConnectionLocalization.m', 'AppboyKit/ABKLocationManagerProvider.m'
sc.resource = 'AppboyKit/Appboy.bundle'
sc.vendored_libraries = 'AppboyKit/libAppboyKitLibrary.a'
sc.weak_framework = 'CoreTelephony', 'Social', 'Accounts', 'AdSupport', 'UserNotifications'
end
Pay attention to line start with sc.vendored_libraries there.Here is the complete source.
ios framework into flutter_plugin
import your Famework or library in both path => Flutter_Plugin/example/ios and Flutter_Plugin/ios .
IN Flutter_plugin/ios/flutter_plugin.podspec file
s.preserve_paths = 'YOUR_FRAMEWORK.framework'
s.xcconfig = { 'OTHER_LDFLAGS' => '-framework YOUR_FRAMEWORK' }
s.ios.vendored_frameworks = 'YOUR_FRAMEWORK.framework'
s.ios.vendored_libraries = 'YOUR_FRAMEWORK'
make your framework embeded and signin in xcode(Flutter_Plugin/example/ios).
!sometimes in DerivedData/.../debug_iphone/flutter_plugin.framework - its not there so make that Flutter_plugin.framework move to that debug_iphone folder , it inside the flutter_plugin folder.

iOS Flutter Plugin Dependency Issue

I am trying to develop a Flutter plugin for the Tapkey Mobile SDK.
I managed to add their SDK by modifying the podspec of the plugin and the Podfile of the example:
tapkey.podspec:
Pod::Spec.new do |s|
s.name = 'tapkey'
s.version = '0.0.1'
s.summary = 'A tapkey flutter plugin'
s.description = <<-DESC
A tapkey flutter plugin
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email#example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.dependency 'Flutter'
s.platform = :ios, '9.0'
s.dependency 'TapkeyMobileLib', '~> 2.5.10.0'
s.static_framework = true
# Flutter.framework does not contain a i386 slice. Only x86_64 simulators are supported.
s.pod_target_xcconfig = { 'DEFINES_MODULE' => 'YES', 'VALID_ARCHS[sdk=iphonesimulator*]' => 'x86_64' }
s.swift_version = '5.0'
end
Podfile:
platform :ios, '9.0'
source 'https://github.com/tapkey/TapkeyCocoaPods'
source 'https://github.com/CocoaPods/Specs.git'
# unmodified Podfile
However, building the app fails with:
Running Xcode build...
Xcode build done. 26,4s
Failed to build iOS app
Error output from Xcode build:
2019-12-26 22:07:57.289 xcodebuild[57331:4745526] DTDeviceKit: deviceType from 1816565999a8254de93745cb449376c7b2946e65 was NULL
2019-12-26 22:07:57.441 xcodebuild[57331:4745803] DTDeviceKit: deviceType from 1816565999a8254de93745cb449376c7b2946e65 was NULL
** BUILD FAILED **
Xcode's output:
22 warnings generated.
<module-includes>:1:9: note: in file included from <module-includes>:1:
#import "Headers/GsonPublicHeader.h"
^
/Users/zarbex/IdeaProjects/tapkey/example/ios/Pods/GsonJ2ObjC-Light/Gson.framework/Headers/GsonPublicHeader.h:1:10: note: in file included from /Users/zarbex/IdeaProjects/tapkey/example/ios/Pods/GsonJ2ObjC-Light/Gson.framework/Headers/GsonPublicHeader.h:1:
#include "$Gson$Preconditions.h"
^
/Users/zarbex/IdeaProjects/tapkey/example/ios/Pods/GsonJ2ObjC-Light/Gson.framework/Headers/$Gson$Preconditions.h:6:10: error: 'J2ObjC_header.h' file not found
#include "J2ObjC_header.h"
^
<unknown>:0: error: could not build Objective-C module 'Gson'
<module-includes>:1:9: note: in file included from <module-includes>:1:
#import "Headers/TapkeyMobileLib.h"
^
/Users/zarbex/IdeaProjects/tapkey/example/ios/Pods/TapkeyMobileLib/TapkeyMobileLib.framework/Headers/TapkeyMobileLib.h:27:9: note: in file included from /Users/zarbex/IdeaProjects/tapkey/example/ios/Pods/TapkeyMobileLib/TapkeyMobileLib.framework/Headers/TapkeyMobileLib.h:27:
#import "CipherFactories.h"
^
note: Using new build system
note: Planning build
note: Constructing build description
Could not build the precompiled application for the device.
I have looked at several similar GitHub issues, but could not solve the problem.

Custom Flutter plugin development for iOS

I am trying to develop a custom Flutter plugin for iOS.
The customer has shared a Vendor-specific private SDK (Not available in Cocoapods repo) for interacting with external hardware. SDK is in *.framework format.
So I created a new plugin. Inside the plugin, I want to add the SDK dependencies in .podspec file from a local path. How to add this dependency? Is it the right approach or do we have any other option to resolve this problem? Kindly help me.
I was able to resolve this issue by providing all vendor-specific frameworks as s.vendored_frameworks in the podspec configuration of the plugin.
s.vendored_frameworks = 'x1.framework','x2.framework','x3.framework',
Pod::Spec.new do |s|
s.name = 'ble'
s.version = '0.0.1'
s.summary = 'A new flutter plugin project.'
s.description = <<-DESC
A new flutter plugin project.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email#example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.ios.deployment_target = '10.0'
s.requires_arc = true
s.ios.frameworks = 'Foundation', 'CoreTelephony', 'Security', 'CoreLocation', 'CoreBluetooth', 'CoreMotion', 'UIKit', 'SystemConfiguration', 'LocalAuthentication', 'CoreML'
s.dependency 'Flutter'
s.vendored_frameworks = 'SeosMobileKeysSDK.framework','BerTlv.framework','CocoaLumberjack.framework','JSONModel.framework','Mixpanel.framework'
end
All framework libraries are placed in the plugin folder itself

Importing IOS SDK libraries to a Flutter Plugin

Summary:
I am building a Flutter Plugin to be used for multiple projects I am developing. I have no experience writing custom platform-specific code.
I am having trouble importing SDK library for IOS *.Framework and *-Resources.bundle to my plugin.
I've tried to the solution for in https://github.com/flutter/flutter/issues/17978
Also, I've tried cleaning and re-building the app but with no success and tried cleaning and re-building the example app but with no success
and I receive the below error:
*.podspec:
Pod::Spec.new do |s|
s.name = 'plugin_name'
s.version = '0.0.1'
s.summary = 'A new flutter plugin project.'
s.description = <<-DESC
A new flutter plugin project.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email#example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.ios.deployment_target = '9.0'
end
Pod::Spec.new do |spec|
spec.name = "plugin_name"
spec.version = "2.3.7"
spec.summary = "SDK"
spec.homepage = "https://hkhars.com"
spec.author = "Hussain Alkhars"
spec.license = { :file => '../LICENSE' }
spec.source = { :path => '.' }
spec.ios.deployment_target = '9.0'
spec.preserve_paths = 'IOSFLUTTERSDK.framework'
spec.xcconfig = { 'OTHER_LDFLAGS' => '-framework IOSFLUTTERSDK' }
spec.vendored_frameworks = 'IOSFLUTTERSDK.framework'
spec.public_header_files = "IOSFLUTTERSDK.framework/Headers/*.h"
spec.resource_bundle = { 'IOSFLUTTERSDK-Resources' => './*' }
end
Error when trying to build with flutter build ios --no-codesign
fatal error: 'plugin_name/PluginNamePlugin.h' file not found
#import <plugin_name/PluginNamePlugin.h>```
You've mangled your Podspec file. There should only be one section starting Pod::Spec.new do |s|.... If you want to try the approach in the linked Github issue, your Podspec file should look like this:
Pod::Spec.new do |s|
s.name = 'plugin_name'
s.version = '0.0.1'
s.summary = 'A new flutter plugin project.'
s.description = <<-DESC
A new flutter plugin project.
DESC
s.homepage = 'http://example.com'
s.license = { :file => '../LICENSE' }
s.author = { 'Your Company' => 'email#example.com' }
s.source = { :path => '.' }
s.source_files = 'Classes/**/*'
s.public_header_files = 'Classes/**/*.h'
s.dependency 'Flutter'
s.ios.deployment_target = '9.0'
s.preserve_paths = 'IOSFLUTTERSDK.framework'
s.xcconfig = { 'OTHER_LDFLAGS' => '-framework IOSFLUTTERSDK' }
s.vendored_frameworks = 'IOSFLUTTERSDK.framework'
s.resource_bundle = { 'IOSFLUTTERSDK-Resources' => './*' }
end
However, I've tried this before with no success - I needed to link everything manually via Xcode by opening the project:
open example/ios/Runner.xcworksapce
Click on the "Runner" project at the top, and click on the "Build Phases" item on the right hand side (if "Build Phases" doesn't show, make sure the folder icon on the left is selected, and you've clicked the Runner Target in the middle panel, not the Runner Project).
Find the "Link Binary with Libraries" panel, and click the "+" button:
Select your .framework file and click "Done". Repeat the same under "Embed Frameworks".
I'm not 100% sure, but I think you can do the same under "Copy Bundle Resources".