iOS 创建静态库(.a)

iOS创建.a和.framework静态库,以及Bundle资源文件的使用 引言在开发中.framework静态库还是比较常见的,比如:SDK,公司间的代码合作等。我们可以把一些不愿意让别人见到的代码,用静态库的方式把它隐藏起来,只留下.h文件显示方法供编程人员使用。而.a文件出了静态库本身外,还需要引入.h文件,而.framework就不需要如此,由于.framework的方便性所以一般情况下我们见到的较多。什么是库库从本质上来说是一种可执行代码的二进制格式,可以被载入内 阅读详情
本文由 Migrant [ 博客]翻译自  Creating a Static Library in iOS Tutorial。
 
如果您有不错的原创或译文,欢迎提交给我们,更欢迎其他朋友加入我们的翻译小组(联系qq:2408167315)。
 ===============================================================================
 
如果你作为iOS开发者已经有一段时间,可能会有一套属于自己的类和工具函数,它们在你的大多数项目中被重用。
 
重用代码的最简单方法是简单的 拷贝/粘贴 源文件。然而,这种方法很快就会成为维护时的噩梦。因为每个app都有自己的一份代码副本,你很难在修复bug或者升级时保证所有副本的同步。
 
这就是静态库要拯救你的。一个静态库是若干个类,函数,定义和资源的包装,你可以将其打包并很容易的在项目之间共享。
 
在本教程中,你将用两种方法亲手创建你自己的通用静态库。
 
为了获得最佳效果,你应该熟悉Objective-C和iOS编程。Core Image的相关知识并不是必须的,但是如果你对示例工程和滤镜代码如何工作感兴趣,了解它会有所帮助。
 
准备好以效率的名义减少,重用并再生你的代码!
 
为什么使用静态库
 
创建静态库可能出于以下几个理由:
1.你想将一些你和你团队中的同事们经常使用的类打包并轻松的分享给周围其他人。
2.你想让一些通用代码处于自己的掌控之下,以便于修复和升级。
3.你想将库共享给其他人,但不想让他们看到你的源代码。
 
你想创建一个还在不断开发的库的快照版本。
 
本教程假设你已经完成学习 Core Image Tutorial,并对其中展示如何应用图片特效的代码得心应手。
 
将上述代码添加到一个静态库中,然后在一个app的修改版本中使用这个静态库。我们会得到一个带有上面列表中全部好处的完全相同的应用。
 
开始
运行Xcode,选择File\New\Project,在Choose a template 对话框中选择iOS\Framework & Library\Cocoa Touch Static Library,如下图:
 
 
点击Next。在工程选项对话框中,输入ImageFilters作为产品名。再输入一个唯一的公司标识,确保Use Automatic Reference Counting被选中且Include Unit Tests未选中。如下图:
 
点击Next。最后,选择你想保存工程的位置并点击Create。
 
Xcode已经准备好静态库工程,甚至已经为你添加了一个ImageFilters类。这就是你的滤镜代码将要存放的地方。
 
注意: 你可以添加任意数量的类到静态库中或者从中删除原有的类。本教程中的代码都会写在开始就被创建好的ImageFilters类中。
 
你的Xcode工程还是一片空白,现在我们添加一些代码进去!
 
图片滤镜
 
该库使用UIKit,为iOS设计,所以你要做的第一件事就是在头文件中导入UIKit。打开ImageFilters.h,在文件顶部添加以下代码:
   
  1. #import <UIKit/UIKit.h> 
接下来将以下声明部分的代码粘贴到@interface ImageFilters : NSObject下面
   
  1. @property (nonatomic,readonly) UIImage *originalImage; 
  2.   
  3. - (id)initWithImage:(UIImage *)image; 
  4. - (UIImage *)grayScaleImage; 
  5. - (UIImage *)oldImageWithIntensity:(CGFloat)level; 
这些头文件中的声明定义了类的公开接口。其他开发者(包括你自己)使用该库时,只需通过阅读该头文件就可以知道类名和暴露的方法。
 
现在增加实现。打开ImageFilters.m文件,粘贴以下代码到#import "ImageFilters.h"下面:
   
  1. @interface ImageFilters() 
  2.   
  3. @property (nonatomic,strong) CIContext  *context; 
  4. @property (nonatomic,strong) CIImage    *beginImage; 
  5.   
  6. @end 
上面的代码声明了一些内部使用的属性。它们不是公开的,所以使用该库的引用没有使用它们的入口。
 
最后,你需要实现方法。粘贴以下代码到@implementation ImageFilters:下面:
   
  1. - (id)initWithImage:(UIImage *)image 
  2. { 
  3.     self = [super init]; 
  4.     if (self) { 
  5.         _originalImage  = image; 
  6.         _context        = [CIContext contextWithOptions:nil]; 
  7.         _beginImage     = [[CIImage alloc] initWithImage:_originalImage]; 
  8.     } 
  9.     return self; 
  10. } 
  11.   
  12. - (UIImage*)imageWithCIImage:(CIImage *)ciImage 
  13. { 
  14.     CGImageRef cgiImage = [self.context createCGImage:ciImage fromRect:ciImage.extent]; 
  15.     UIImage *image = [UIImage imageWithCGImage:cgiImage]; 
  16.     CGImageRelease(cgiImage); 
  17.   
  18.     return image; 
  19. } 
  20.   
  21. - (UIImage *)grayScaleImage 
  22. { 
  23.     if( !self.originalImage) 
  24.         return nil; 
  25.   
  26.     CIImage *grayScaleFilter = [CIFilter filterWithName:@"CIColorControls" keysAndValues:kCIInputImageKey, self.beginImage, @"inputBrightness", [NSNumber numberWithFloat:0.0], @"inputContrast", [NSNumber numberWithFloat:1.1], @"inputSaturation", [NSNumber numberWithFloat:0.0], nil].outputImage; 
  27.   
  28.     CIImage *output = [CIFilter filterWithName:@"CIExposureAdjust" keysAndValues:kCIInputImageKey, grayScaleFilter, @"inputEV", [NSNumber numberWithFloat:0.7], nil].outputImage; 
  29.   
  30.     UIImage *filteredImage = [self imageWithCIImage:output]; 
  31.     return filteredImage; 
  32. } 
  33.   
  34. - (UIImage *)oldImageWithIntensity:(CGFloat)intensity 
  35. { 
  36.     if( !self.originalImage ) 
  37.         return nil; 
  38.   
  39.     CIFilter *sepia = [CIFilter filterWithName:@"CISepiaTone"]; 
  40.     [sepia setValue:self.beginImage forKey:kCIInputImageKey]; 
  41.     [sepia setValue:@(intensity) forKey:@"inputIntensity"]; 
  42.   
  43.     CIFilter *random = [CIFilter filterWithName:@"CIRandomGenerator"]; 
  44.   
  45.     CIFilter *lighten = [CIFilter filterWithName:@"CIColorControls"]; 
  46.     [lighten setValue:random.outputImage forKey:kCIInputImageKey]; 
  47.     [lighten setValue:@(1 - intensity) forKey:@"inputBrightness"]; 
  48.     [lighten setValue:@0.0 forKey:@"inputSaturation"]; 
  49.   
  50.     CIImage *croppedImage = [lighten.outputImage imageByCroppingToRect:[self.beginImage extent]]; 
  51.   
  52.     CIFilter *composite = [CIFilter filterWithName:@"CIHardLightBlendMode"]; 
  53.     [composite setValue:sepia.outputImage forKey:kCIInputImageKey]; 
  54.     [composite setValue:croppedImage forKey:kCIInputBackgroundImageKey]; 
  55.   
  56.     CIFilter *vignette = [CIFilter filterWithName:@"CIVignette"]; 
  57.     [vignette setValue:composite.outputImage forKey:kCIInputImageKey]; 
  58.     [vignette setValue:@(intensity * 2) forKey:@"inputIntensity"]; 
  59.     [vignette setValue:@(intensity * 30) forKey:@"inputRadius"]; 
  60.   
  61.     UIImage *filteredImage = [self imageWithCIImage:vignette.outputImage]; 
  62.   
  63.     return filteredImage; 
  64. } 
这段代码实现了初始化和图片滤镜功能。详细解释上述代码的功能已经超出了本教程的范围,你可以从Core Image Tutorial中了解到更多的关于 Core Image 和滤镜的知识。
 
到这里,你已经有了一个静态库,它有一个暴露了以下3个方法的公开类ImageFilters:
initWithImage : 初始化滤镜类
grayScaleImage : 创建灰阶图片
oldImageWithIntensity : 创建怀旧效果的图片
 
现在构建并运行你的库。你会注意到Xcode的”Run”按钮只是执行了一次构建,而并不能真正的运行库去查看效果,因为并没有真正的app。
 
静态库的后缀名是.a而并不是一个.app或者.ipa文件。可以在工程导航栏中的Products文件夹下找到生成的静态库。右键点击libImageFilters.a并在弹出菜单中选择Show in Finder。
 
 
Xcode会在Finder中打开文件夹,你可以看到以下类似的结构:
 
离完成一个库产品还剩两件事:
1.Header files : 在include文件夹中可以找到库的所有公开头文件。在该示例中,只有一个公开类所以文件夹中只有一个ImageFilters.h文件。稍后你会在你的app工程中用到这个头文件以便于Xcode在编译期识别暴露的类。
2.Binary Libraty : Xcode生成的静态库是ImageFilters.a。想在应用中使用该库,你需要用该文件链接。
 
这两个部分和你想在应用里包含一些新的框架时所需要做的事很相似,简单的导入框架头文件并建立链接。
 
库已经准备就绪,需要附加说明的是,默认情况下,库文件只会为当前的架构构建。如果你在模拟器下构建,那么库会包含对应i386架构的结果代码;如果在真机设备下构建,你将会得到对应ARM架构的代码。你可能需要构建两个版本的库,并且当从模拟器切换到设备的时候选择其中一个使用。
 
怎么办?
 
幸运的是,有一个更好的办法可以不建立多个配置或在工程中构建产品就可以支持多个平台。你可以创建一个对应 2个 架构的包含结果代码的universal binary。
 
通用二进制
通用二进制是一种特殊的二进制文件,它包含对应多个架构的结果代码。你可能在从PowerPC(PPC)到Inter(i386)的Mac电脑产品线的过渡中对其有所熟悉。在这个过程中,Mac应用程序通常迁移为包含 2个 可执行包的一个二进制文件,这样应用程序即能在Inter也能在PowerPC的Mac电脑上运行。
 
同时支持ARM和i386的概念并没有太大不同。在这里静态库要包含支持iOS设备(ARM)和模拟器(i386)的结果代码。Xcode可以识别通用库,每次你构建应用的时候,它会根据目标选择适当的架构。
为了创建通用二进制库,需要使用一个名为lipo的系统工具。
 
别担心,不是那种lipo! :] (lipo有脂肪的意思 — 译者注)
 
lipo是一个命令行工具,它允许在通用文件上执行操作(类似于创建通用二进制, 列出通用文件内容等等)。本教程中使用lipo的目的是联合不同架构的二进制文件到单个输出文件中。你可以直接在命令行中使用lipo命令,但在本教程中你可以让Xcode执行一段创建通用库的命令行脚本来为你做这件事。
 
Xcode中一个集合目标可以一次构建多个目标,包括命令行脚本。在Xcode菜单中选择File/New/Target,选择iOS/Other并点击Aggregate,如图:
 
将目标命名为UniversalLib,确保选中ImageFilters工程,如图:
 
在工程导航视图中选中ImageFilters,然后选择UniversalLib目标。切换到Build Phases标签;在这里设置构建目标时将要执行的动作。
 
点击Add Build Phase按钮,在弹出的菜单中选择Add Run Script,如下图:
 
现在你需要设置脚本项。展开Run Script模块,在Shell行下粘贴如下代码:
   
  1. # define output folder environment variable 
  2. UNIVERSAL_OUTPUTFOLDER=${BUILD_DIR}/${CONFIGURATION}-universal 
  3.   
  4. # Step 1. Build Device and Simulator versions 
  5. xcodebuild -target ImageFilters ONLY_ACTIVE_ARCH=NO -configuration ${CONFIGURATION} -sdk iphoneos  BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" 
  6. xcodebuild -target ImageFilters -configuration ${CONFIGURATION} -sdk iphonesimulator -arch i386 BUILD_DIR="${BUILD_DIR}" BUILD_ROOT="${BUILD_ROOT}" 
  7.   
  8. # make sure the output directory exists 
  9. mkdir -p "${UNIVERSAL_OUTPUTFOLDER}" 
  10.   
  11. # Step 2. Create universal binary file using lipo 
  12. lipo -create -output "${UNIVERSAL_OUTPUTFOLDER}/lib${PROJECT_NAME}.a" "${BUILD_DIR}/${CONFIGURATION}-iphoneos/lib${PROJECT_NAME}.a" "${BUILD_DIR}/${CONFIGURATION}-iphonesimulator/lib${PROJECT_NAME}.a" 
  13.   
  14. # Last touch. copy the header files. Just for convenience 
  15. cp -R "${BUILD_DIR}/${CONFIGURATION}-iphoneos/include" "${UNIVERSAL_OUTPUTFOLDER}/" 
 
代码并不十分复杂,它是这样工作的:
UNIVERSAL_OUTPUTFOLDER 包括了通用二进制包将要被存放的文件夹:“Debug-universal”
 
Step 1. 第2行执行了xcodebuild并命令它构建ARM架构的二进制文件。(你可以看到这行中的-sdk iphoneos参数)
下一行再次执行了xcodebuild命令并在另一个文件夹中构建了一个针对Inter架构的iPhone模拟器的二进制文件,在这里关键参数是-sdk iphonesimulator -arch i386。(如果感兴趣,你可以在 man page了解更多关于xcodebuild的资料)
 
Step 2. 现在已经有了2个.a文件分别对应两个架构。执行lipo -create,用它们创建出一个通用二进制。
 
最后一行的作用是复制头文件到通用构建文件夹的外层。(用cp命令)
 
你的Run Script窗口应该看起来如下:
 
现在你已经准备好构建一个静态库的通用版本。在方案下啦菜单中选择集合目标UniversalLib,如下(不像截图上的”iOS Device”,你看到的可能是自己的设备名字):
 
点击Play按钮来为集合方案构建目标。
 
在libImageFilters.a上再次选择Show in Finder查看结果。将Finder切换到列视图查看文件夹层次,可以看到一个包含库的通用版本的叫做Debug-Universal的新文件夹(或Release-Universal如果你构建了发布版本),如下图:
 
除了这个链接到模拟器和真实设备的二进制文件,你还可以找到普通的头文件和静态库文件。
 
这是你创建自己的通用静态库所需要学习的所有知识。
 
概括起来,一个静态库工程和一个应用工程非常相似。可以拥有一个或多个类,最后的产品是头文件和一个.a文件。这个.a文件就是可以链接到多个应用程序中的静态库。
 
在应用中使用静态库
在应用中使用ImageFilters类和直接使用源代码并没有太大区别:导入头文件然后开始使用类。问题是Xcode并不知道头文件和库文件的位置。
 
有两种办法可以将静态库引入到工程中:
方法 1: 直接引用头文件和库二进制文件(.a)
方法 2: 将库工程作为子项目
 
选择哪一种方法完全取决于你的喜好或者是否有静态库的源代码和工程配置文件任由你支配。
 
本教程将分别介绍两种方法。你可以自由尝试第一个或第二个,但推荐按照文中介绍的顺序分别尝试两个。在两个部分的开头,需要一个zip文件,该文件是在 Core Image Tutorial中创建的应用的修改版本,修改后的版本使用了库中新的ImageFilters类。
 
本教程的主要目的是教你如何使用静态库,所以修改后的工程包括了所有应用需要的源代码。这样你就可以将注意力集中在使用库所需要的工程设置上。
 
方法 1: 头文件和库二进制文件
在本节中,你需要下载 starter project for this section。复制压缩文件到硬盘上的任意文件夹并解压。可以看到如下的文件夹结构:
 
为了方便起见,.a通用库文件和头文件已经复制了一份在其中,但工程并未设置使用它们。你将从这里开始。
 
注意: 标准的Unix引入惯例是一个include文件夹,用来存放头文件,一个lib文件夹用来存放库文件(.a)。这种文件夹结构这是一种惯例,并不强制。你并不需要一定遵从这种结构或者复制文件到工程文件夹中。在你自己的应用中,你可以任意选择头文件和库文件的位置,只要随后在Xcode工程中设置了适当的路径。
 
打开工程,构建并运行你的应用,将会看到以下错误:
 
正如所期望的那样,应用并不知道去哪里寻找头文件。为了解决这个问题,你需要在工程中添加一个Header Search Path,指明头文件存放的位置。设置头文件搜索路径始终是使用静态库的第一步。
 
按照下图示范,在导航栏中点击工程根节点(1),选择CoreImageFun目标(2)。选择Build Settings(3),在列表中找出Header Search Paths设置项。如果必要,可以在搜索框中输入”header search”来过滤庞大的设置列表(4)。
 
双击Header Search Paths项,弹出一个浮动窗口,点击+按钮,输入:
   
  1. $SOURCE_ROOT/include 
弹出窗口应该如下所示:
 
$SOURCE_ROOT是一个Xcode环境变量,指向工程根文件夹。Xcode会使用包含你工程的实际文件夹代替此变量,这意味着即使你把工程移动到其它文件夹或驱动器,它仍然可以指向最新的位置。
在弹出窗口范围外点击鼠标使其消失,你会看到Xcode已经自动将变量转换为工程的实际位置,如图所示:
 
构建并运行应用,看看结果是什么。呃……一些链接错误出现了:
 
这看起来并不是很好,但是给了你另一个你所需要的信息。仔细看,会发现所有的编译错误全都消失了,全部被链接错误所代替。这表示Xcode找到了头文件并且用它去编译应用,但在链接阶段,Xcode无法找到ImageFilter类的结果代码。为什么?
 
很简单 — 你还没有告诉Xcode去哪里寻找包含类实现的库文件。(看,没什么大不了)
 
如下面的屏幕截图所示,回到CoreImageFun目标(2)的构建设置(1)。选择Build Phases标签(3),展开Link Binary With Libraries部分(4)。最后,点击+按钮(5)。
 
在出现的窗口中,点击Add Other…按钮,在工程根文件夹下的lib子目录中找到libImageFilters.a库文件,如图:
 
完成这些以后,你的Build Phase标签看起来如下:
 
最后一步是增加-ObjC链接标识。该链接尝试更高效的只包含需要的代码,而有时会排除静态库代码。使用该标识,库中的所有Objective-C类和类别都将被适当的加载。你可以从苹果的 Technical Q&A QA1490了解详细信息。
 
点击Build Settings标签,找到Other linker Flags设置,如图:
 
在弹出窗口中,点击+按钮并输入-ObjC,如图:
 
最后构建并运行应用,此时应该不会得到任何构建错误信息,应用顺利展示它的光彩之处:
 
拖动滑块改变滤镜级别,或者点击GrayScale按钮。对图片应用滤镜的代码来自于静态库,而不是应用。
 
恭喜 — 你已经构建了你的第一个静态库并在一个真正的应用里使用它!你会发现这种包含头文件和库的方法在很多第三方库中使用,如AdMob,TestFlight或一些不提供源代码的商业库。
 
方法 2: 子项目
在这部分,请在 这里下载所需工程。
 
复制下载的文件到任意位置,解压。可以看到以下文件夹结构:
 
 
如果学习了方法一,你可能注意到了工程的差异。这个工程里没有任何的头文件和静态库文件 — 因为根本不需要。作为替代方案,你要将你在本教程开始创建的ImageFilters库工程添作为依赖加到本工程中。
在做这些之前,构建并运行应用。会看到以下错误:
 
如果学习过上一个方法,你已经知道如何修复这个问题。在示例工程中,你在ViewController类中使用了ImageFilters类,但并未告诉Xcode去哪里寻找头文件。Xcode会尝试寻找ImageFilters.h文件,但是失败了。
 
将ImageFilters库工程作为子项目所需的所有操作就是拖拽库工程文件到库文件树中。如果该工程已经在另一个Xcode窗口中被打开,那么Xcode无法正确将其添加为子工程。所以在继续本教程之前,确保ImageFilters库工程已经被关闭。
 
在Finder中找到名为ImageFilters.xcodeproj库工程文件。拖拽它到CoreImageFun工程左侧的导航栏中,如图:
 
完成拖放后,你的工程浏览视图应该如下图所示:
 
现在Xcode已经识别了子工程,你可以将库添加为工程依赖。这样Xcode就可以在构建主应用之前确保库为最新版本。
 
点击工程文件(1),选择CoreImageFun目标(2)。点击Build Phases标签(3)并展开Target Dependencies(4),如图:
 
点击+按钮增加一个新依赖。如下图所示,确保你从弹出窗口中选择了ImageFilters目标(不是universalLib):
 
添加完成之后,依赖窗口应该如图所示:
 
最后,设置静态库工程链接到应用。展开Link Binary with libraries,点击+按钮,如图:
 
选择libImageFilters.a,点击Add:
 
添加库之后,Link Binary with Libraries部分应该如图所示:
 
像方法一那样,最后一步是增加-ObjC链接标识。点击Build Settings标签,找到Other linker Flags设置,如图:
 
在弹出窗口中,点击+按钮并输入-ObjC,如图:
 
构建并运行应用,应该没有任何错误,应用会再一次被打开:
拖动滑块或者点击GrayScale按钮查看图片滤镜结果。滤镜逻辑的代码完全包含在库中。
 
如果按照第一种方法在应用中添加库(使用头文件和库文件),你可能注意到和第二种方法的区别。在方法二中,你没有在工程设置中添加任何头文件搜索路径。另一个区别是你没有使用通用库。
 
为什么会有这样的区别?当添加一个库作为一个子工程,Xcode会为你考虑几乎所有的事情。添加子工程和依赖后,Xcode知道去哪里寻找头文件和二进制文件,也知道根据你的设置去选择哪需要构建哪一个架构的库。这非常方便。
 
如果你使用你自己的库或者拥有源代码和工程文件,将库作为子工程不失为一个引入静态库的简便的方法。让你更容易作为工程依赖构建整合,并担心更少的事情。
 
未来
你可以从这里下载到包括了本教程所有代码的工程。
 
希望本教程能够让你对静态库的基本概念和怎样在应用中使用它们有一个更深入的了解。
 
下一步就是用所学到的知识构建你自己的库了。你肯定有一些添加到工程中通用类。它们是你加入你自己的可复用库的优秀候选人。你也可以考虑根据功能创建多个库:网络部分的代码作为一个,UI部分作为另一个,等等。你可以只向工程中添加所需要的代码。
 
为了强化和深入探讨你在本教程中所学到的概念,我推荐苹果的文档 Introduction to Using Static Libraries in iOS。

iOS项目中 Xcode 创建.a和framework静态库 最近在整理交接文档,看到之前写的项目需要封装成静态库,之前一直没时间整理,所以整理了一下创建静态库的步骤,做下记录。 一、库介绍 库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行。库分静态库和动态库两种。 iOS中的静态库有 .a 和 .framework两种形式;动态库有.dylib 和 .framework 形式,后来.dylib动态库又被苹果替换成.tbd的形式。 二、... 阅读详情

相关推荐

iOS-制作.a静态库SDK和使用.a静态库

一、创建静态项目创建一个新的工程,选择Framework & Library下面的Cocoa Touch Framework。二、在静态库中添加内容这里,我就把我自己平时封装的一个工具类拖进来。 三、设置对应的参数 Build Active Architecture Only选项设置 Build Setting里面的Build Active Architecture Only设置为NO。Buil

追求灵魂代码 6894

在iOS中创建静态库

本文由 Migrant [博客]翻译自 Creating a Static Library in iOS Tutorial。   如果您有不错的原创或译文,欢迎提交给我们,更欢迎其他朋友加入我们的翻译小组(联系qq:2408167315)。  ===================================================================

u010944926的专栏 759

iOS打包静态库framework,.a文件及bundle资源包的创建及使用

1.打包framework静态库 之前打包静态库好多步骤记不太清楚了,发现网上给的资料各种各样,好多坑不清楚,而且不太全面,所以自己整理了下资料,供大家参考,细节不足之处还望指正. 设置 Build Setting 中的 COMBINE_HIDPI_IMAGES 为 NO,否则 Bundle 中的图片就是 tiff 格式了。编译生成 Bundle 文件 • 我们分别选择 Generic iOS D.......................................

1692

iOS开发过程中出现错误整理

1、No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=armv7s, VALID_ARCHS=armv7 armv6). 今天上午开完会,一回来真机调试就报 No architectures to compile for (ONLY_ACTIVE_ARCH=YES, active arch=armv7s, VAL

Abel的专栏 1万+

iOS 静态库项目的创建与使用

在 “Build Settings” 中,找到 “Architectures” 选项,确保选择的是 “Standard Architectures”,如 arm64 和 armv7。在应用项目的 “Build Settings” 中,找到 “Search Paths”,将静态库文件的路径添加到 “Library Search Paths” 中。在 “Build Phases” 中,点击 “+”,选择 “New Copy Files Phase”,将静态库文件添加到 “Frameworks” 目录下。

DevScribe的博客 401

用Zotero+B站Kimi,我如何把一篇顶会论文快速做成组会PPT(含完整提示词)

本文介绍如何利用Zotero和Kimi快速将顶会论文转化为组会PPT,提升学术汇报效率。通过Zotero的文献管理插件和Kimi的AI提炼技术,实现从论文阅读到PPT生成的全流程自动化,帮助研究者在90分钟内完成高质量汇报准备。

weixin_30955617的博客 499

iOS之如何创建.a静态库

①、打开 Xcode 并创建一个新的 Xcode 项目。②、选择 "macOS" -> "Framework & Library" -> "Cocoa Touch Static Library"。③、命名你的项目,例如 "StaticLibrary"。④、选择合适的语言 (Swift 或 Objective-C)。

码农--xc 2067

VMD分子可视化实战:5个隐藏技巧让你的科研图像秒变顶刊级别

本文深入探讨了VMD分子可视化软件在科研图像美化中的5个高阶技巧,旨在帮助研究者将分子结构图提升至顶刊级别。内容涵盖原子色彩与材质的艺术化定制、沉浸式分子环境构建、专业构图与视角控制、数据驱动的动态可视化以及自动化工作流建立,通过精细的色彩映射、光照调整、周期性边界展示和脚本自动化,显著增强图像的科学叙事性与视觉冲击力。

weixin_29240343的博客 419

iOS之如何创建.framework静态库

iOS之如何创建.framework静态库

码农--xc 2412

2023年数学建模国赛三大赛题核心建模思路与实战代码全解

本文全面解析2023年数学建模国赛三大赛题的核心建模思路与实战代码,涵盖塔式太阳能光热发电系统优化、多波束测深系统动态规划及蔬菜商品化策略建模。通过Python代码示例和优化算法(如遗传算法、NSGA2)展示,帮助参赛者掌握数学建模的关键技术与实战技巧,提升竞赛成绩。

weixin_33713350的博客 331

淘宝抓包,直达函数内部request请求体和response响应体, 告别FD, Charles,SSL,justtrustme 等http代理,证书工具。

淘宝抓包,hook发包函数,直接获取response相应数据

binary66的博客 4468

ios 静态库合成_iOS中.a和.framework静态库的创建与.bundle资源包的使用详解

前言开发中经常使用三方库去实现某特定功能,而这些三方库通常又分为开源库和闭源库。开源库可以直接拿到源码,和自己写的没有什么区别,我们可以最大程度的修改源码来适应自己功能。闭源库就是被发布者提前打包好的静态库或 Bundle 包,对此我们无法看到内部实现,对于其封装好的特定功能,我们也只需要调用其开放的API即可。在正式的上代码之前,先介绍一些从网上搜集的静态库相关的基本概念,以加深对后面知识的理解...

weixin_39575047的博客 471

VMware虚拟机安装MS-DOS 7.10教程

dos安装教程dos版本7.10附下载链接。

Minecraft_xiaole的博客 1万+

iOS项目工程中创建静态库文件(.a)库文件

步骤1.创建工程HLStaticTest 步骤2.创建静态库文件 步骤3. 关闭HLStatic,回到HLStaticTest Targets - 》Build Phases ->Link Binary With Libraries 然后进

Dogg 1377

1、JMP脚本编程全面指南:从基础到高级应用

本博客全面介绍了JMP脚本编程的各个方面,从JMP基础和JSL入门,到数据类型、数据结构、编程方法、数据表操作、图形与三维场景脚本,再到应用程序创建与扩展功能。内容涵盖脚本工具使用、常见任务实现、兼容性说明及未来发展趋势,旨在帮助用户掌握JMP脚本语言的强大功能,提升数据分析的自动化与定制化能力。适合从初学者到高级用户的深入学习与实践参考。

flink9streamer的博客 266

2022中山大学计算机技术专硕考研初试、复试经验帖

个人简介 推荐几个我自己感觉对考研非常有帮助的小助手吧。可以帮助节省时间! 考研时间规划总览 初试篇 数学 英语 政治 408 复试篇 机试 笔试 面试 关于选导师 个人感言

zik的博客 1万+

ios c语言创建文件,iOS如何生成.a文件静态库

首先来谈谈为何要使用.a文件 Objective-c语言有.h .m 文件组成。静态库可以将 .m文件封装成一个.a文件,第三方应用程序只需要拿到这个.a文件和代码对应的.h文件即可使用静态库中封装的方法。IOS静态库适合去制作第三方提供的SD第一步1.首先创建一个新的工程,选择Framework&:,在选择Cocoa Touch Static Library 工程名自己定义2.接下来你会...

weixin_39715348的博客 289

如何使用事务码SMICM分析ABAP代码发起的HTTP请求的错误

当我用CL_HTTP_CLIENT往一个外网的url发请求时,遇到错误:ICM_HTTP_SSL_PEER_CERT_UNTRUSTED 错误是从这段ABAP代码里抛出来的: CALL METHOD lo_http_client-&gt;get_last_error IMPORTING code = lv_sysubrc message = ev_error_message. "BREAK-...

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 3206

ios .a静态库和framework静态库的创建以及使用

简介 什么是库? 库是程序代码的集合,是共享程序代码的一种方式 根据源代码的公开情况,库可以分为 2 种类型 开源库 公开源代码,能看到具体实现 比如 SDWebImage 、 AFNetworking 闭源库 不公开源代码,是经过编译后的二进制文件,看不到具体实现 主要分为:静态库、动态库 静态库和动态库 静态库和动态库的存在形式

冰清雪酷的专栏 643

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

深度学习工具包 DeepLearningToolbox

深度学习工具包Deprecation notice.-----This toolbox is outdated and no longer maintained.There are much better tools available for deep learning than this toolbox, e.g. [Theano](http://deeplearning.net/software/theano/), [torch](http://torch.ch/) or [tensorflow](http://www.tensorflow.org/)I would suggest you use one of the tools mentioned above rather than use this toolbox.Best, Rasmus.DeepLearnToolbox================A Matlab toolbox for Deep Learning.Deep Learning is a new subfield of machine learning that focuses on learning deep hierarchical models of data.It is inspired by the human brain's apparent deep (layered, hierarchical) architecture.A good overview of the theory of Deep Learning theory is[Learning Deep Architectures for AI](http://www.iro.umontreal.ca/~bengioy/papers/ftml_book.pdf)For a more informal introduction, see the following videos by Geoffrey Hinton and Andrew Ng.* [The Next Generation of Neural Networks](http://www.youtube.com/watch?v=AyzOUbkUf3M) (Hinton, 2007)* [Recent Developments in Deep Learning](http://www.youtube.com/watch?v=VdIURAu1-aU) (Hinton, 2010)* [Unsupervised Feature Learning and Deep Learning](http://www.youtube.com/watch?v=ZmNOAtZIgIk) (Ng, 2011)If you use this toolbox in your research please cite [Prediction as a candidate for learning deep hierarchical models of data](http://www2.imm.dtu.dk/pubdb/views/publication_details.php?id=6284)```@MASTERSTHESIS\{IMM2012-06284, author = "R. B. Palm", title = "Prediction as a candidate for learning deep hierarchical models of data", year = "2012",}```Contact: rasmusbergpalm at gmail dot comDirectories included in the toolbox-----------------------------------`NN/` - A library for Feedforward Backpropagation Neural Networks`CNN/` - A library for Convolutional Neural Networks`DBN/` - A library for Deep Belief Networks`SAE/` - A library for Stacked Auto-Encoders`CAE/` - A library for Convolutional Auto-Encoders`util/` - Utility functions used by the libraries`data/` - Data used by the examples`tests/` - unit tests to verify toolbox is workingFor references on each library check REFS.mdSetup-----1. Download.2. addpath(genpath('DeepLearnToolbox'));Example: Deep Belief Network---------------------```matlabfunction test_example_DBNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit RBM and visualize its weightsrand('state',0)dbn.sizes = [100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);figure; visualize(dbn.rbm{1}.W'); % Visualize the RBM weights%% ex2 train a 100-100 hidden unit DBN and use its weights to initialize a NNrand('state',0)%train dbndbn.sizes = [100 100];opts.numepochs = 1;opts.batchsize = 100;opts.momentum = 0;opts.alpha = 1;dbn = dbnsetup(dbn, train_x, opts);dbn = dbntrain(dbn, train_x, opts);%unfold dbn to nnnn = dbnunfoldtonn(dbn, 10);nn.activation_function = 'sigm';%train nnopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.10, 'Too big error');```Example: Stacked Auto-Encoders---------------------```matlabfunction test_example_SAEload mnist_uint8;train_x = double(train_x)/255;test_x = double(test_x)/255;train_y = double(train_y);test_y = double(test_y);%% ex1 train a 100 hidden unit SDAE and use it to initialize a FFNN% Setup and train a stacked denoising autoencoder (SDAE)rand('state',0)sae = saesetup([784 100]);sae.ae{1}.activation_function = 'sigm';sae.ae{1}.learningRate = 1;sae.ae{1}.inputZeroMaskedFraction = 0.5;opts.numepochs = 1;opts.batchsize = 100;sae = saetrain(sae, train_x, opts);visualize(sae.ae{1}.W{1}(:,2:end)')% Use the SDAE to initialize a FFNNnn = nnsetup([784 100 10]);nn.activation_function = 'sigm';nn.learningRate = 1;nn.W{1} = sae.ae{1}.W{1};% Train the FFNNopts.numepochs = 1;opts.batchsize = 100;nn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.16, 'Too big error');```Example: Convolutional Neural Nets---------------------```matlabfunction test_example_CNNload mnist_uint8;train_x = double(reshape(train_x',28,28,60000))/255;test_x = double(reshape(test_x',28,28,10000))/255;train_y = double(train_y');test_y = double(test_y');%% ex1 Train a 6c-2s-12c-2s Convolutional neural network %will run 1 epoch in about 200 second and get around 11% error. %With 100 epochs you'll get around 1.2% errorrand('state',0)cnn.layers = { struct('type', 'i') %input layer struct('type', 'c', 'outputmaps', 6, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %sub sampling layer struct('type', 'c', 'outputmaps', 12, 'kernelsize', 5) %convolution layer struct('type', 's', 'scale', 2) %subsampling layer};cnn = cnnsetup(cnn, train_x, train_y);opts.alpha = 1;opts.batchsize = 50;opts.numepochs = 1;cnn = cnntrain(cnn, train_x, train_y, opts);[er, bad] = cnntest(cnn, test_x, test_y);%plot mean squared errorfigure; plot(cnn.rL);assert(er<0.12, 'Too big error');```Example: Neural Networks---------------------```matlabfunction test_example_NNload mnist_uint8;train_x = double(train_x) / 255;test_x = double(test_x) / 255;train_y = double(train_y);test_y = double(test_y);% normalize[train_x, mu, sigma] = zscore(train_x);test_x = normalize(test_x, mu, sigma);%% ex1 vanilla neural netrand('state',0)nn = nnsetup([784 100 10]);opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samples[nn, L] = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.08, 'Too big error');%% ex2 neural net with L2 weight decayrand('state',0)nn = nnsetup([784 100 10]);nn.weightPenaltyL2 = 1e-4; % L2 weight decayopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex3 neural net with dropoutrand('state',0)nn = nnsetup([784 100 10]);nn.dropoutFraction = 0.5; % Dropout fraction opts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex4 neural net with sigmoid activation functionrand('state',0)nn = nnsetup([784 100 10]);nn.activation_function = 'sigm'; % Sigmoid activation functionnn.learningRate = 1; % Sigm require a lower learning rateopts.numepochs = 1; % Number of full sweeps through dataopts.batchsize = 100; % Take a mean gradient step over this many samplesnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex5 plotting functionalityrand('state',0)nn = nnsetup([784 20 10]);opts.numepochs = 5; % Number of full sweeps through datann.output = 'softmax'; % use softmax outputopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, train_x, train_y, opts);[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');%% ex6 neural net with sigmoid activation and plotting of validation and training error% split training data into training and validation datavx = train_x(1:10000,:);tx = train_x(10001:end,:);vy = train_y(1:10000,:);ty = train_y(10001:end,:);rand('state',0)nn = nnsetup([784 20 10]); nn.output = 'softmax'; % use softmax outputopts.numepochs = 5; % Number of full sweeps through dataopts.batchsize = 1000; % Take a mean gradient step over this many samplesopts.plot = 1; % enable plottingnn = nntrain(nn, tx, ty, opts, vx, vy); % nntrain takes validation set as last two arguments (optionally)[er, bad] = nntest(nn, test_x, test_y);assert(er < 0.1, 'Too big error');```[![Bitdeli Badge](https://d2weczhvl823v0.cloudfront.net/rasmusbergpalm/deeplearntoolbox/trend.png)](https://bitdeli.com/free "Bitdeli Badge")

iOS:Xcode7下创建 .a静态库 和 .framework静态库

Xcode7 中创建静态库:.a 和 .framework 一、简单介绍 1.什么是库?   库是程序代码的集合,是共享程序代码的一种方式 2.库的分类   根据源代码的公开情况,库可以分为2种类型   (1)开源库     公开源代码,能看到具体实现     比如SDWebImage、AFNetworking   (2)闭源库     不公开源代...

dienangpiao2051的博客 199

Statistics and Machine Learning Toolbox

Statistics and Machine Learning Toolbox(带书签),MATLAB统计学习工具

iOS 静态库(.a和.framework)创建

iOS程序中为了保持多个项目代码的互用或者提供自己代码给别人执行又不想暴露自己的源码,通常采用建立静态库或者动态库的方式,今天我就介绍下这两个库的建立以及使用 目录 一、.a库的创建以及使用: 1、基本创建: 2、oc工程调用: 3、swift工程调用: 二、.framework创建以及使用: 1、工程外创建引用 1.1、工程外创建: 1.2调用:直接framework包拖入调用...

wokuaab_q的博客 1260

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

iOS创建.a和.framework静态库,及Bundle资源文件的使用

引言 在开发中.framework静态库还是比较常见的,比如:SDK,公司间的代码合作等。我们可以把一些不愿意让别人见到的代码,用静态库的方式把它隐藏起来,只留下.h文件显示方法供编程人员使用。而.a文件出了静态库本身外,还需要引入.h文件,而.framework就不需要如此,由于.framework的方便性所以一般情况下我们见到的较多。 什么是库 库从本质上来说是一种可执行代码的二进制格式...

baidu_37366055的博客 1677

iOS 中 .a 和 .framework 静态库的创建与 .bundle 资源包的使用

iOS 中 .a 和 .framework 静态库的创建与 .bundle 资源包的使用 前言 开发中经常使用三方库去实现某特定功能,而这些三方库通常又分为开源库和闭源库。开源库可以直接拿到源码,和自己写的没有什么区别,我们可以最大程度的修改源码来适应自己功能。闭源库就是被发布者提前打包好的静态库或 Bundle 包,对此我们无法看到内部实现,对于其封装好的特定功能,我们也只需要调用其开放...

weixin_30471065的博客 170

Xcode6.4创建以及使用iOS.a的静态库

1.创建静态库 2.实现简单的静态库demo 3.command + B  编译下。成功则生成.a的静态库文件 4.找到文件,Window -> Projects -> MyLibrary OK,静态库生成完毕。 5.静态库的使用 方法一: 在项目中,Add Files to "XXX" 选中这两项,添加

lct710992308的博客 539
上一篇: iOS网络编程-http
下一篇: Xcode 6制作动态及静态Framework
直隶码农
博客等级 码龄19年 95粉丝 103原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值