Charts for iOS on CocoaPods: Swift Syntax Error - ios

The following problem appears to not occur on Xcode 8.2.1 (8C1002), but is a show-stepper on 8.3 beta (8W109m).
A project I am writing includes the Charts for iOS library via Cocoapods.
Here is my Podfile:
target 'v5snapp' do
use_frameworks!
pod 'Fabric'
pod 'Crashlytics'
pod 'Charts'
pod 'GLCalendarView', '~> 1.0.0'
pod 'MBProgressHUD', '~> 0.9.2'
pod 'RNCryptor-objc'
end
# I haven't needed this code for a while now
#post_install do |installer|
# installer.pods_project.targets.each do |target|
# target.build_configurations.each do |config|
# config.build_settings['SWIFT_VERSION'] = '3.0'
# end
# end
#end
In the Charts library, all of a sudden, there is a breaking change in the code. So, now that project won't compile, which shuts down building my whole project. Bummer.
Here is the function with the breaking code:
open override func isEqual(_ object: Any?) -> Bool {
if object == nil
{
return false
}
if !(object! as AnyObject).isKind(of: type(of: self))
{
return false
}
// This is the breaking code. The problem seems to be this:
// object! as AnyObject).data !== data
if (object! as AnyObject).data !== data && !((object! as AnyObject).data??.isEqual(self.data))!
{
return false
}
if fabs((object! as AnyObject).y - y) > DBL_EPSILON
{
return false
}
return true
}
I don't write in Swift yet, and although most of it is pretty straightforward, I'm a little fuzzy on the !, ?, and ===/!== vs. ==/!= stuff. So, what's wrong with the Swift code as-is? How can I fix it for my project? I'm tempted to just delete the offending code (leaving the other half of the line) until the library gets updated. As popular as it is, I'm sure I'm not the only one having this issue. I haven't seen this as an issue yet on the GitHub repo. I was hoping to figure out the fix myself (or here) before posting it as an issue there. Seems like just a simple problem. In the meantime, I'll go back to Xcode 8.2.1, but my devices are now on iOS 10.3 Beta, which makes it a pain to not be able to push directly to them over the wire.

Related

App using xcframework CocoaPod logs classes implemented in both app and framework

We have created a CocoaPod which is an XCFramework that has dependencies on other CocoaPods. When we run the demo example app or install the pod in a new app, it works, however this is logged to the console on launch (repeated for many classes):
objc[38875]: Class OTSubscriber is implemented in both
/Users/MyUser/Library/Developer/CoreSimulator/Devices/8DD81910-DD40-4BD7-9355-8A0C78EFD32E/data/Containers/Bundle/Application/60E8C18A-37DC-4C2B-AEB3-E88C3A7C4D96/MyCocoaPod_Example.app/Frameworks/MyFramework.framework/MyFramework
(0x10e3fd660) and
/Users/MyUser/Library/Developer/CoreSimulator/Devices/8DD81910-DD40-4BD7-9355-8A0C78EFD32E/data/Containers/Bundle/Application/60E8C18A-37DC-4C2B-AEB3-E88C3A7C4D96/MyCocoaPod_Example.app/MyCocoaPod_Example
(0x10c8abd80). One of the two will be used. Which one is undefined.
This class is from OpenTok, which is a dependency specified for the pod used in the framework. The message seems to reveal CocoaPods is installing the dependencies on the app in addition to the framework, causing this issue. The app itself shouldn't have any dependencies except this framework.
Perhaps something was done incorrectly in the pod creation process? These are the steps we took:
Create an Xcode framework project, add a Podfile listing its dependencies, build out the framework's functionality
Create an XCFramework from the framework's xcworkspace
Create the pod using pod lib create MyCocoaPod choosing iOS, Swift, include demo, none and no for testing
Update the Podspec:
Pod::Spec.new do |s|
s.name = 'MyCocoaPod'
s.version = '1.0.0'
s.summary = 'Summary'
s.description = <<-DESC
'Description'
DESC
s.homepage = 'https://myhomepage.com'
s.license = { :type => 'MIT', :file => 'LICENSE' }
s.author = { 'Author' => 'auther#somedomain.com' }
s.ios.deployment_target = '12.0'
s.source = { :git => 'https://github.com/user/git-repo.git', :tag => s.version.to_s }
s.vendored_frameworks = 'MyFramework.xcframework'
s.swift_version = '5.5.2'
s.dependency 'OpenTok', '2.21.3'
# Needed to pass lint validation
s.pod_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
s.user_target_xcconfig = { 'EXCLUDED_ARCHS[sdk=iphonesimulator*]' => 'arm64' }
end
Drag and drop MyFramework.xcframework into Pods/Development Pods/MyCocoPod
Update the example's Podfile to specify BUILD_LIBRARY_FOR_DISTRIBUTION = YES:
post_install do |installer|
installer.pods_project.targets.each do |target|
target.build_configurations.each do |config|
config.build_settings['BUILD_LIBRARY_FOR_DISTRIBUTION'] = 'YES'
end
end
end
Run pod install in Example directory - note this will cause the framework to be moved to the root level in Finder and under a Frameworks group in Xcode
Update the example app's code to import and use MyFramework
Commit, tag, and push the changes to the repo
Push the Podspec to the specs repo
Not sure if this is your case but maybe you are falling in a scenario which happened to me,
meaning a dynamic framework that depends on a static framework. In such scenario, your dynamic framework would end up embedding the static one in his resulting binary. Then, in order to import your dynamic framework in the project, you will import with the setting “Embed and sign” for example, as that’s indeed a dynamic one, along with the other static framework which your dynamic one depends on. This causes the duplicated implementation ( your app including the static dependency + the dynamic one embedding inside the same dependency.
What you could do if this is your case, is to make sure that the dynamic framework configuration is changed to be static (static xcframework to be precise) , maybe outside cocoa pod as first step if that simplifies. Code wise would be the same, but it will “link” to the dependency (OpenTok for example) rather than embedding it. As result, once imported in the app, it should be imported only once, as your custom framework links to it and does not embeds it, finally avoiding the duplicated implementation. (static frameworks are imported with “Do not embed” which means that they will be merged in compile time to the app executable)

Cocoapods post_install, how to add target membership in Pods project

I have a Podfile, that when constructing the Pods.xcodeProj ends up with an included xcframework that is a Pods.xcodeproj file reference, that I need to add as a target reference to one of the pods built targets.
I think it's possible to do such a thing in the Podfile post_install phase, but I cannot figure out the xcodeproj gem syntax required to (A) find the Nami.xcframework reference I need to add to the target, then (B) add that file reference to the desired target (see image below for the framework I wish to adjust target membership for, I basically just want to automate checking that target membership box).
My start to this Podfile script looks like:
post_install do |installer|
nami_target = installer.pods_project.targets { |f| f.name == "react-native-nami-sdk" }
#Pseudocode begins here, this is what I cannot figure out
nami_xcframework_fileref = ??
nami_target.addBuildReference(nami_xcframework)
end
Thanks for any help on this, I've found a number of example pod file scripts but none seem to do quite what I am trying to do.
I managed to figure out the full script I needed, the Podfile post_install script below does exactly what I was looking for.
Note that a key was that while you can examine targets by using the .name property, for file references only .path will always have contents you can examine, .name is often blank. Also another key item, is that you need to add the file reference to the frameworks_build_phase aspect of the target.
The final script (added to the end of a Podfile):
post_install do |installer|
puts("Attempting to add Nami.xcframework reference to react-native-nami-sdk project.")
installer.pods_project.targets.each do |target|
if target.name == "react-native-nami-sdk"
puts("Found react-native-nami-sdk target.")
all_filerefs = installer.pods_project.files
all_filerefs.each do |fileref|
if fileref.path.end_with? "Nami.xcframework"
puts("Found Nami.xcframework fileref.")
build_phase = target.frameworks_build_phase
puts("Determining if react-native-nami-sdk build phase needs correction.")
unless build_phase.files_references.include?(fileref)
puts("Adding Nami.xcframework to react-native-nami-sdk target")
build_phase.add_file_reference(fileref)
end
end
end
end
end
end

Database.database().reference() is nil

I'm creating an iMessage app that needs to connect to the same database as my regular app.
I call FirebaseApp.configure() and I authenticate the user but for some reason after all of that Database.database().reference() is null even though it is supposed to be a non null value.
var ref: DatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
if FirebaseApp.app() == nil {
FirebaseApp.configure()
Database.database().isPersistenceEnabled = true
print("FIREAPP Configed")
print(FirebaseApp.app())
signIn() //Use kept google credentials to log in
configureDatabase()
}
}
func configureDatabase() {
ref = Database.database().reference()
print(ref)
}
I'm expecting Database.database().reference() to be the root reference of the database instead of nil. Thanks for any help in advance!
I was also struggling with similar errors.
In my situation, my understanding of CocoaPods was not enough.
Before:
target 'MyApp' do
use_frameworks!
pod 'Firebase/Database'
target 'MyAppTests' do
inherit! :search_paths
end
target 'MyFrameWorkA' do
inherit! :search_paths
end
target 'MyFrameWorkB' do
inherit! :search_paths
end
end
After:
abstract_target 'AnyTargets' do # Anything that doesn't duplicate the actual target name
use_frameworks!
pod 'Firebase/Database'
target 'MyApp' do
end
target 'MyAppTests' do
end
target 'MyFrameWorkA' do
end
target 'MyFrameWorkB' do
end
end
I was able to consult your questions when looking for a solution.
I hope you solve the problem.
It seems you're confused about this line:
ref = Database.database().reference()
This merely sets up a reference to the root of the database. It doesn't load any data yet.
To actually load the data, attach a listener to the reference:
ref.observeSingleEvent(of: .value, with: { (snapshot) in
print(snapshot.value)
}) { (error) in
print(error.localizedDescription)
}
Note that data is loaded from Firebase asynchronously. Any code that needs the data, must be inside the completion handler (as above) or be called from there.
Also see the Firebase documentation on reading and writing data.
I stumbled over this error as well and the solution for me was adding 'Firebase/Core' to my pod file. I am not sure if this is common knowledge, but on setting up my firebase database project I never read about adding this specific pod.
My pod file after rewriting it:
target 'MyApp' do
# Comment the next line if you're not using Swift and don't want to use dynamic frameworks
use_frameworks!
# Pods for MyApp
# add pods for desired Firebase products
# https://firebase.google.com/docs/ios/setup#available-pods
pod 'Firebase/Database'
pod 'Firebase/Core'
end

How to set CLANG_ENABLE_MODULES = NO for pod generated project?

I'm trying to integrate ccache on my project which doesn't support clang modules. So I disabled clang modules in my main xcode project like below.
But for cocoapods generated project files, clang modules are enabled by default. Even if I change this setting, cocoapods will change it back on next pod update.
Is there anyway to let pod know that I want to fall back to the old behavior before apple introduced clang modules? Turn off CLANG_ENABLE_MODULES, and link system frameworks used by other pod generated static library for me in my main project automatically, like AVFoundation, MapKit, etc
Are you a Chinese developer? Have you seen this article before?
https://zhuanlan.zhihu.com/p/27584726
It's a tutorial of using ccache to speed up Xcode build process.It also provide the config of cocoapods.
I copied the code here, to let others who don't know Chinese and encounter the same problem know how to solve this problem.
post_install do |installer_representation|
installer_representation.pods_project.targets.each do |target|
target.build_configurations.each do |config|
#关闭 Enable Modules (Translation:Close Enable Modules)
config.build_settings['CLANG_ENABLE_MODULES'] = 'NO'
# 在生成的 Pods 项目文件中加入 CC 参数,路径的值根据你自己的项目来修改(Translation: Add CC parameter to pods project. You can change the path to whatever you want.)
config.build_settings['CC'] = '$(PODS_ROOT)/../ccache-clang'
end
end
end
but this configuration only turn off CLANG_ENABLE_MODULES.
As far as I know, there is no way to link system frameworks when using ccache and cocoapods.
Hope it helps.
If you are creating a custom pod, in your podspec file, write something like this,
Pod::Spec.new do |s|
# some configuration
s.pod_target_xcconfig = {
'OTHER_LDFLAGS' => '-lObjC', # if you created a category for a class from other lib
'CLANG_ALLOW_NON_MODULAR_INCLUDES_IN_FRAMEWORK_MODULES' => 'YES',
'CLANG_ENABLE_MODULES' => 'NO', # here is what you want
'CLANG_WARN_DOCUMENTATION_COMMENTS' => 'NO',
'GCC_C_LANGUAGE_STANDARD' => 'gnu17'
}
end

No visible #interface in Cocoapods

I am trying to modulize my app by splitting it in different sub projects.
Inspired by this idea. So I splited my project to static libraries followed by that tutorial. I created a first library with some costume UIHelpers/Views. It has some dependencies which I defined in PodSpec file followed by AFNetworking example. (one of the dependencies is Choosy). I stored this library in bitBucket. Everything is working fine for that library(I can build it in Xcode). The problem start when I create a Model Library. I specify Git path of UIHelpers in the Model PodFile. Every time I get an error of No visible #interface for a category in Choosy (the error come from CocoaPod NOT in my project, the category is imported in the .mfile). I tried to play with link flags -ObjC,$(inhereted),-force_load included all of them.Objective-C categories in static library I cleaned the derived data.
I read the CocoaPodTroubleShoutes.
Can somebody suggest what can be tried. There is a lot of question in stuck regarding that compile error but none of them helped me.
I believe the problem somewhere in my PodSpec(cant be sure) pod lib linit I receive :- ERROR | [iOS] Choosy/Choosy/Model/ChoosyAppInfo.m:32:19: error: no visible #interface for 'UIImage' declares the selector 'applyMaskImage:completion:'
My PodSec:
Pod::Spec.new do |s|
#I tried this options:
#s.xcconfig = { 'OTHER_LDFLAGS' => $(inherited) }
#s.compiler_flags = '-ObjC'
#'-all_load'
#$(inherited)
#'-DOS_OBJECT_USE_OBJC=0', '-Wno-format'
#'-force_load'
s.prefix_header_contents = '#import <UIKit/UIKit.h>', '#import <Foundation/Foundation.h>','#import <CoreGraphics/CoreGraphics.h>','#import "ARNStyles.h"'
s.description = <<-DESC
A longer description of ARNUIHelpers in Markdown format.
DESC
s.homepage = "http://EXAMPLE/ARNUIHelpers"
s.platform = :ios, "7.0"
s.ios.deployment_target = "7.0"
s.source_files = 'UIHelpers/**/*.{h,m}'
s.requires_arc = true
s.subspec 'Choosy' do |ss|
ss.requires_arc = true
ss.compiler_flags = '-force_load'
ss.platform = :ios, "7.0"
ss.dependency 'Choosy'
# ss.xcconfig = { "FRAMEWORK_SEARCH_PATHS" => "$(PODS_ROOT)/Headers/Public/Choosy"}
# ss.ios.public_header_files = 'UIImage+ImageEffects.h'
end
s.subspec 'Dependencies' do |ss|
#ss.ios.public_header_files = 'UIImage+ImageEffects.h'
ss.requires_arc = true
ss.dependency 'FormatterKit'
end
end
In the end it was my fault. The previous developer copied those files from Choosy pod and included it manually.We still use Choosy in other places. Unfortunately the error wasn't clear enough to deduce what was wrong.

Resources