当前位置:  开发笔记 > 编程语言 > 正文

如何在另一个框架内添加框架(Umbrella Framework)

如何解决《如何在另一个框架内添加框架(UmbrellaFramework)》经验,为你挑选了4个好方法。

我使用以下教程构建了一个框架.

我也有这个框架.

我正在尝试在我的内部实现第二个框架,从我在Apple文档中读到的结果框架被称为"伞框架".

我在框架中使用拖放添加了第二个框架,并验证它是否在"Link Binary With Libraries"中.

在我尝试在我的框架的一个类中进行下一次导入之后:

#import 

我收到错误,因为导入的框架不可见.

另外我看过stackoverflow帖子: 如何在iOS SDK中创建一个伞形框架?

更新

有没有人试图为iOS提取PLCrashReporter类并将其集成到一个项目中?

你可以在这里找到我的尝试.



1> Vel Genov..:

分发另一个框架的诱惑是可以理解的,但是非常气馁.我将尝试解释为什么(带参数),并提供一些有用的替代方案.

伞框架仅供您使用,只有当您是两个框架的分发者时,您才能完全控制它们,并且它们将一起分发.

苹果公司有一个关于这个话题的热门话题,他们说他们不鼓励伞形框架.

不要创建伞框架

虽然可以使用Xcode创建伞形框架,但对大多数开发人员来说这样做是不必要的,不建议这样做.Apple使用伞形框架来掩盖操作系统中库之间的一些相互依赖关系.几乎在所有情况下,您都应该能够将代码包含在单个标准框架包中.或者,如果您的代码足够模块化,您可以创建多个框架,但在这种情况下,模块之间的依赖关系将是最小的或不存在的,并且不应该保证为它们创建保护伞.

首先,这是大多数开发人员在这种情况下所做的事情,因为有许多框架依赖于其他框架.

告知用户您的框架需要使用其他第三方框架.这是完全标准的,在大多数情况下是预期的.然后在系统级别链接到它.就这么简单.您的框架会发现第三方和函数似乎很有用,就像使用本机框架一样.以UIKit为例.要链接到第三方,请按照下一部分中的步骤操作.它当然可以通过标准方式完成,但使用像CocoaPods这样的工具将使您的项目更容易维护.

要完全回答您的问题,而不是以通常的方式添加第三方框架,因为您可能会遇到问题和复杂问题,请使用 CocoaPods为您添加它.通过这种方式,您可以消除可能的问题,并获得CocoaPods的额外好处,从而获得您需要的第三方的确切版本.

这是一个名为"CrashTest"的应用程序的CocoaPods Podfile

target 'CrashTest' do
pod 'PLCrashReporter', '~> 1.2.0'
end

只是为了澄清一下,当您开发框架时,它仍将被添加到您的项目中并且可见.这里的最大区别在于它将与您的框架分开分发,最终用户必须将两者都添加到他们的项目中才能使工作正常.

以下是为什么这样做的原因.

例如,您希望包含PLCrashReporter在您的框架中.假设另一个框架供应商也希望将其包含在他们的网站中.使用这两个框架的应用程序将PLCrashReporter包含两次(作为每个伞框架的一部分).可能甚至不同版本的它.这可能会导致用户应用程序内部出现严重问题.如果两个伞形框架都链接到PLCrashReporter,如上一节所述,则可以完全避免此问题.

我在上面提到的另一点是版本控制.在分发伞形框架时,您需要能够控制所涉及的所有框架的版本,并且您无法控制第三方框架.这将再次导致与上述问题类似的问题.

我知道这种方法并没有提供问题的直接答案,但它试图阻止一种不良的做法,同时指出行业标准的做事方式.


我们不应该使用"使用Cocopods"作为有效答案.这并没有解释如何做到这一点
@VelGenov我对Cocopods的看法非常熟悉.您对管理框架的建议是在环境中引入依赖关系,而不是自己解释如何执行它.这是一个糟糕的答案,对不知情的人有害.
总体而言,Cocopods对iOS社区有害。等待实际的快速软件包管​​理器不要用一些红宝石代码(严重地)将一堆废话注入到您的项目文件中(这是不支持的)来毒害您的系统。苹果在这里只是错了。首先有充分的理由来构建“伞框架”,这从它们的存在就可以证明。

2> Segev..:

Apple不鼓励你创建一个伞形框架但是,仍然说它有可能对它的结构有一些描述等,所以我将专注于如何实际做到这一点.

我必须提一下,如果你控制一个或多个框架,将它们捆绑成一个并不是一个坏主意,可以帮助最终开发人员.

在最近的Xcodes(7及更高版本)上创建一个伞形框架现在非常简单

这是怎么做的.

首先创建一个框架:

在此输入图像描述

拖到CrashReporter.frameworkUmbrella框架项目:

在此输入图像描述

用于确保两个框架都正常运行的示例代码:

Umbrella.h:

#import 
#import 

@interface Umbrella : NSObject

+(void)sayHelloFromUmbrella;

@end

Umbrella.m:

#import "Umbrella.h"
#import 

@implementation Umbrella

+(void)sayHelloFromUmbrella
{
    NSLog(@"Hey from Umbrella");
    PLCrashReporter *crashObject = [[PLCrashReporter alloc]initWithConfiguration:nil];
    NSLog(@"crashObject: %@",crashObject);
}

@end

构建,您将获得构建文件夹中的Umbrella.framework(包含CrashReporter.framework).

Umbrella.framework其拖放到要使用它的项目中的"嵌入式二进制文件"中:

在此输入图像描述

然后只需导入完成的框架.

我们刚刚将Umbrella.framework拖到的项目中的ViewController.m:

#import "ViewController.h"
#import 

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    [Umbrella sayHelloFromUmbrella];
}

哪个会输出这个:

Hey from Umbrella 
crashObject: 

这告诉我们两个框架都在工作.


我用苹果的劝阻开始了我的回答.此外,我没有讨论该法案的道德规范.(许可证等)这只是回答操作直接问题.在我们的例子中,我管理了一些框架并将其中两个组合成一个很好的解决方案.我找不到一个关于如何使用最近的Xcodes做一个体面的教程,并相信上述就足够了.
框架("CrashReporter")实际上并未嵌入在Umbrella框架中.它只是联系在一起.必须将CrashReporter框架复制到Umbrella中的目录中,并且必须在运行时从那里加载.
这个答案并没有创建一个仅仅链接到框架的伞形框架
@Segev这个答案,并没有描述伞形框架的创建.同样,这个答案产生的框架*静态链接*到"PLCrashReporter"."PLCrashReporter"二进制文件在"Umbrella"中归档*.

3> MinamiTouma..:

这里是一个演示项目:

伞框架演示

这一行下的所有答案都是错误的,因为他们只是手动将子框架复制到"伞框架"中

在框架中嵌入框架(iOS 8+)

如何在iOS SDK中创建一个伞形框架?

如何在另一个框架内添加框架(Umbrella Framework)

伞框架

首先我们应该知道"伞形框架"是Mac OS中的概念而不是iOS,官方文档就在这里

https://developer.apple.com/library/content/documentation/MacOSX/Conceptual/BPFrameworks/Concepts/CreationGuidelines.html#//apple_ref/doc/uid/20002254-BAJHGGGA

如果你想创建一个不推荐的"UmbrellaFramework",你必须一步一步地完成这些过程,并在编译和链接期间知道细节

    将所有子框架Mach-O更改为静态库,这意味着将此目标编译为静态库(.a)

    在构建阶段手动将所有子框架复制到UmbrellaFramework(与其他答案一样)

    将"FakeBundleShellScript"添加到Target"UmbrellaFramework",它使所有子框架将自己的资源打包为bundle来加入"UmbrellaFramework"

    更改框架加载功能,你必须通过路径或url加载子框架资源,使它成为一个bundle,这一步意味着你应该对所有代码的子框架和伞都有最高控制权

!!这是您可以参考的"FakeBundleShellScript"的示例

APP_PATH="${TARGET_BUILD_DIR}/${WRAPPER_NAME}"
find "$APP_PATH" -name '*.framework' -type d | while read -r FRAMEWORK
do
FRAMEWORK_EXECUTABLE_NAME=$(defaults read "$FRAMEWORK/Info.plist" CFBundleExecutable)
FRAMEWORK_EXECUTABLE_PATH="$FRAMEWORK/$FRAMEWORK_EXECUTABLE_NAME"
BUNDLE_IN_ROOT="$APP_PATH/${FRAMEWORK_EXECUTABLE_NAME}.bundle"
if [[ -e "$FRAMEWORK_EXECUTABLE_PATH" ]]; then
  FRAMEWORK_MACH_O="$(otool -a "$FRAMEWORK_EXECUTABLE_PATH" | head -n 1)"
  FRAMEWORK_FAT_ARCH="$(lipo -info "$FRAMEWORK_EXECUTABLE_PATH")"
else
  FRAMEWORK_MACH_O="NO EXIST"
  FRAMEWORK_FAT_ARCH="NO EXIST"
fi
echo "FRAMEWORK_EXECUTABLE_NAME is $FRAMEWORK_EXECUTABLE_NAME"
echo "FRAMEWORK_EXECUTABLE_PATH is $FRAMEWORK_EXECUTABLE_PATH"
echo "FRAMEWORK_MACH_O is $FRAMEWORK_MACH_O"
echo "FRAMEWORK_FAT_ARCH is $FRAMEWORK_FAT_ARCH"
echo "BUNDLE_IN_ROOT is $BUNDLE_IN_ROOT"
if [[ "$FRAMEWORK_MACH_O" =~ "Archive :" ]]; then
  echo "Rmove Static-Mach-O is $FRAMEWORK_EXECUTABLE_PATH"
  rm "$FRAMEWORK_EXECUTABLE_PATH"
  defaults write "$FRAMEWORK/Info.plist" CFBundlePackageType "BNDL"
  defaults delete "$FRAMEWORK/Info.plist" CFBundleExecutable
  if [[ -d "$BUNDLE_IN_ROOT" ]]; then
    rm -rf "$BUNDLE_IN_ROOT"
  fi
  mv -f "$FRAMEWORK" "$BUNDLE_IN_ROOT"
elif [[ "$FRAMEWORK_FAT_ARCH" =~ "Architectures in the fat file" ]]; then
  #statements
  EXTRACTED_ARCHS=()
  for ARCH in $ARCHS
  do
    echo "Extracting $ARCH from $FRAMEWORK_EXECUTABLE_NAME"
    lipo -extract "$ARCH" "$FRAMEWORK_EXECUTABLE_PATH" -o "$FRAMEWORK_EXECUTABLE_PATH-$ARCH"
    EXTRACTED_ARCHS+=("$FRAMEWORK_EXECUTABLE_PATH-$ARCH")
  done
  echo "Merging extracted architectures: ${ARCHS}"
  lipo -o "$FRAMEWORK_EXECUTABLE_PATH-merged" -create "${EXTRACTED_ARCHS[@]}"
  rm "${EXTRACTED_ARCHS[@]}"
  echo "Replacing original executable with thinned version"
  rm "$FRAMEWORK_EXECUTABLE_PATH"
  mv "$FRAMEWORK_EXECUTABLE_PATH-merged" "$FRAMEWORK_EXECUTABLE_PATH"
fi
done

http://alanli7991.github.io/2017/07/17/%E6%A8%A1%E5%9D%97%E5%8C%9617Framework%E4%B8%8EStaticFramework%E4%BC%AA%E8%A3 %85Bundle /

正如我所说的,制作一个不推荐的"UmbrellaFramework"的关键是!!!! [将子框架编译为静态,通过假捆绑处理资源],记住!! Apple总是说不要创建一个UmbrellaFramework

如果你能理解中文,可以从我的博客中获得更多关于制作"UmbrellaFramework"的细节

Alan.li 2017年的文章



4> Adriana Pine..:

我尝试做@Segev建议的操作,但是不断收到错误消息,指出缺少嵌入式框架文件。

但是,做了一些额外的配置,我设法使其正常工作!

这是我所做的:

    在伞形框架项目中添加嵌入式框架头文件。

    在伞头中添加:导入“ EmbeddedFramework.h”

    然后将伞形框架导入所需的项目中,您将不会遇到更多错误

您将看到伞形框架的“ Headers”文件夹将包含“ EmbeddedFramework.h”文件

您可以在此处查看示例项目:

伞框架:https : //github.com/AdrianaPineda/FrameworkGOMobileSample

示例应用程序:https : //github.com/AdrianaPineda/iOSGOMobileSampleApp

希望这可以帮助


推荐阅读
大大炮
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有