ios - Xcode 9.3 Swift嵌套自定义框架单元测试和iTunesConnect上传

标签 ios swift xcode frameworks

几天后,我已经厌倦了混乱的构建设置...

我有一个应用程序,我们称它为MyiPhoneApp,它使用大约10个 private /自定义框架(Cocoa Touch Dynamic Framework)。 MyiPhoneApp也将Cocoapods用于某些依赖项(不相关?)。我的 private 框架自己在使用自己(彼此依赖)。

因此,我的设置是(此处为便于阅读而简化):

框架( private /自定义可可触摸动态):
Models
目标: ViewModelsViewModelsTests 取决于 private 框架:无
ViewModels
定位:ViewModelsViewModelsTests 取决于 private 框架:ModelsViews
定位:ViewsViews 依赖于 private 框架:ModelsViewModels
应用
MyiPhoneApp:

定位:MyiPhoneAppMyiPhoneAppTestsMyiPhoneAppUITests 取决于 private 框架的 MyiPhoneApp:ModelsViewModelsViews
捕获22个正在运行的单元测试并上传到iTunesConnect

使用ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES的所有目标,我可以在每个专用框架中运行所有单元测试。 但是然后我从iTunes Connect收到拒绝错误:

[04:06:20]:[运输器错误输出]:错误ITMS-90206:“无效
束。位于“MyiPhoneApp.app/Frameworks/Models.framework”的捆绑软件
包含不允许的文件'Frameworks'。” [04:06:20]:[传输器错误
输出]:错误ITMS-90206:“无效的捆绑包。捆绑包位于
“MyiPhoneApp.app/Frameworks/ViewModels.framework”包含不允许
文件“Frameworks”。”​​ [04:06:20]:[传输器错误输出]:错误
ITMS-90206:“无效的捆绑包。捆绑包位于
'MyiPhoneApp.app/Frameworks/Views.framework'包含不允许的文件
'构架'。”

这似乎类似于:
(SO Q958)[Validation Error: Invalid Bundle. The bundle at ... contains disallowed file 'Frameworks'

Q958的The answer with over 240 upvotes,建议:
为Frameworks和Tests目标(和Frameworks的Test Target ..?)设置ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO,为Apps设置YESthis Github comment也建议这样做

尝试尝试时(框架及其测试目标的ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO),我无法运行测试。

当我尝试运行ModelTests(记住Framwork Models不依赖于任何其他框架)时,测试失败/死于:

dyld:未加载库:@ rpath / libswiftCore.dylib引用自:
/Users/sajjon/Library/Developer/Xcode/DerivedData/Models-ahgxztzgogwcfheblqbzabdqxhtm/Build/Products/Debug-iphonesimulator/Models.framework/Models
原因:找不到图片

什么是正确的设置?

我已经尝试过Xcode 9.3和Xcode 9.4。我的框架和我的应用程序使用以下xcconfig文件:

我的系统

Macbook Pro 15英寸2016年末
macOS High Sierra v 10.13.5(17F77)

椰子足1.5.3(捆绑包)

Bundler版本1.16.1bundle exec pod --version => 1.5.3
我的Podfile

source 'https://github.com/CocoaPods/Specs.git'
platform :ios, '11.2'
inhibit_all_warnings!
use_frameworks!

workspace 'MyWorkspace.xcworkspace'

### PODS (sorted by name) ###

def nimble
  pod 'Nimble',  '~> 7.1'
end

def rxswift           
  pod 'RxSwift', '~> 4.1'
end

def viewcomposer      
  pod 'ViewComposer', :git => 'https://github.com/Sajjon/ViewComposer.git'
end

def quick
  pod 'Quick',  '~> 1.3'
end

# Rest of pods removed for this StackOverFlow question for readability #

# Global Pod used by ___ALL___ targets
swiftlint

#@@ Apps (sorted by name) @@#

target 'MyiPhoneApp' do
  project 'Apps/MyiPhoneApp/MyiPhoneApp'


  # lots of pods removed for this SO question for readability
  rxswift
  tinyconstraints
  viewcomposer

  abstract_target 'Tests' do
    nimble
    quick

    target "MyiPhoneAppTests"
    target "MyiPhoneAppUITests"
  end
end


### PRIVATE FRAMEWORKS ###

abstract_target 'Framework-Models' do
  project 'Common/Models/Models'

  target 'Models' do
    # lots of pods removed for this SO question for readability
    rxswift
    swiftybeaver
  end

  target 'ModelsTests' do
    nimble
    quick
  end
end

abstract_target 'Framework-ViewModels' do
  project 'Common/ViewModels/ViewModels'

  target 'ViewModels' do
    # lots of pods removed for this SO question for readability
    rxswift
    viewcomposer
  end

  target 'ViewModelsTests' do
    nimble
    quick
  end
end

abstract_target 'Framework-Views' do
  project 'Common/Views/Views'

  target 'Views' do
    # lots of pods removed for this SO question for readability
    rxswift
    tinyconstraints
    viewcomposer
  end

  target 'ViewsTests' do
    nimble
    quick
  end
end

我的xcconfig文件设置

因此,如您在上面的Podfile中看到的那样,我的 private Framework使用Pod。但是我想使用xcconfig文件在我的框架之间共享构建设置(我只写了三个ViewModelsViewsModels,但实际上我大约有10个。)

因此,我研究了Xcode默认为Apps,Cocoa Touch Dynamic Frameworks创建的xcconfig文件,以及在测试目标和非测试目标之间以及在调试和发布之间,这些设置的区别。

由此,我创建了这些xcconfig文件
base_shared.xcconfig
包括配置: NONE
说明:由所有目标(应用程序(主要,测试,UITest),框架(主要,测试))使用。
base_debug.xcconfig
包括配置: NONE
说明:由所有调试目标(应用程序(主要,测试,UITest),框架(主要,测试))使用。
base_release.xcconfig
包括配置: NONE
说明:由所有发行目标(应用程序(主要,测试,UITest),框架(主要,测试))使用。
base_apps.xcconfig
包括配置: base_shared 说明:由应用程序目标(主要,测试,UITest)使用
base_framework.xcconfig
包括配置: base_shared 说明:由框架(主要,测试)使用。
base_tests.xcconfig
包括配置: base_shared 说明:由所有测试目标(应用程序,框架)使用。
base_uitests.xcconfig
包括配置: base_shared 说明:由所有UITest目标(应用程序)使用。

然后,对于每个应用程序框架,我在Common xcconfig中包括xcconfig的正确组合。所以对于框架Models,我创建6个配置文件:Models-Common.xcconfigModels-Debug.xcconfigModels-Release.xcconfig,“ModelsTests-Common.xcconfig”,ModelsTests-Debug.xcconfigModelsTests-Release.xcconfig

虽然这会产生许多xcconfig文件,每个框架6个,但它们都很小。而且,我可以在所有10多个框架之间共享所有构建设置。这是一个权衡。

我的xcconfig文件的内容
base_shared.xcconfig:
// BuildSettings shared between both DEBUG and RELEASE and also identical for both FRAMEWORKS (Cocoa Touch Framework) and APPS (iOS)

// Vanilla Xcode 9.3 settings
ALWAYS_SEARCH_USER_PATHS = NO
CLANG_ANALYZER_NONNULL = YES
CLANG_ANALYZER_NUMBER_OBJECT_CONVERSION = YES_AGGRESSIVE
CLANG_CXX_LANGUAGE_STANDARD = gnu++14
CLANG_CXX_LIBRARY = libc++
CLANG_ENABLE_MODULES = YES
CLANG_ENABLE_OBJC_ARC = YES
CLANG_ENABLE_OBJC_WEAK = YES
CLANG_WARN_BLOCK_CAPTURE_AUTORELEASING = YES
CLANG_WARN_BOOL_CONVERSION = YES
CLANG_WARN_COMMA = YES
CLANG_WARN_CONSTANT_CONVERSION = YES
CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES
CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR
CLANG_WARN_DOCUMENTATION_COMMENTS = YES
CLANG_WARN_EMPTY_BODY = YES
CLANG_WARN_ENUM_CONVERSION = YES
CLANG_WARN_INFINITE_RECURSION = YES
CLANG_WARN_INT_CONVERSION = YES
CLANG_WARN_NON_LITERAL_NULL_CONVERSION = YES
CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES
CLANG_WARN_OBJC_LITERAL_CONVERSION = YES
CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR
CLANG_WARN_RANGE_LOOP_ANALYSIS = YES
CLANG_WARN_STRICT_PROTOTYPES = YES
CLANG_WARN_SUSPICIOUS_MOVE = YES
CLANG_WARN_UNGUARDED_AVAILABILITY = YES_AGGRESSIVE
CLANG_WARN_UNREACHABLE_CODE = YES
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES
COPY_PHASE_STRIP = NO
ENABLE_STRICT_OBJC_MSGSEND = YES
GCC_C_LANGUAGE_STANDARD = gnu11
GCC_NO_COMMON_BLOCKS = YES
SDKROOT = iphoneos
GCC_WARN_64_TO_32_BIT_CONVERSION = YES
GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR
GCC_WARN_UNDECLARED_SELECTOR = YES
GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE
GCC_WARN_UNUSED_FUNCTION = YES
GCC_WARN_UNUSED_VARIABLE = YES
IPHONEOS_DEPLOYMENT_TARGET = 11.2

// Custom set
CODE_SIGN_STYLE = Manual
SWIFT_VERSION = 4.1
DEVELOPMENT_TEAM = MYTEAMIDGOESHERE
ENABLE_BITCODE = NO
CODE_SIGN_ENTITLEMENTS =
CODE_SIGN_IDENTITY =
base_debug.xcconfig:
_DEBUG = DEBUG
GCC_PREPROCESSOR_DEFINITIONS = $(_DEBUG)
DEBUG_INFORMATION_FORMAT = dwarf
ENABLE_TESTABILITY = YES
GCC_DYNAMIC_NO_PIC = NO
GCC_OPTIMIZATION_LEVEL = 0
MTL_ENABLE_DEBUG_INFO = YES
ONLY_ACTIVE_ARCH = YES
SWIFT_ACTIVE_COMPILATION_CONDITIONS = DEBUG
SWIFT_OPTIMIZATION_LEVEL = -Onone
SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(inherited) $(_DEBUG)
base_release.xcconfig:
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
ENABLE_NS_ASSERTIONS = NO
MTL_ENABLE_DEBUG_INFO = NO
SWIFT_COMPILATION_MODE = wholemodule
SWIFT_OPTIMIZATION_LEVEL = -O
VALIDATE_PRODUCT = YES
base_apps.xcconfig:
#include "base_shared.xcconfig"
// Apps have no specific BuildSettings that the FRAMEWORKS does not have as well. But in the future they might have, thus we have this file.

// These settings were in the TravelCompanion xcconfig
SWIFT_ACTIVE_COMPILATION_CONDITIONS[sdk=iphonesimulator*] = $(inherited) IOS_SIMULATOR
MTL_ENABLE_DEBUG_INFO = NO
SWIFT_OPTIMIZATION_LEVEL = -O
DEBUG_INFORMATION_FORMAT = dwarf-with-dsym
ENABLE_NS_ASSERTIONS = NO
VALIDATE_PRODUCT = YES
SUPPORTED_PLATFORMS = iphonesimulator iphoneos
VALID_ARCHS = arm64 armv7 armv7s
CLANG_MODULES_AUTOLINK = YES
GCC_OPTIMIZATION_LEVEL = s
CLANG_ENABLE_CODE_COVERAGE = NO
TARGETED_DEVICE_FAMILY = 1
CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES
VERSIONING_SYSTEM = apple_generic

// Custom
// The flag `ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES` should be set to `YES` for apps and `NO` for frameworks
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES
base_framework.xcconfig:
#include "base_shared.xcconfig"

// BuildSettings specific for FRAMEWORKS (Cocoa Touch Framework)

// Vanilla BuildSettings
CURRENT_PROJECT_VERSION = 1
VERSIONING_SYSTEM = apple-generic
VERSION_INFO_PREFIX =

// Custom Set
PRODUCT_NAME = $(TARGET_NAME:c99extidentifier)
INSTALL_PATH = $(LOCAL_LIBRARY_DIR)/Frameworks
DYLIB_COMPATIBILITY_VERSION = 1
DYLIB_CURRENT_VERSION = 1
DEFINES_MODULE = YES
SKIP_INSTALL = YES


// The flag `ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES` should be set to `YES` for apps and `NO` for frameworks
ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = NO

LD_RUNPATH_SEARCH_PATHS = $(inherited) @executable_path/Frameworks @loader_path/Frameworks
base_tests.xcconfig:
#include "base_shared.xcconfig"

ONLY_ACTIVE_ARCH = YES

//Only used by APPS but it does not mess up build settings for test targets for FRAMEWORKS in Xcode 9.3 so will keep it here for now
BUNDLE_LOADER = $(TEST_HOST)
base_uitests.xcconfig:
#include "base_shared.xcconfig"
TEST_TARGET_NAME = $(PRODUCT_NAME)
Models-Common.xcconfig:
#include "../../../../Configurations/base_framework.xcconfig"

INFOPLIST_FILE = Source/SupportingFiles/Models-Info.plist
PRODUCT_BUNDLE_IDENTIFIER = com.sajjon.Models
Models-Debug.xcconfig:
#include "Models-Common.xcconfig"
#include "../../../../Configurations/base_debug.xcconfig"
#include "../../Pods/Target Support Files/Pods-Framework-Models-Models/Pods-Framework-Models-Models.debug.xcconfig"
Models-Release.xcconfig:
#include "Models-Common.xcconfig"
#include "../../../../Configurations/base_release.xcconfig"
#include "../../Pods/Target Support Files/Pods-Framework-Models-Models/Pods-Framework-Models-Models.release.xcconfig"
ModelsTests-Common.xcconfig:
#include "../../../../Configurations/base_framework.xcconfig"
#include "../../../../Configurations/base_tests.xcconfig"
INFOPLIST_FILE = Tests/SupportingFiles/ModelsTests-Info.plist
ModelsTests-Debug.xcconfig:
#include "ModelsTests-Common.xcconfig"
#include "../../../../Configurations/base_debug.xcconfig"
#include "../../Pods/Target Support Files/Pods-Framework-Models-ModelsTests/Pods-Framework-Models-ModelsTests.debug.xcconfig"
ModelsTests-Release.xcconfig:
#include "ModelsTests-Common.xcconfig"
#include "../../../../Configurations/base_release.xcconfig"
#include "../../Pods/Target Support Files/Pods-Framework-Models-ModelsTests/Pods-Framework-Models-ModelsTests.release.xcconfig"
MyiPhoneApp-Commong.xcconfig:
#include "../../../../Configurations/base_apps.xcconfig"

_APP_NAME_PROD = My iPhone App
_BUNDLE_IDENTIFIER_PROD = com.sajjon.myiphoneaop
INFOPLIST_FILE = Source/SupportingFiles/MyiPhoneApp-Info.plist

DEVELOPMENT_TEAM = MYTEAMGOESHERE

PRODUCT_NAME = $(_APP_NAME_PROD)
ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage

CODE_SIGN_ENTITLEMENTS = Source/SupportingFiles/$(_APP_NAME_PROD).entitlements
SWIFT_OBJC_BRIDGING_HEADER = Source/SupportingFiles/MyiPhoneApp-Bridging-Header.h

PRODUCT_MODULE_NAME = TravelCompanion

// Overridden in Debug.xcconfig
CODE_SIGN_IDENTITY = iPhone Distribution

// Overridden in Release.xcconfig
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-Alpha

ENABLE_TESTABILITY = YES
MyiPhoneApp-Debug.xcconfig:
#include "MyiPhoneApp-Common.xcconfig"
#include "../../../../Configurations/base_debug.xcconfig"
#include "../../Pods/Target Support Files/Pods-MyiPhoneApp/Pods-MyiPhoneApp.debug.xcconfig"

_DEBUG = DEBUG
_CODE_SIGN_ID_DEBUG = iPhone Developer
_BUNDLE_IDENTIFIER_DEBUG = $(_BUNDLE_IDENTIFIER_PROD).dev
_PP_DEBUG = match Development $(_BUNDLE_IDENTIFIER_DEBUG)

CODE_SIGN_IDENTITY = $(_CODE_SIGN_ID_DEBUG)

PROVISIONING_PROFILE_SPECIFIER = $(_PP_DEBUG)
PRODUCT_BUNDLE_IDENTIFIER = $(_BUNDLE_IDENTIFIER_DEBUG)
APP_DISPLAY_NAME = MyiPhoneApp
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-Debug
SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(inherited) $(_DEBUG)
GCC_PREPROCESSOR_DEFINITIONS = $(_DEBUG)
GCC_OPTIMIZATION_LEVEL = 0
GCC_OPTIMIZATION_LEVEL = 0
MTL_ENABLE_DEBUG_INFO = YES
SWIFT_OPTIMIZATION_LEVEL = -Onone
GCC_DYNAMIC_NO_PIC = NO
ONLY_ACTIVE_ARCH = YES
ENABLE_NS_ASSERTIONS = YES
ENABLE_NS_ASSERTIONS[sdk=iphoneos*] = YES
VALIDATE_PRODUCT = NO
MyiPhoneApp-Release.xcconfig:
#include "MyiPhoneApp-Common.xcconfig"
#include "../../../../Configurations/base_release.xcconfig"
#include "../../Pods/Target Support Files/Pods-MyiPhoneApp/Pods-MyiPhoneApp.release.xcconfig"

_PP_PROD = match AppStore $(_BUNDLE_IDENTIFIER_PROD)

PROVISIONING_PROFILE_SPECIFIER = $(_PP_PROD)
PRODUCT_BUNDLE_IDENTIFIER = $(_BUNDLE_IDENTIFIER_PROD)
APP_DISPLAY_NAME = $(_APP_NAME_PROD)
ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon-Production
SWIFT_ACTIVE_COMPILATION_CONDITIONS = $(inherited) APP_STORE_BUILD
SWIFT_OPTIMIZATION_LEVEL = -Owholemodule

最佳答案

在我们的项目中,我们有很多自定义框架,我们也遇到了类似的问题。对于每个框架,我们有两个构建配置,分别是DEBUG和RELEASE。而且,我们仅启用了ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES,用于我们用来运行测试的DEBUG构建。

关于ios - Xcode 9.3 Swift嵌套自定义框架单元测试和iTunesConnect上传,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/50746080/

相关文章:

ios - Swift 可选值及其实例化

android - gridview.extent 不会在 flutter 中滚动

ios - 如何实现左右滑动以在 swift IOS 中更改数据/ View ?

ios - 将 Facebook 数据传输到 Firebase

ios - 编译 xcode 项目时 Alamofire 出现大量问题

xcode - 在代码编辑器中禁用 Xcode 抗锯齿文本?

objective-c - Storyboard中的组静态 tableView 未出现

ios - 移动 map View 后显示标注

ios - 如何检索数组数据而不是字典?

ios - IOS 7.1 上的 requestWhenInUseAuthorization 错误