Commit c9ac09dd authored by Kyle Fuller's avatar Kyle Fuller

Merge pull request #2835 from CocoaPods/swift

Support for Frameworks / Swift
parents 36ca914e c5a799f3
...@@ -6,8 +6,31 @@ To install release candidates run `[sudo] gem install cocoapods --pre` ...@@ -6,8 +6,31 @@ To install release candidates run `[sudo] gem install cocoapods --pre`
## Master ## Master
##### Highlighted Enhancement That Needs Testing
* Support Frameworks & Swift: CocoaPods now recognizes Swift source files and
builds dynamic frameworks when necessary. A project can explicitly
opt-in via `use_frameworks!` in the Podfile, or if any dependency contains
Swift code, all pods for that target will be integrated as frameworks.
As a pod author, you can change the module name of the built framework by
specifying a `module_name` in the podspec. The built frameworks are embedded into
the host application with a new shell script build phase in the user's
project allowing configuration-dependent pods.
[Marius Rackwitz](https://github.com/mrackwitz)
[#2835](https://github.com/CocoaPods/CocoaPods/issues/2835)
##### Breaking ##### Breaking
* Bundle Resources into Frameworks: Previously all resources were compiled and
copied into the `mainBundle`. Now Pods have to use
`[NSBundle bundleForClass:<#Class from Pod#>]` to access provided resources
relative to the bundle.
[Boris Bügling](https://github.com/neonichu)
[#2835](https://github.com/CocoaPods/CocoaPods/issues/2730)
* Only the hooks specified by usage of the `plugin` directive of the `Podfile` * Only the hooks specified by usage of the `plugin` directive of the `Podfile`
will be run. Additionally, plugins that depend on hooks will have to update to will be run. Additionally, plugins that depend on hooks will have to update to
specify their 'plugin name' when registering the hooks in order to make it specify their 'plugin name' when registering the hooks in order to make it
......
...@@ -7,7 +7,7 @@ GIT ...@@ -7,7 +7,7 @@ GIT
GIT GIT
remote: https://github.com/CocoaPods/Core.git remote: https://github.com/CocoaPods/Core.git
revision: c9c91c5296067ebf5af122ed87580e9f0479b47c revision: a01ba8e384324922bd173a415330b0a95fb13c5d
branch: master branch: master
specs: specs:
cocoapods-core (0.35.0) cocoapods-core (0.35.0)
......
![CocoaPods Logo](https://raw.github.com/CocoaPods/shared_resources/master/assets/cocoapods-banner-readme.png) ![CocoaPods Logo](https://raw.github.com/CocoaPods/shared_resources/master/assets/cocoapods-banner-readme.png)
### CocoaPods: The Objective-C dependency manager ### CocoaPods: The Cocoa dependency manager
[![Build Status](http://img.shields.io/travis/CocoaPods/CocoaPods/master.svg?style=flat)](https://travis-ci.org/CocoaPods/CocoaPods) [![Build Status](http://img.shields.io/travis/CocoaPods/CocoaPods/master.svg?style=flat)](https://travis-ci.org/CocoaPods/CocoaPods)
[![Gem Version](http://img.shields.io/gem/v/cocoapods.svg?style=flat)](http://badge.fury.io/rb/cocoapods) [![Gem Version](http://img.shields.io/gem/v/cocoapods.svg?style=flat)](http://badge.fury.io/rb/cocoapods)
......
...@@ -225,8 +225,12 @@ begin ...@@ -225,8 +225,12 @@ begin
desc "Build all examples" desc "Build all examples"
task :build do task :build do
Dir.chdir("examples/AFNetworking Example") do Bundler.require 'xcodeproj', :development
puts "Installing Pods" Dir['examples/*'].each do |dir|
Dir.chdir(dir) do
puts "Example: #{dir}"
puts " Installing Pods"
# pod_command = ENV['FROM_GEM'] ? 'sandbox-pod' : 'bundle exec ../../bin/sandbox-pod' # pod_command = ENV['FROM_GEM'] ? 'sandbox-pod' : 'bundle exec ../../bin/sandbox-pod'
# TODO: The sandbox is blocking local git repos making bundler crash # TODO: The sandbox is blocking local git repos making bundler crash
pod_command = ENV['FROM_GEM'] ? 'sandbox-pod' : 'bundle exec ../../bin/pod' pod_command = ENV['FROM_GEM'] ? 'sandbox-pod' : 'bundle exec ../../bin/pod'
...@@ -234,17 +238,26 @@ begin ...@@ -234,17 +238,26 @@ begin
execute_command "rm -rf Pods" execute_command "rm -rf Pods"
execute_command "#{pod_command} install --verbose --no-repo-update" execute_command "#{pod_command} install --verbose --no-repo-update"
puts "Building example: AFNetworking Mac Example" workspace_path = 'Examples.xcworkspace'
execute_command "xcodebuild -workspace 'AFNetworking Examples.xcworkspace' -scheme 'AFNetworking Example' clean build" workspace = Xcodeproj::Workspace.new_from_xcworkspace(workspace_path)
workspace.schemes.each do |scheme_name, project_path|
next if scheme_name == 'Pods'
puts " Building scheme: #{scheme_name}"
project = Xcodeproj::Project.open(project_path)
target = project.targets.first
puts "Building example: AFNetworking iOS Example" case target
when :osx
execute_command "xcodebuild -workspace '#{workspace_path}' -scheme '#{scheme_name}' clean build"
when :ios
xcode_version = `xcodebuild -version`.scan(/Xcode (.*)\n/).first.first xcode_version = `xcodebuild -version`.scan(/Xcode (.*)\n/).first.first
major_version = xcode_version.split('.').first.to_i major_version = xcode_version.split('.').first.to_i
# Specifically build against the simulator SDK so we don't have to deal with code signing. # Specifically build against the simulator SDK so we don't have to deal with code signing.
if major_version > 5 simulator_name = major_version > 5 ? 'iPhone 6' : 'iPhone Retina (4-inch)'
execute_command "xcodebuild -workspace 'AFNetworking Examples.xcworkspace' -scheme 'AFNetworking iOS Example' clean build ONLY_ACTIVE_ARCH=NO -destination 'platform=iOS Simulator,name=iPhone 6'" execute_command "xcodebuild -workspace '#{workspace_path}' -scheme '#{scheme_name}' clean build ONLY_ACTIVE_ARCH=NO -destination 'platform=iOS Simulator,name=#{simulator_name}"
else end
execute_command "xcodebuild -workspace 'AFNetworking Examples.xcworkspace' -scheme 'AFNetworking iOS Example' clean build ONLY_ACTIVE_ARCH=NO -destination 'platform=iOS Simulator,name=iPhone Retina (4-inch)'" end
end end
end end
end end
......
...@@ -11,7 +11,7 @@ Gem::Specification.new do |s| ...@@ -11,7 +11,7 @@ Gem::Specification.new do |s|
s.homepage = "https://github.com/CocoaPods/CocoaPods" s.homepage = "https://github.com/CocoaPods/CocoaPods"
s.authors = ["Eloy Duran", "Fabio Pelosin"] s.authors = ["Eloy Duran", "Fabio Pelosin"]
s.summary = "An Objective-C library package manager." s.summary = "The Cocoa library package manager."
s.description = "CocoaPods manages library dependencies for your Xcode project.\n\n" \ s.description = "CocoaPods manages library dependencies for your Xcode project.\n\n" \
"You specify the dependencies for your project in one easy text file. " \ "You specify the dependencies for your project in one easy text file. " \
"CocoaPods resolves dependencies between libraries, fetches source " \ "CocoaPods resolves dependencies between libraries, fetches source " \
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
objects = { objects = {
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
26E82B9975F54DA9BAC1E0C9 /* libPods-AFNetworking Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 6935B1E417A24F0E958977ED /* libPods-AFNetworking Example.a */; }; 1A2265312C5CBC89CD477BF8 /* libPods-AFNetworking Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 53BDE93051BED183E9F4D921 /* libPods-AFNetworking Example.a */; };
B304CCE8177D58DD00F4FC85 /* adn.cer in Resources */ = {isa = PBXBuildFile; fileRef = B304CCE7177D58DD00F4FC85 /* adn.cer */; }; B304CCE8177D58DD00F4FC85 /* adn.cer in Resources */ = {isa = PBXBuildFile; fileRef = B304CCE7177D58DD00F4FC85 /* adn.cer */; };
F8129C001591061B009BFE23 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8129BFF1591061B009BFE23 /* Cocoa.framework */; }; F8129C001591061B009BFE23 /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8129BFF1591061B009BFE23 /* Cocoa.framework */; };
F8129C321591073C009BFE23 /* AFAppDotNetAPIClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F8129C251591073C009BFE23 /* AFAppDotNetAPIClient.m */; }; F8129C321591073C009BFE23 /* AFAppDotNetAPIClient.m in Sources */ = {isa = PBXBuildFile; fileRef = F8129C251591073C009BFE23 /* AFAppDotNetAPIClient.m */; };
...@@ -20,7 +20,7 @@ ...@@ -20,7 +20,7 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
3C79D6B3AA6A1DBBAE48A944 /* Pods-AFNetworking Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking Example/Pods-AFNetworking Example.debug.xcconfig"; sourceTree = "<group>"; }; 3C79D6B3AA6A1DBBAE48A944 /* Pods-AFNetworking Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking Example/Pods-AFNetworking Example.debug.xcconfig"; sourceTree = "<group>"; };
6935B1E417A24F0E958977ED /* libPods-AFNetworking Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AFNetworking Example.a"; sourceTree = BUILT_PRODUCTS_DIR; }; 53BDE93051BED183E9F4D921 /* libPods-AFNetworking Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AFNetworking Example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
A67B777556EF5D95EAFA5CF8 /* Pods-AFNetworking Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking Example/Pods-AFNetworking Example.release.xcconfig"; sourceTree = "<group>"; }; A67B777556EF5D95EAFA5CF8 /* Pods-AFNetworking Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking Example/Pods-AFNetworking Example.release.xcconfig"; sourceTree = "<group>"; };
B304CCE7177D58DD00F4FC85 /* adn.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = adn.cer; sourceTree = SOURCE_ROOT; }; B304CCE7177D58DD00F4FC85 /* adn.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = adn.cer; sourceTree = SOURCE_ROOT; };
F8129BFB1591061B009BFE23 /* AFNetworking Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "AFNetworking Example.app"; sourceTree = BUILT_PRODUCTS_DIR; }; F8129BFB1591061B009BFE23 /* AFNetworking Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = "AFNetworking Example.app"; sourceTree = BUILT_PRODUCTS_DIR; };
...@@ -47,7 +47,7 @@ ...@@ -47,7 +47,7 @@
buildActionMask = 2147483647; buildActionMask = 2147483647;
files = ( files = (
F8129C001591061B009BFE23 /* Cocoa.framework in Frameworks */, F8129C001591061B009BFE23 /* Cocoa.framework in Frameworks */,
26E82B9975F54DA9BAC1E0C9 /* libPods-AFNetworking Example.a in Frameworks */, 1A2265312C5CBC89CD477BF8 /* libPods-AFNetworking Example.a in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
...@@ -90,7 +90,7 @@ ...@@ -90,7 +90,7 @@
children = ( children = (
F8129BFF1591061B009BFE23 /* Cocoa.framework */, F8129BFF1591061B009BFE23 /* Cocoa.framework */,
F8129C011591061B009BFE23 /* Other Frameworks */, F8129C011591061B009BFE23 /* Other Frameworks */,
6935B1E417A24F0E958977ED /* libPods-AFNetworking Example.a */, 53BDE93051BED183E9F4D921 /* libPods-AFNetworking Example.a */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -169,7 +169,7 @@ ...@@ -169,7 +169,7 @@
F8129BF21591061B009BFE23 /* Project object */ = { F8129BF21591061B009BFE23 /* Project object */ = {
isa = PBXProject; isa = PBXProject;
attributes = { attributes = {
LastUpgradeCheck = 0460; LastUpgradeCheck = 0610;
}; };
buildConfigurationList = F8129BF51591061B009BFE23 /* Build configuration list for PBXProject "AFNetworking Mac Example" */; buildConfigurationList = F8129BF51591061B009BFE23 /* Build configuration list for PBXProject "AFNetworking Mac Example" */;
compatibilityVersion = "Xcode 3.2"; compatibilityVersion = "Xcode 3.2";
...@@ -253,13 +253,16 @@ ...@@ -253,13 +253,16 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = NO; COPY_PHASE_STRIP = NO;
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_DYNAMIC_NO_PIC = NO; GCC_DYNAMIC_NO_PIC = NO;
GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_ENABLE_OBJC_EXCEPTIONS = YES;
...@@ -272,7 +275,9 @@ ...@@ -272,7 +275,9 @@
GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7; MACOSX_DEPLOYMENT_TARGET = 10.7;
ONLY_ACTIVE_ARCH = YES; ONLY_ACTIVE_ARCH = YES;
...@@ -284,20 +289,25 @@ ...@@ -284,20 +289,25 @@
isa = XCBuildConfiguration; isa = XCBuildConfiguration;
buildSettings = { buildSettings = {
ALWAYS_SEARCH_USER_PATHS = NO; ALWAYS_SEARCH_USER_PATHS = NO;
ARCHS = "$(ARCHS_STANDARD_64_BIT)";
CLANG_ENABLE_OBJC_ARC = YES; CLANG_ENABLE_OBJC_ARC = YES;
CLANG_WARN_BOOL_CONVERSION = YES;
CLANG_WARN_CONSTANT_CONVERSION = YES; CLANG_WARN_CONSTANT_CONVERSION = YES;
CLANG_WARN_EMPTY_BODY = YES;
CLANG_WARN_ENUM_CONVERSION = YES; CLANG_WARN_ENUM_CONVERSION = YES;
CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_INT_CONVERSION = YES;
CLANG_WARN_UNREACHABLE_CODE = YES;
CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
COPY_PHASE_STRIP = YES; COPY_PHASE_STRIP = YES;
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
ENABLE_STRICT_OBJC_MSGSEND = YES;
GCC_C_LANGUAGE_STANDARD = gnu99; GCC_C_LANGUAGE_STANDARD = gnu99;
GCC_ENABLE_OBJC_EXCEPTIONS = YES; GCC_ENABLE_OBJC_EXCEPTIONS = YES;
GCC_VERSION = com.apple.compilers.llvm.clang.1_0; GCC_VERSION = com.apple.compilers.llvm.clang.1_0;
GCC_WARN_64_TO_32_BIT_CONVERSION = YES; GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
GCC_WARN_ABOUT_RETURN_TYPE = YES; GCC_WARN_ABOUT_RETURN_TYPE = YES;
GCC_WARN_UNDECLARED_SELECTOR = YES;
GCC_WARN_UNINITIALIZED_AUTOS = YES; GCC_WARN_UNINITIALIZED_AUTOS = YES;
GCC_WARN_UNUSED_FUNCTION = YES;
GCC_WARN_UNUSED_VARIABLE = YES; GCC_WARN_UNUSED_VARIABLE = YES;
MACOSX_DEPLOYMENT_TARGET = 10.7; MACOSX_DEPLOYMENT_TARGET = 10.7;
SDKROOT = macosx; SDKROOT = macosx;
...@@ -313,6 +323,7 @@ ...@@ -313,6 +323,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Prefix.pch; GCC_PREFIX_HEADER = Prefix.pch;
INFOPLIST_FILE = "Mac-Info.plist"; INFOPLIST_FILE = "Mac-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app; WRAPPER_EXTENSION = app;
}; };
...@@ -327,6 +338,7 @@ ...@@ -327,6 +338,7 @@
GCC_PRECOMPILE_PREFIX_HEADER = YES; GCC_PRECOMPILE_PREFIX_HEADER = YES;
GCC_PREFIX_HEADER = Prefix.pch; GCC_PREFIX_HEADER = Prefix.pch;
INFOPLIST_FILE = "Mac-Info.plist"; INFOPLIST_FILE = "Mac-Info.plist";
LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/Frameworks";
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
WRAPPER_EXTENSION = app; WRAPPER_EXTENSION = app;
}; };
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0500" LastUpgradeVersion = "0610"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
......
...@@ -8,7 +8,7 @@ ...@@ -8,7 +8,7 @@
/* Begin PBXBuildFile section */ /* Begin PBXBuildFile section */
2982AD3217107C0000FFF048 /* adn.cer in Resources */ = {isa = PBXBuildFile; fileRef = 2982AD3117107C0000FFF048 /* adn.cer */; }; 2982AD3217107C0000FFF048 /* adn.cer in Resources */ = {isa = PBXBuildFile; fileRef = 2982AD3117107C0000FFF048 /* adn.cer */; };
E5D2E13908F241ABAC3B554B /* libPods-AFNetworking iOS Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = 9D87F8FEDE4A4313B0D579A3 /* libPods-AFNetworking iOS Example.a */; }; 9A67BEDAF4D3529C5380A3E2 /* libPods-AFNetworking iOS Example.a in Frameworks */ = {isa = PBXBuildFile; fileRef = DB1F7D464FF374F6931E274F /* libPods-AFNetworking iOS Example.a */; };
F8129C7415910C37009BFE23 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F8129C7215910C37009BFE23 /* AppDelegate.m */; }; F8129C7415910C37009BFE23 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = F8129C7215910C37009BFE23 /* AppDelegate.m */; };
F818101615E6A0C600EF93C2 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50ABD6EC159FC2CE001BE42C /* MobileCoreServices.framework */; }; F818101615E6A0C600EF93C2 /* MobileCoreServices.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 50ABD6EC159FC2CE001BE42C /* MobileCoreServices.framework */; };
F88812F016C533D6003C8B8C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469E013957DF100DB05C8 /* Security.framework */; }; F88812F016C533D6003C8B8C /* Security.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = F8E469E013957DF100DB05C8 /* Security.framework */; };
...@@ -35,11 +35,9 @@ ...@@ -35,11 +35,9 @@
/* Begin PBXFileReference section */ /* Begin PBXFileReference section */
2982AD3117107C0000FFF048 /* adn.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = adn.cer; sourceTree = SOURCE_ROOT; }; 2982AD3117107C0000FFF048 /* adn.cer */ = {isa = PBXFileReference; lastKnownFileType = file; path = adn.cer; sourceTree = SOURCE_ROOT; };
50ABD6EC159FC2CE001BE42C /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; }; 50ABD6EC159FC2CE001BE42C /* MobileCoreServices.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = MobileCoreServices.framework; path = System/Library/Frameworks/MobileCoreServices.framework; sourceTree = SDKROOT; };
5628C4E1DE6DDC806B14CF8D /* Pods-AFNetworking iOS Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking iOS Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking iOS Example.release.xcconfig"; sourceTree = "<group>"; };
7669B6F3267891B0317A0167 /* Pods-AFNetworking iOS Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking iOS Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking iOS Example/Pods-AFNetworking iOS Example.debug.xcconfig"; sourceTree = "<group>"; }; 7669B6F3267891B0317A0167 /* Pods-AFNetworking iOS Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking iOS Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking iOS Example/Pods-AFNetworking iOS Example.debug.xcconfig"; sourceTree = "<group>"; };
9D87F8FEDE4A4313B0D579A3 /* libPods-AFNetworking iOS Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AFNetworking iOS Example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
BEA3D3BDD12996573240F05F /* Pods-AFNetworking iOS Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking iOS Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking iOS Example/Pods-AFNetworking iOS Example.release.xcconfig"; sourceTree = "<group>"; }; BEA3D3BDD12996573240F05F /* Pods-AFNetworking iOS Example.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking iOS Example.release.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking iOS Example/Pods-AFNetworking iOS Example.release.xcconfig"; sourceTree = "<group>"; };
C3B414D5F7FCC5379A284B4E /* Pods-AFNetworking iOS Example.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-AFNetworking iOS Example.debug.xcconfig"; path = "Pods/Target Support Files/Pods-AFNetworking iOS Example.debug.xcconfig"; sourceTree = "<group>"; }; DB1F7D464FF374F6931E274F /* libPods-AFNetworking iOS Example.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = "libPods-AFNetworking iOS Example.a"; sourceTree = BUILT_PRODUCTS_DIR; };
F8129C3815910830009BFE23 /* Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Prefix.pch; sourceTree = SOURCE_ROOT; }; F8129C3815910830009BFE23 /* Prefix.pch */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Prefix.pch; sourceTree = SOURCE_ROOT; };
F8129C7215910C37009BFE23 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = SOURCE_ROOT; }; F8129C7215910C37009BFE23 /* AppDelegate.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = SOURCE_ROOT; };
F8129C7315910C37009BFE23 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = SOURCE_ROOT; }; F8129C7315910C37009BFE23 /* AppDelegate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = SOURCE_ROOT; };
...@@ -83,7 +81,7 @@ ...@@ -83,7 +81,7 @@
F8E469DF13957DD500DB05C8 /* CoreLocation.framework in Frameworks */, F8E469DF13957DD500DB05C8 /* CoreLocation.framework in Frameworks */,
F8D0701B14310F4A00653FD3 /* SystemConfiguration.framework in Frameworks */, F8D0701B14310F4A00653FD3 /* SystemConfiguration.framework in Frameworks */,
F818101615E6A0C600EF93C2 /* MobileCoreServices.framework in Frameworks */, F818101615E6A0C600EF93C2 /* MobileCoreServices.framework in Frameworks */,
E5D2E13908F241ABAC3B554B /* libPods-AFNetworking iOS Example.a in Frameworks */, 9A67BEDAF4D3529C5380A3E2 /* libPods-AFNetworking iOS Example.a in Frameworks */,
); );
runOnlyForDeploymentPostprocessing = 0; runOnlyForDeploymentPostprocessing = 0;
}; };
...@@ -93,8 +91,6 @@ ...@@ -93,8 +91,6 @@
9CE17E7C344B0E75BC0723EA /* Pods */ = { 9CE17E7C344B0E75BC0723EA /* Pods */ = {
isa = PBXGroup; isa = PBXGroup;
children = ( children = (
C3B414D5F7FCC5379A284B4E /* Pods-AFNetworking iOS Example.debug.xcconfig */,
5628C4E1DE6DDC806B14CF8D /* Pods-AFNetworking iOS Example.release.xcconfig */,
7669B6F3267891B0317A0167 /* Pods-AFNetworking iOS Example.debug.xcconfig */, 7669B6F3267891B0317A0167 /* Pods-AFNetworking iOS Example.debug.xcconfig */,
BEA3D3BDD12996573240F05F /* Pods-AFNetworking iOS Example.release.xcconfig */, BEA3D3BDD12996573240F05F /* Pods-AFNetworking iOS Example.release.xcconfig */,
); );
...@@ -169,7 +165,7 @@ ...@@ -169,7 +165,7 @@
F8E469641395739D00DB05C8 /* UIKit.framework */, F8E469641395739D00DB05C8 /* UIKit.framework */,
F8E469661395739D00DB05C8 /* Foundation.framework */, F8E469661395739D00DB05C8 /* Foundation.framework */,
F8E469681395739D00DB05C8 /* CoreGraphics.framework */, F8E469681395739D00DB05C8 /* CoreGraphics.framework */,
9D87F8FEDE4A4313B0D579A3 /* libPods-AFNetworking iOS Example.a */, DB1F7D464FF374F6931E274F /* libPods-AFNetworking iOS Example.a */,
); );
name = Frameworks; name = Frameworks;
sourceTree = "<group>"; sourceTree = "<group>";
...@@ -383,7 +379,7 @@ ...@@ -383,7 +379,7 @@
GCC_WARN_SIGN_COMPARE = YES; GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNUSED_PARAMETER = NO; GCC_WARN_UNUSED_PARAMETER = NO;
INFOPLIST_FILE = "iOS-Info.plist"; INFOPLIST_FILE = "iOS-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 5.0; IPHONEOS_DEPLOYMENT_TARGET = 8.0;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
WARNING_CFLAGS = ""; WARNING_CFLAGS = "";
WRAPPER_EXTENSION = app; WRAPPER_EXTENSION = app;
...@@ -404,7 +400,7 @@ ...@@ -404,7 +400,7 @@
GCC_WARN_SIGN_COMPARE = YES; GCC_WARN_SIGN_COMPARE = YES;
GCC_WARN_UNUSED_PARAMETER = NO; GCC_WARN_UNUSED_PARAMETER = NO;
INFOPLIST_FILE = "iOS-Info.plist"; INFOPLIST_FILE = "iOS-Info.plist";
IPHONEOS_DEPLOYMENT_TARGET = 5.0; IPHONEOS_DEPLOYMENT_TARGET = 8.0;
PRODUCT_NAME = "$(TARGET_NAME)"; PRODUCT_NAME = "$(TARGET_NAME)";
VALIDATE_PRODUCT = YES; VALIDATE_PRODUCT = YES;
WARNING_CFLAGS = ""; WARNING_CFLAGS = "";
......
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<Scheme <Scheme
LastUpgradeVersion = "0500" LastUpgradeVersion = "0610"
version = "1.3"> version = "1.3">
<BuildAction <BuildAction
parallelizeBuildables = "YES" parallelizeBuildables = "YES"
......
...@@ -25,6 +25,7 @@ ...@@ -25,6 +25,7 @@
#if __IPHONE_OS_VERSION_MIN_REQUIRED #if __IPHONE_OS_VERSION_MIN_REQUIRED
#import "GlobalTimelineViewController.h" #import "GlobalTimelineViewController.h"
#import <AFNetworking/AFNetworkActivityIndicatorManager.h>
#import "AFNetworkActivityIndicatorManager.h" #import "AFNetworkActivityIndicatorManager.h"
@implementation AppDelegate @implementation AppDelegate
......
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
xcodeproj "AFNetworking Mac Example.xcodeproj" xcodeproj "AFNetworking Mac Example.xcodeproj"
#### ####
workspace 'AFNetworking Examples.xcworkspace' workspace 'Examples.xcworkspace'
target "AFNetworking Example" do target "AFNetworking Example" do
platform :osx, '10.8' platform :osx, '10.8'
...@@ -11,7 +11,7 @@ target "AFNetworking Example" do ...@@ -11,7 +11,7 @@ target "AFNetworking Example" do
end end
target "AFNetworking iOS Example" do target "AFNetworking iOS Example" do
platform :ios, '7.0' platform :ios, '8.0'
xcodeproj "AFNetworking iOS Example.xcodeproj" xcodeproj "AFNetworking iOS Example.xcodeproj"
pod "AFNetworking", "1.3.3" pod "AFNetworking", "1.3.3"
end end
Pod::Spec.new do |s|
s.name = 'Alamofire'
s.version = '0.0.1'
s.license = 'MIT'
s.summary = 'Elegant HTTP Networking in Swift'
s.homepage = 'https://github.com/Alamofire/Alamofire'
s.social_media_url = 'http://twitter.com/mattt'
s.authors = { 'Mattt Thompson' => 'm@mattt.me' }
s.source = { :git => 'https://github.com/Alamofire/Alamofire.git', :branch => 'master' }
s.requires_arc = true
s.ios.deployment_target = '8.0'
s.osx.deployment_target = '10.10'
s.source_files = 'Source/*.swift'
end
// AppDelegate.swift
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import UIKit
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {
var window: UIWindow?
// MARK: - UIApplicationDelegate
func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
let splitViewController = self.window!.rootViewController as UISplitViewController
let navigationController = splitViewController.viewControllers.last as UINavigationController
navigationController.topViewController.navigationItem.leftBarButtonItem = splitViewController.displayModeButtonItem()
splitViewController.delegate = self
return true
}
// MARK: - UISplitViewControllerDelegate
func splitViewController(splitViewController: UISplitViewController!, collapseSecondaryViewController secondaryViewController:UIViewController!, ontoPrimaryViewController primaryViewController:UIViewController!) -> Bool {
if let secondaryAsNavController = secondaryViewController as? UINavigationController {
if let topAsDetailController = secondaryAsNavController.topViewController as? DetailViewController {
return topAsDetailController.request == nil
}
}
return false
}
}
This diff is collapsed.
// DetailViewController.swift
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import UIKit
import Alamofire
class DetailViewController: UITableViewController {
enum Sections: Int {
case Headers, Body
}
var request: Alamofire.Request? {
didSet {
oldValue?.cancel()
self.title = self.request?.description
self.refreshControl?.endRefreshing()
self.headers.removeAll()
self.body = nil
self.elapsedTime = nil
}
}
var headers: [String: String] = [:]
var body: String?
var elapsedTime: NSTimeInterval?
override func awakeFromNib() {
super.awakeFromNib()
self.refreshControl?.addTarget(self, action: "refresh", forControlEvents: .ValueChanged)
}
// MARK: - UIViewController
override func viewDidAppear(animated: Bool) {
super.viewDidAppear(animated)
self.refresh()
}
// MARK: - IBAction
@IBAction func refresh() {
if self.request == nil {
return
}
self.refreshControl?.beginRefreshing()
let start = CACurrentMediaTime()
self.request?.responseString { (request, response, body, error) in
let end = CACurrentMediaTime()
self.elapsedTime = end - start
for (field, value) in response!.allHeaderFields {
self.headers["\(field)"] = "\(value)"
}
self.body = body
self.tableView.reloadData()
self.refreshControl?.endRefreshing()
}
}
// MARK: UITableViewDataSource
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
switch Sections(rawValue: section)! {
case .Headers:
return self.headers.count
case .Body:
return self.body == nil ? 0 : 1
default:
return 0
}
}
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
switch Sections(rawValue: indexPath.section)! {
case .Headers:
let cell = self.tableView.dequeueReusableCellWithIdentifier("Header") as UITableViewCell
let field = self.headers.keys.array.sorted(<)[indexPath.row]
let value = self.headers[field]
cell.textLabel.text = field
cell.detailTextLabel!.text = value
return cell
case .Body:
let cell = self.tableView.dequeueReusableCellWithIdentifier("Body") as UITableViewCell
cell.textLabel.text = self.body
return cell
}
}
// MARK: UITableViewDelegate
override func numberOfSectionsInTableView(tableView: UITableView) -> Int {
return 2
}
override func tableView(tableView: UITableView, titleForHeaderInSection section: Int) -> String {
if self.tableView(tableView, numberOfRowsInSection: section) == 0 {
return ""
}
switch Sections(rawValue: section)! {
case .Headers:
return "Headers"
case .Body:
return "Body"
}
}
override func tableView(tableView: UITableView, heightForRowAtIndexPath indexPath: NSIndexPath) -> CGFloat {
switch Sections(rawValue: indexPath.section)! {
case .Body:
return 300
default:
return tableView.rowHeight
}
}
override func tableView(tableView: UITableView, titleForFooterInSection section: Int) -> String {
if Sections(rawValue: section)! == .Body && self.elapsedTime != nil {
let numberFormatter = NSNumberFormatter()
numberFormatter.numberStyle = .DecimalStyle
return "Elapsed Time: \(numberFormatter.stringFromNumber(self.elapsedTime!)) sec"
}
return ""
}
}
// MasterViewController.swift
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import Foundation
import Alamofire
enum HTTPBinRoute: URLStringConvertible {
case Method(Alamofire.Method)
case BasicAuth(String, String)
var URLString: String {
let baseURLString = "http://httpbin.org/"
let path: String = {
switch self {
case .Method(let method):
return "/\(method.rawValue.lowercaseString)"
case .BasicAuth(let user, let password):
return "/basic-auth/\(user)/\(password)"
}
}()
return NSURL(string: path, relativeToURL: NSURL(string: baseURLString))!.absoluteString!
}
}
{
"images" : [
{
"idiom" : "iphone",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "iphone",
"size" : "60x60",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "29x29",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "40x40",
"scale" : "2x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "1x"
},
{
"idiom" : "ipad",
"size" : "76x76",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"orientation" : "portrait",
"idiom" : "iphone",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "iphone",
"subtype" : "retina4",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "1x"
},
{
"orientation" : "portrait",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
},
{
"orientation" : "landscape",
"idiom" : "ipad",
"extent" : "full-screen",
"minimum-system-version" : "7.0",
"scale" : "2x"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
{
"images" : [
{
"idiom" : "universal",
"scale" : "1x",
"filename" : "Logo.png"
},
{
"idiom" : "universal",
"scale" : "2x",
"filename" : "Logo@2x.png"
}
],
"info" : {
"version" : 1,
"author" : "xcode"
}
}
\ No newline at end of file
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.alamofire.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>Alamofire</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>1</string>
<key>LSRequiresIPhoneOS</key>
<true/>
<key>UIMainStoryboardFile</key>
<string>Main</string>
<key>UIRequiredDeviceCapabilities</key>
<array>
<string>armv7</string>
</array>
<key>UIStatusBarTintParameters</key>
<dict>
<key>UINavigationBar</key>
<dict>
<key>Style</key>
<string>UIBarStyleDefault</string>
<key>Translucent</key>
<false/>
</dict>
</dict>
<key>UISupportedInterfaceOrientations</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
<key>UISupportedInterfaceOrientations~ipad</key>
<array>
<string>UIInterfaceOrientationPortrait</string>
<string>UIInterfaceOrientationPortraitUpsideDown</string>
<string>UIInterfaceOrientationLandscapeLeft</string>
<string>UIInterfaceOrientationLandscapeRight</string>
</array>
</dict>
</plist>
// MasterViewController.swift
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
import UIKit
import Alamofire
class MasterViewController: UITableViewController {
@IBOutlet weak var titleImageView: UIImageView!
var detailViewController: DetailViewController? = nil
var objects = NSMutableArray()
override func awakeFromNib() {
super.awakeFromNib()
self.navigationItem.titleView = self.titleImageView
}
// MARK: - UIViewController
override func viewDidLoad() {
super.viewDidLoad()
if let split = self.splitViewController {
let controllers = split.viewControllers
self.detailViewController = controllers.last?.topViewController as? DetailViewController
}
}
// MARK: - UIStoryboardSegue
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if let detailViewController = segue.destinationViewController.topViewController as? DetailViewController {
func requestForSegue(segue: UIStoryboardSegue) -> Request? {
switch segue.identifier as String! {
case "GET":
return Alamofire.request(.GET, "http://httpbin.org/get")
case "POST":
return Alamofire.request(.POST, "http://httpbin.org/post")
case "PUT":
return Alamofire.request(.PUT, "http://httpbin.org/put")
case "DELETE":
return Alamofire.request(.DELETE, "http://httpbin.org/delete")
default:
return nil
}
}
if let request = requestForSegue(segue) {
detailViewController.request = request
}
}
}
}
<?xml version="1.0" encoding="UTF-8"?>
<Workspace
version = "1.0">
<FileRef
location = "group:iOS Example.xcodeproj">
</FileRef>
<FileRef
location = "group:Pods/Pods.xcodeproj">
</FileRef>
</Workspace>
Copyright (c) 2014 Alamofire (http://alamofire.org/)
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
source 'https://github.com/CocoaPods/Specs.git'
workspace 'Examples.xcworkspace'
xcodeproj 'iOS Example.xcodeproj'
target 'iOS Example' do
platform :ios, '8.0'
use_frameworks!
pod 'Alamofire', :path => '.'
end
// Alamofire.h
//
// Copyright (c) 2014 Alamofire (http://alamofire.org)
//
// Permission is hereby granted, free of charge, to any person obtaining a copy
// of this software and associated documentation files (the "Software"), to deal
// in the Software without restriction, including without limitation the rights
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
// copies of the Software, and to permit persons to whom the Software is
// furnished to do so, subject to the following conditions:
//
// The above copyright notice and this permission notice shall be included in
// all copies or substantial portions of the Software.
//
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
// THE SOFTWARE.
#import <Foundation/Foundation.h>
FOUNDATION_EXPORT double AlamofireVersionNumber;
FOUNDATION_EXPORT const unsigned char AlamofireVersionString[];
This diff is collapsed.
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>com.alamofire.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
...@@ -56,9 +56,13 @@ module Pod ...@@ -56,9 +56,13 @@ module Pod
autoload :BridgeSupport, 'cocoapods/generator/bridge_support' autoload :BridgeSupport, 'cocoapods/generator/bridge_support'
autoload :CopyResourcesScript, 'cocoapods/generator/copy_resources_script' autoload :CopyResourcesScript, 'cocoapods/generator/copy_resources_script'
autoload :DummySource, 'cocoapods/generator/dummy_source' autoload :DummySource, 'cocoapods/generator/dummy_source'
autoload :EmbedFrameworksScript, 'cocoapods/generator/embed_frameworks_script'
autoload :Header, 'cocoapods/generator/header' autoload :Header, 'cocoapods/generator/header'
autoload :InfoPlistFile, 'cocoapods/generator/info_plist_file'
autoload :ModuleMap, 'cocoapods/generator/module_map'
autoload :PrefixHeader, 'cocoapods/generator/prefix_header' autoload :PrefixHeader, 'cocoapods/generator/prefix_header'
autoload :TargetEnvironmentHeader, 'cocoapods/generator/target_environment_header' autoload :TargetEnvironmentHeader, 'cocoapods/generator/target_environment_header'
autoload :UmbrellaHeader, 'cocoapods/generator/umbrella_header'
autoload :XCConfig, 'cocoapods/generator/xcconfig' autoload :XCConfig, 'cocoapods/generator/xcconfig'
end end
......
...@@ -28,7 +28,7 @@ module Pod ...@@ -28,7 +28,7 @@ module Pod
self.abstract_command = true self.abstract_command = true
self.command = 'pod' self.command = 'pod'
self.version = VERSION self.version = VERSION
self.description = 'CocoaPods, the Objective-C library package manager.' self.description = 'CocoaPods, the Cocoa library package manager.'
self.plugin_prefixes = %w(claide cocoapods) self.plugin_prefixes = %w(claide cocoapods)
[Install, Update, Outdated, IPC::Podfile, IPC::Repl].each { |c| c.send(:include, ProjectDirectory) } [Install, Update, Outdated, IPC::Podfile, IPC::Repl].each { |c| c.send(:include, ProjectDirectory) }
......
...@@ -113,6 +113,7 @@ module Pod ...@@ -113,6 +113,7 @@ module Pod
['--subspec=NAME', 'Lint validates only the given subspec'], ['--subspec=NAME', 'Lint validates only the given subspec'],
['--no-subspecs', 'Lint skips validation of subspecs'], ['--no-subspecs', 'Lint skips validation of subspecs'],
['--no-clean', 'Lint leaves the build directory intact for inspection'], ['--no-clean', 'Lint leaves the build directory intact for inspection'],
['--use-frameworks', 'Lint uses frameworks to install the spec'],
['--sources=https://github.com/artsy/Specs', 'The sources from which to pull dependant pods ' \ ['--sources=https://github.com/artsy/Specs', 'The sources from which to pull dependant pods ' \
'(defaults to https://github.com/CocoaPods/Specs.git). '\ '(defaults to https://github.com/CocoaPods/Specs.git). '\
'Multiple sources must be comma-delimited.']].concat(super) 'Multiple sources must be comma-delimited.']].concat(super)
...@@ -124,6 +125,7 @@ module Pod ...@@ -124,6 +125,7 @@ module Pod
@clean = argv.flag?('clean', true) @clean = argv.flag?('clean', true)
@subspecs = argv.flag?('subspecs', true) @subspecs = argv.flag?('subspecs', true)
@only_subspec = argv.option('subspec') @only_subspec = argv.option('subspec')
@use_frameworks = argv.flag?('use-frameworks')
@source_urls = argv.option('sources', 'https://github.com/CocoaPods/Specs.git').split(',') @source_urls = argv.option('sources', 'https://github.com/CocoaPods/Specs.git').split(',')
@podspecs_paths = argv.arguments! @podspecs_paths = argv.arguments!
super super
...@@ -144,6 +146,7 @@ module Pod ...@@ -144,6 +146,7 @@ module Pod
validator.allow_warnings = @allow_warnings validator.allow_warnings = @allow_warnings
validator.no_subspecs = !@subspecs || @only_subspec validator.no_subspecs = !@subspecs || @only_subspec
validator.only_subspec = @only_subspec validator.only_subspec = @only_subspec
validator.use_frameworks = @use_frameworks
validator.validate validator.validate
unless @clean unless @clean
......
...@@ -68,6 +68,7 @@ module Pod ...@@ -68,6 +68,7 @@ module Pod
['--subspec=NAME', 'Lint validates only the given subspec'], ['--subspec=NAME', 'Lint validates only the given subspec'],
['--no-subspecs', 'Lint skips validation of subspecs'], ['--no-subspecs', 'Lint skips validation of subspecs'],
['--no-clean', 'Lint leaves the build directory intact for inspection'], ['--no-clean', 'Lint leaves the build directory intact for inspection'],
['--use-frameworks', 'Lint uses frameworks to install the spec'],
['--sources=https://github.com/artsy/Specs', 'The sources from which to pull dependant pods ' \ ['--sources=https://github.com/artsy/Specs', 'The sources from which to pull dependant pods ' \
'(defaults to https://github.com/CocoaPods/Specs.git). '\ '(defaults to https://github.com/CocoaPods/Specs.git). '\
'Multiple sources must be comma-delimited.']].concat(super) 'Multiple sources must be comma-delimited.']].concat(super)
...@@ -79,6 +80,7 @@ module Pod ...@@ -79,6 +80,7 @@ module Pod
@clean = argv.flag?('clean', true) @clean = argv.flag?('clean', true)
@subspecs = argv.flag?('subspecs', true) @subspecs = argv.flag?('subspecs', true)
@only_subspec = argv.option('subspec') @only_subspec = argv.option('subspec')
@use_frameworks = argv.flag?('use-frameworks')
@source_urls = argv.option('sources', 'https://github.com/CocoaPods/Specs.git').split(',') @source_urls = argv.option('sources', 'https://github.com/CocoaPods/Specs.git').split(',')
@podspecs_paths = argv.arguments! @podspecs_paths = argv.arguments!
super super
...@@ -94,6 +96,7 @@ module Pod ...@@ -94,6 +96,7 @@ module Pod
validator.allow_warnings = @allow_warnings validator.allow_warnings = @allow_warnings
validator.no_subspecs = !@subspecs || @only_subspec validator.no_subspecs = !@subspecs || @only_subspec
validator.only_subspec = @only_subspec validator.only_subspec = @only_subspec
validator.use_frameworks = @use_frameworks
validator.validate validator.validate
invalid_count += 1 unless validator.validated? invalid_count += 1 unless validator.validated?
...@@ -580,8 +583,8 @@ Pod::Spec.new do |s| ...@@ -580,8 +583,8 @@ Pod::Spec.new do |s|
# ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― # # ――― Source Code ―――――――――――――――――――――――――――――――――――――――――――――――――――――――――――――― #
# #
# CocoaPods is smart about how it includes source code. For source files # CocoaPods is smart about how it includes source code. For source files
# giving a folder will include any h, m, mm, c & cpp files. For header # giving a folder will include any swift, h, m, mm, c & cpp files.
# files it will include any header in the folder. # For header files it will include any header in the folder.
# Not including the public_header_files will make all headers public. # Not including the public_header_files will make all headers public.
# #
......
...@@ -264,7 +264,7 @@ module Pod ...@@ -264,7 +264,7 @@ module Pod
'CocoaPods.podfile.yaml', 'CocoaPods.podfile.yaml',
'CocoaPods.podfile', 'CocoaPods.podfile',
'Podfile', 'Podfile',
] ].freeze
public public
......
module Pod
module Generator
class EmbedFrameworksScript
# @return [TargetDefinition] The target definition, whose label will be
# used to locate the target-specific build products.
#
attr_reader :target_definition
# @return [Hash{String, Array{String}] Multiple lists of frameworks per
# configuration.
#
attr_reader :frameworks_by_config
# @param [TargetDefinition] target_definition
# @see #target_definition
#
# @param [Hash{String, Array{String}] frameworks_by_config
# @see #frameworks_by_config
#
def initialize(target_definition, frameworks_by_config)
@target_definition = target_definition
@frameworks_by_config = frameworks_by_config
end
# Saves the resource script to the given pathname.
#
# @param [Pathname] pathname
# The path where the embed frameworks script should be saved.
#
# @return [void]
#
def save_as(pathname)
pathname.open('w') do |file|
file.puts(script)
end
File.chmod(0755, pathname.to_s)
end
private
# @!group Private Helpers
# @return [String] The contents of the embed frameworks script.
#
def script
script = <<-eos.strip_heredoc
#!/bin/sh
set -e
echo "mkdir -p ${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
mkdir -p "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
SWIFT_STDLIB_PATH="${DT_TOOLCHAIN_DIR}/usr/lib/swift/${PLATFORM_NAME}"
install_framework()
{
local source="${BUILT_PRODUCTS_DIR}/#{target_definition.label}/$1"
local destination="${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}"
if [ -L ${source} ]; then
echo "Symlinked..."
source=$(readlink "${source}")
fi
# use filter instead of exclude so missing patterns dont' throw errors
echo "rsync -av --filter \"- CVS/\" --filter \"- .svn/\" --filter \"- .git/\" --filter \"- .hg/\" --filter \"- Headers/\" --filter \"- PrivateHeaders/\" ${source} ${destination}"
rsync -av --filter "- CVS/" --filter "- .svn/" --filter "- .git/" --filter "- .hg/" --filter "- Headers/" --filter "- PrivateHeaders/" "${source}" "${destination}"
# Resign the code if required by the build settings to avoid unstable apps
if [ "${CODE_SIGNING_REQUIRED}" == "YES" ]; then
code_sign "${destination}/$1"
fi
# Embed linked Swift runtime libraries
local basename
basename=$(echo $1 | sed -E s/\\\\..+// && exit ${PIPESTATUS[0]})
local swift_runtime_libs
swift_runtime_libs=$(xcrun otool -LX "${CONFIGURATION_BUILD_DIR}/${FRAMEWORKS_FOLDER_PATH}/$1/${basename}" | grep @rpath/libswift | sed -E s/@rpath\\\\/\\(.+dylib\\).*/\\\\1/g | uniq -u && exit ${PIPESTATUS[0]})
for lib in $swift_runtime_libs; do
echo "rsync -av \\"${SWIFT_STDLIB_PATH}/${lib}\\" \\"${destination}\\""
rsync -av "${SWIFT_STDLIB_PATH}/${lib}" "${destination}"
done
}
# Signs a framework with the provided identity
code_sign() {
# Use the current code_sign_identitiy
echo "Code Signing $1 with Identity ${EXPANDED_CODE_SIGN_IDENTITY_NAME}"
echo "/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements $1"
/usr/bin/codesign --force --sign ${EXPANDED_CODE_SIGN_IDENTITY} --preserve-metadata=identifier,entitlements "$1"
}
eos
script += "\n" unless frameworks_by_config.values.all?(&:empty?)
frameworks_by_config.each do |config, frameworks|
unless frameworks.empty?
script += %(if [[ "$CONFIGURATION" == "#{config}" ]]; then\n)
frameworks.each do |framework|
script += " install_framework '#{framework}'\n"
end
script += "fi\n"
end
end
script
end
end
end
end
...@@ -13,7 +13,11 @@ module Pod ...@@ -13,7 +13,11 @@ module Pod
# @return [Array<String>] The list of the headers to import. # @return [Array<String>] The list of the headers to import.
# #
attr_reader :imports attr_accessor :imports
# @return [Array<String>] The list of the modules to import.
#
attr_accessor :module_imports
# @param [Symbol] platform # @param [Symbol] platform
# @see platform # @see platform
...@@ -21,6 +25,7 @@ module Pod ...@@ -21,6 +25,7 @@ module Pod
def initialize(platform) def initialize(platform)
@platform = platform @platform = platform
@imports = [] @imports = []
@module_imports = []
end end
# Generates the contents of the header according to the platform. # Generates the contents of the header according to the platform.
...@@ -41,6 +46,13 @@ module Pod ...@@ -41,6 +46,13 @@ module Pod
result << %|#import "#{import}"\n| result << %|#import "#{import}"\n|
end end
unless module_imports.empty?
module_imports.each do |import|
result << %|\n@import #{import}|
end
result << "\n"
end
result result
end end
......
module Pod
module Generator
# Generates Info.plist files. A Info.plist file is generated for each
# Pod and for each Pod target definition, that requires to be built as
# framework. It states public attributes.
#
class InfoPlistFile
# @return [Target] the target represented by this Info.plist.
#
attr_reader :target
# @param [Target] target @see target
#
def initialize(target)
@target = target
end
# Generates and saves the Info.plist to the given path.
#
# @param [Pathname] path
# the path where the prefix header should be stored.
#
# @return [void]
#
def save_as(path)
contents = generate
path.open('w') do |f|
f.write(contents)
end
end
# The version associated with the current target
#
# @note Will return 1.0.0 for the AggregateTarget
#
# @return [String]
#
def target_version
if target && target.respond_to?(:root_spec)
target.root_spec.version.to_s
else
'1.0.0'
end
end
# Generates the contents of the Info.plist
#
# @return [String]
#
def generate
FILE_CONTENTS.sub('${CURRENT_PROJECT_VERSION_STRING}', target_version)
end
FILE_CONTENTS = <<-EOS
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>${EXECUTABLE_NAME}</string>
<key>CFBundleIdentifier</key>
<string>org.cocoapods.${PRODUCT_NAME:rfc1034identifier}</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>${PRODUCT_NAME}</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>${CURRENT_PROJECT_VERSION_STRING}</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>${CURRENT_PROJECT_VERSION}</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
EOS
end
end
end
module Pod
module Generator
# Generates LLVM module map files. A module map file is generated for each
# Pod and for each Pod target definition that is built as a framework. It
# specifies a different umbrella header than usual to avoid name conflicts
# with existing headers of the podspec.
#
class ModuleMap
# @return [Target] the target represented by this Info.plist.
#
attr_reader :target
# @param [Target] target @see target
#
def initialize(target)
@target = target
end
# Generates and saves the Info.plist to the given path.
#
# @param [Pathname] path
# the path where the prefix header should be stored.
#
# @return [void]
#
def save_as(path)
contents = generate
path.open('w') do |f|
f.write(contents)
end
end
# Generates the contents of the module.modulemap file.
#
# @return [String]
#
def generate
<<-eos.strip_heredoc
framework module #{target.product_module_name} {
umbrella header "#{target.umbrella_header_path.basename}"
export *
module * { export * }
}
eos
end
end
end
end
module Pod
module Generator
# Generates an umbrella header file for clang modules, which are used by
# dynamic frameworks on iOS 8 and OSX 10.10 under the hood.
#
# If the target is a +PodTarget+, then the umbrella header is required
# to make all public headers in a convenient manner available without the
# need to write out header declarations for every library header.
#
class UmbrellaHeader < Header
# @return [Target]
# the target, which provides the product name
attr_reader :target
# @param [Target] target
# @see target
#
def initialize(target)
super(target.target_definition.platform)
@target = target
end
# Generates the contents of the umbrella header according to the included
# pods.
#
# @return [String]
#
def generate
result = super
result << "\n"
result << <<-eos.strip_heredoc
FOUNDATION_EXPORT double #{target.product_module_name}VersionNumber;
FOUNDATION_EXPORT const unsigned char #{target.product_module_name}VersionString[];
eos
result << "\n"
result
end
end
end
end
...@@ -47,34 +47,58 @@ module Pod ...@@ -47,34 +47,58 @@ module Pod
# @return [Xcodeproj::Config] # @return [Xcodeproj::Config]
# #
def generate def generate
header_search_path_flags = target.sandbox.public_headers.search_paths(target.platform) pod_targets = target.pod_targets_for_build_configuration(@configuration_name)
@xcconfig = Xcodeproj::Config.new( config = {
'OTHER_LDFLAGS' => XCConfigHelper.default_ld_flags(target), 'OTHER_LDFLAGS' => XCConfigHelper.default_ld_flags(target),
'OTHER_LIBTOOLFLAGS' => '$(OTHER_LDFLAGS)', 'OTHER_LIBTOOLFLAGS' => '$(OTHER_LDFLAGS)',
'HEADER_SEARCH_PATHS' => XCConfigHelper.quote(header_search_path_flags),
'PODS_ROOT' => target.relative_pods_root, 'PODS_ROOT' => target.relative_pods_root,
'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1', 'GCC_PREPROCESSOR_DEFINITIONS' => '$(inherited) COCOAPODS=1',
'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_path_flags, '-isystem') }
)
target.pod_targets.each do |pod_target| if target.requires_frameworks?
next unless pod_target.include_in_build_config?(@configuration_name) # Framework headers are automatically discoverable by `#import <…>`.
header_search_paths = pod_targets.map { |target| "$PODS_FRAMEWORK_BUILD_PATH/#{target.product_name}/Headers" }
build_settings = {
'PODS_FRAMEWORK_BUILD_PATH' => target.configuration_build_dir,
'FRAMEWORK_SEARCH_PATHS' => '"$PODS_FRAMEWORK_BUILD_PATH"',
# Make headers discoverable by `import "…"`
'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-iquote')
}
config.merge!(build_settings)
else
# Make headers discoverable from $PODS_ROOT/Headers directory
header_search_paths = target.sandbox.public_headers.search_paths(target.platform)
build_settings = {
# by `#import "…"`
'HEADER_SEARCH_PATHS' => XCConfigHelper.quote(header_search_paths),
# by `#import <…>`
'OTHER_CFLAGS' => '$(inherited) ' + XCConfigHelper.quote(header_search_paths, '-isystem')
}
config.merge!(build_settings)
end
@xcconfig = Xcodeproj::Config.new(config)
XCConfigHelper.add_target_specific_settings(target, @xcconfig)
pod_target.file_accessors.each do |file_accessor| pod_targets.each do |pod_target|
XCConfigHelper.add_spec_build_settings_to_xcconfig(file_accessor.spec_consumer, @xcconfig) unless pod_target.should_build? && pod_target.requires_frameworks?
file_accessor.vendored_frameworks.each do |vendored_framework| # In case of generated pod targets, which require frameworks, the
XCConfigHelper.add_framework_build_settings(vendored_framework, @xcconfig, target.sandbox.root) # vendored frameworks and libraries are already linked statically
# into the framework binary and must not be linked again to the
# user target.
XCConfigHelper.add_settings_for_file_accessors_of_target(pod_target, @xcconfig)
end end
file_accessor.vendored_libraries.each do |vendored_library|
XCConfigHelper.add_library_build_settings(vendored_library, @xcconfig, target.sandbox.root) # Add pod target to list of frameworks / libraries that are
# linked with the user’s project.
if pod_target.should_build?
if pod_target.requires_frameworks?
@xcconfig.merge!('OTHER_LDFLAGS' => %(-framework "#{pod_target.product_basename}"))
else
@xcconfig.merge!('OTHER_LDFLAGS' => %(-l "#{pod_target.product_basename}"))
end end
end end
# Add pod static lib to list of libraries that are to be linked with
# the user’s project.
next unless pod_target.should_build?
@xcconfig.merge!('OTHER_LDFLAGS' => %(-l "#{pod_target.name}"))
end end
# TODO Need to decide how we are going to ensure settings like these # TODO Need to decide how we are going to ensure settings like these
...@@ -83,9 +107,30 @@ module Pod ...@@ -83,9 +107,30 @@ module Pod
# See https://github.com/CocoaPods/CocoaPods/issues/1216 # See https://github.com/CocoaPods/CocoaPods/issues/1216
@xcconfig.attributes.delete('USE_HEADERMAP') @xcconfig.attributes.delete('USE_HEADERMAP')
generate_ld_runpath_search_paths if target.requires_frameworks?
@xcconfig @xcconfig
end end
def generate_ld_runpath_search_paths
ld_runpath_search_paths = ['$(inherited)']
if target.platform.symbolic_name == :osx
ld_runpath_search_paths << "'@executable_path/../Frameworks'"
ld_runpath_search_paths << \
if target.native_target.symbol_type == :unit_test_bundle
"'@loader_path/../Frameworks'"
else
"'@loader_path/Frameworks'"
end
else
ld_runpath_search_paths << [
"'@executable_path/Frameworks'",
"'@loader_path/Frameworks'"
]
end
@xcconfig.merge!('LD_RUNPATH_SEARCH_PATHS' => ld_runpath_search_paths.join(' '))
end
#---------------------------------------------------------------------# #---------------------------------------------------------------------#
end end
end end
......
...@@ -57,8 +57,20 @@ module Pod ...@@ -57,8 +57,20 @@ module Pod
# 'USE_HEADERMAP' => 'NO' # 'USE_HEADERMAP' => 'NO'
} }
if target.requires_frameworks?
# Only quote the FRAMEWORK_SEARCH_PATHS entry, because it’s a setting that takes multiple values.
# In addition, quoting CONFIGURATION_BUILD_DIR would make it be interpreted as a relative path.
build_settings = {
'PODS_FRAMEWORK_BUILD_PATH' => target.configuration_build_dir,
'CONFIGURATION_BUILD_DIR' => '$PODS_FRAMEWORK_BUILD_PATH',
'FRAMEWORK_SEARCH_PATHS' => '"$PODS_FRAMEWORK_BUILD_PATH"',
}
config.merge!(build_settings)
end
xcconfig_hash = add_xcconfig_namespaced_keys(public_xcconfig.to_hash, config, target.xcconfig_prefix) xcconfig_hash = add_xcconfig_namespaced_keys(public_xcconfig.to_hash, config, target.xcconfig_prefix)
@xcconfig = Xcodeproj::Config.new(xcconfig_hash) @xcconfig = Xcodeproj::Config.new(xcconfig_hash)
XCConfigHelper.add_target_specific_settings(target, @xcconfig)
@xcconfig.includes = [target.name] @xcconfig.includes = [target.name]
@xcconfig @xcconfig
end end
......
...@@ -40,15 +40,7 @@ module Pod ...@@ -40,15 +40,7 @@ module Pod
# #
def generate def generate
@xcconfig = Xcodeproj::Config.new @xcconfig = Xcodeproj::Config.new
target.file_accessors.each do |file_accessor| XCConfigHelper.add_settings_for_file_accessors_of_target(target, @xcconfig)
XCConfigHelper.add_spec_build_settings_to_xcconfig(file_accessor.spec_consumer, @xcconfig)
file_accessor.vendored_frameworks.each do |vendored_framework|
XCConfigHelper.add_framework_build_settings(vendored_framework, @xcconfig, target.sandbox.root)
end
file_accessor.vendored_libraries.each do |vendored_library|
XCConfigHelper.add_library_build_settings(vendored_library, @xcconfig, target.sandbox.root)
end
end
@xcconfig @xcconfig
end end
......
...@@ -33,6 +33,26 @@ module Pod ...@@ -33,6 +33,26 @@ module Pod
ld_flags ld_flags
end end
# Configures the given Xcconfig
#
# @param [PodTarget] pod_target
# The pod target, which holds the list of +Spec::FileAccessor+.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
def self.add_settings_for_file_accessors_of_target(target, xcconfig)
target.file_accessors.each do |file_accessor|
XCConfigHelper.add_spec_build_settings_to_xcconfig(file_accessor.spec_consumer, xcconfig)
file_accessor.vendored_frameworks.each do |vendored_framework|
XCConfigHelper.add_framework_build_settings(vendored_framework, xcconfig, target.sandbox.root)
end
file_accessor.vendored_libraries.each do |vendored_library|
XCConfigHelper.add_library_build_settings(vendored_library, xcconfig, target.sandbox.root)
end
end
end
# Configures the given Xcconfig according to the build settings of the # Configures the given Xcconfig according to the build settings of the
# given Specification. # given Specification.
# #
...@@ -59,6 +79,9 @@ module Pod ...@@ -59,6 +79,9 @@ module Pod
# @param [Xcodeproj::Config] xcconfig # @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit. # The xcconfig to edit.
# #
# @param [Pathname] sandbox_root
# The path retrieved from Sandbox#root.
#
def self.add_framework_build_settings(framework_path, xcconfig, sandbox_root) def self.add_framework_build_settings(framework_path, xcconfig, sandbox_root)
name = File.basename(framework_path, '.framework') name = File.basename(framework_path, '.framework')
dirname = '$(PODS_ROOT)/' + framework_path.dirname.relative_path_from(sandbox_root).to_s dirname = '$(PODS_ROOT)/' + framework_path.dirname.relative_path_from(sandbox_root).to_s
...@@ -70,7 +93,7 @@ module Pod ...@@ -70,7 +93,7 @@ module Pod
end end
# Configures the given Xcconfig with the the build settings for the given # Configures the given Xcconfig with the the build settings for the given
# framework path. # library path.
# #
# @param [Pathanme] framework_path # @param [Pathanme] framework_path
# The path of the framework. # The path of the framework.
...@@ -78,6 +101,9 @@ module Pod ...@@ -78,6 +101,9 @@ module Pod
# @param [Xcodeproj::Config] xcconfig # @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit. # The xcconfig to edit.
# #
# @param [Pathname] sandbox_root
# The path retrieved from Sandbox#root.
#
def self.add_library_build_settings(library_path, xcconfig, sandbox_root) def self.add_library_build_settings(library_path, xcconfig, sandbox_root)
name = File.basename(library_path, '.a').sub(/\Alib/, '') name = File.basename(library_path, '.a').sub(/\Alib/, '')
dirname = '$(PODS_ROOT)/' + library_path.dirname.relative_path_from(sandbox_root).to_s dirname = '$(PODS_ROOT)/' + library_path.dirname.relative_path_from(sandbox_root).to_s
...@@ -88,6 +114,58 @@ module Pod ...@@ -88,6 +114,58 @@ module Pod
xcconfig.merge!(build_settings) xcconfig.merge!(build_settings)
end end
# Add the code signing settings for generated targets to ensure that
# frameworks are correctly signed to be integrated and re-signed when
# building the application and embedding the framework
#
# @param [Target] target
# The target.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
def self.add_code_signing_settings(target, xcconfig)
build_settings = {}
if target.platform.to_sym == :osx
build_settings['CODE_SIGN_IDENTITY'] = ''
end
xcconfig.merge!(build_settings)
end
# Checks if the given target requires specific settings and configures
# the given Xcconfig.
#
# @param [Target] target
# The target.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
def self.add_target_specific_settings(target, xcconfig)
if target.requires_frameworks?
add_code_signing_settings(target, xcconfig)
end
add_language_specific_settings(target, xcconfig)
end
# Checks if the given target requires language specific settings and
# configures the given Xcconfig.
#
# @param [Target] target
# The target.
#
# @param [Xcodeproj::Config] xcconfig
# The xcconfig to edit.
#
def self.add_language_specific_settings(target, xcconfig)
if target.uses_swift?
build_settings = {
'OTHER_SWIFT_FLAGS' => quote(['-D COCOAPODS']),
}
xcconfig.merge!(build_settings)
end
end
# Adds the search paths of the developer frameworks to the specification # Adds the search paths of the developer frameworks to the specification
# if needed. This is done because the `SenTestingKit` requires them and # if needed. This is done because the `SenTestingKit` requires them and
# adding them to each specification which requires it is repetitive and # adding them to each specification which requires it is repetitive and
......
...@@ -89,6 +89,7 @@ module Pod ...@@ -89,6 +89,7 @@ module Pod
prepare prepare
resolve_dependencies resolve_dependencies
download_dependencies download_dependencies
determine_dependency_product_types
generate_pods_project generate_pods_project
integrate_user_project if config.integrate_targets? integrate_user_project if config.integrate_targets?
perform_post_install_actions perform_post_install_actions
...@@ -311,6 +312,21 @@ module Pod ...@@ -311,6 +312,21 @@ module Pod
@pod_installers.each(&:clean!) @pod_installers.each(&:clean!)
end end
# Determines if the dependencies need to be built as dynamic frameworks or
# if they can be built as static libraries by checking for the Swift source
# presence. Therefore it is important that the file accessors of the
# #pod_targets are created.
#
# @return [void]
#
def determine_dependency_product_types
aggregate_targets.each do |aggregate_target|
aggregate_target.pod_targets.each do |pod_target|
pod_target.host_requires_frameworks = aggregate_target.requires_frameworks?
end
end
end
# Performs any post-installation actions # Performs any post-installation actions
# #
# @return [void] # @return [void]
...@@ -444,7 +460,13 @@ module Pod ...@@ -444,7 +460,13 @@ module Pod
end end
end end
# Adds a target dependency for each pod spec to each aggregate target and
# links the pod targets among each other.
#
# @return [void]
#
def set_target_dependencies def set_target_dependencies
frameworks_group = pods_project.frameworks_group
aggregate_targets.each do |aggregate_target| aggregate_targets.each do |aggregate_target|
aggregate_target.pod_targets.each do |pod_target| aggregate_target.pod_targets.each do |pod_target|
unless pod_target.should_build? unless pod_target.should_build?
...@@ -464,7 +486,15 @@ module Pod ...@@ -464,7 +486,15 @@ module Pod
unless pod_dependency_target unless pod_dependency_target
puts "[BUG] DEP: #{dep}" puts "[BUG] DEP: #{dep}"
end end
next unless pod_dependency_target.should_build?
pod_target.native_target.add_dependency(pod_dependency_target.native_target) pod_target.native_target.add_dependency(pod_dependency_target.native_target)
if pod_target.requires_frameworks?
product_ref = frameworks_group.files.find { |f| f.path == pod_dependency_target.product_name } ||
frameworks_group.new_product_ref_for_target(pod_dependency_target.product_basename, pod_dependency_target.product_type)
pod_target.native_target.frameworks_build_phase.add_file_reference(product_ref)
end
end end
end end
end end
......
...@@ -180,8 +180,25 @@ module Pod ...@@ -180,8 +180,25 @@ module Pod
def generate_targets def generate_targets
targets = [] targets = []
result.specs_by_target.each do |target_definition, specs| result.specs_by_target.each do |target_definition, specs|
targets << generate_target(target_definition, specs)
end
targets
end
# Setup the aggregate target for a single user target
#
# @param [TargetDefinition] target_definition
# the target definition for the user target.
#
# @param [Array<Specification>] specs
# the specifications that need to be installed grouped by the
# given target definition.
#
# @return [AggregateTarget]
#
def generate_target(target_definition, specs)
target = AggregateTarget.new(target_definition, sandbox) target = AggregateTarget.new(target_definition, sandbox)
targets << target target.host_requires_frameworks |= target_definition.uses_frameworks?
if config.integrate_targets? if config.integrate_targets?
project_path = compute_user_project_path(target_definition) project_path = compute_user_project_path(target_definition)
...@@ -202,25 +219,53 @@ module Pod ...@@ -202,25 +219,53 @@ module Pod
end end
end end
grouped_specs = specs.map do |spec| target.pod_targets = generate_pod_targets(target, specs)
specs.select { |s| s.root == spec.root }
end.uniq target
end
# Setup the pod targets for an aggregate target. Group specs and subspecs
# by their root to create a {PodTarget} for each spec.
#
# @param [AggregateTarget] target
# the aggregate target
#
# @param [Array<Specification>] specs
# the specifications that need to be installed.
#
# @return [Array<PodTarget>]
#
def generate_pod_targets(target, specs)
grouped_specs = specs.group_by(&:root).values.uniq
grouped_specs.map do |pod_specs|
generate_pod_target(target, pod_specs)
end
end
# Create a target for each spec group and add it to the aggregate target
#
# @param [AggregateTarget] target
# the aggregate target
#
# @param [Array<Specification>] specs
# the specifications of an equal root.
#
# @return [PodTarget]
#
def generate_pod_target(target, pod_specs)
pod_target = PodTarget.new(pod_specs, target.target_definition, sandbox)
grouped_specs.each do |pod_specs|
pod_target = PodTarget.new(pod_specs, target_definition, sandbox)
if config.integrate_targets? if config.integrate_targets?
pod_target.user_build_configurations = target.user_build_configurations pod_target.user_build_configurations = target.user_build_configurations
pod_target.archs = @archs_by_target_def[target_definition] pod_target.archs = @archs_by_target_def[target.target_definition]
else else
pod_target.user_build_configurations = {} pod_target.user_build_configurations = {}
if target_definition.platform.name == :osx if target.platform.name == :osx
pod_target.archs = '$(ARCHS_STANDARD_64_BIT)' pod_target.archs = '$(ARCHS_STANDARD_64_BIT)'
end end
end end
target.pod_targets << pod_target
end pod_target
end
targets
end end
# Generates dependencies that require the specific version of the Pods # Generates dependencies that require the specific version of the Pods
...@@ -515,6 +560,37 @@ module Pod ...@@ -515,6 +560,37 @@ module Pod
end end
end end
# Checks if any of the targets for the {TargetDefinition} computed before
# by #compute_user_project_targets require to be build as a framework due
# the presence of Swift source code in any of the source build phases.
#
# @param [TargetDefinition] target_definition
# the target definition
#
# @param [Array<PBXNativeTarget>] native_targets
# the targets which are checked for presence of Swift source code
#
# @return [Boolean] Whether the user project targets to integrate into
# uses Swift
#
def compute_user_project_targets_require_framework(target_definition, native_targets)
file_predicate = nil
file_predicate = proc do |file_ref|
if file_ref.respond_to?(:last_known_file_type)
file_ref.last_known_file_type == 'sourcecode.swift'
elsif file_ref.respond_to?(:files)
file_ref.files.any?(&file_predicate)
else
false
end
end
target_definition.platform.supports_dynamic_frameworks? || native_targets.any? do |target|
target.source_build_phase.files.any? do |build_file|
file_predicate.call(build_file.file_ref)
end
end
end
# @return [Hash{String=>Symbol}] A hash representing the user build # @return [Hash{String=>Symbol}] A hash representing the user build
# configurations where each key corresponds to the name of a # configurations where each key corresponds to the name of a
# configuration and its value to its type (`:debug` or `:release`). # configuration and its value to its type (`:debug` or `:release`).
......
...@@ -36,25 +36,47 @@ module Pod ...@@ -36,25 +36,47 @@ module Pod
# @return [void] # @return [void]
# #
def add_target def add_target
product_type = target.product_type
name = target.label name = target.label
platform = target.platform.name platform = target.platform.name
deployment_target = target.platform.deployment_target.to_s deployment_target = target.platform.deployment_target.to_s
@native_target = project.new_target(:static_library, name, platform, deployment_target) @native_target = project.new_target(product_type, name, platform, deployment_target)
product_name = target.product_name
product = @native_target.product_reference
product.name = product_name
product.path = product_name
target.user_build_configurations.each do |bc_name, type| target.user_build_configurations.each do |bc_name, type|
configuration = @native_target.add_build_configuration(bc_name, type) configuration = @native_target.add_build_configuration(bc_name, type)
end end
settings = { 'OTHER_LDFLAGS' => '', 'OTHER_LIBTOOLFLAGS' => '' } @native_target.build_configurations.each do |configuration|
configuration.build_settings.merge!(custom_build_settings)
end
target.native_target = @native_target
end
# Returns the customized build settings which are overridden in the build
# settings of the user target.
#
# @return [Hash{String => String}]
#
def custom_build_settings
settings = {}
if target.archs if target.archs
settings['ARCHS'] = target.archs settings['ARCHS'] = target.archs
end end
@native_target.build_configurations.each do |configuration| if target.requires_frameworks?
configuration.build_settings.merge!(settings) settings['PRODUCT_NAME'] = target.product_module_name
else
settings.merge!('OTHER_LDFLAGS' => '', 'OTHER_LIBTOOLFLAGS' => '')
end end
target.native_target = @native_target settings
end end
# Creates the directory where to store the support files of the target. # Creates the directory where to store the support files of the target.
...@@ -63,6 +85,68 @@ module Pod ...@@ -63,6 +85,68 @@ module Pod
target.support_files_dir.mkdir target.support_files_dir.mkdir
end end
# Creates the Info.plist file which sets public framework attributes
#
# @return [void]
#
def create_info_plist_file
path = target.info_plist_path
UI.message "- Generating Info.plist file at #{UI.path(path)}" do
generator = Generator::InfoPlistFile.new(target)
generator.save_as(path)
add_file_to_support_group(path)
native_target.build_configurations.each do |c|
relative_path = path.relative_path_from(sandbox.root)
c.build_settings['INFOPLIST_FILE'] = relative_path.to_s
end
end
end
# Creates the module map file which ensures that the umbrella header is
# recognized with a customized path
#
# @return [void]
#
def create_module_map
path = target.module_map_path
UI.message "- Generating module map file at #{UI.path(path)}" do
generator = Generator::ModuleMap.new(target)
generator.save_as(path)
add_file_to_support_group(path)
native_target.build_configurations.each do |c|
relative_path = path.relative_path_from(sandbox.root)
c.build_settings['MODULEMAP_FILE'] = relative_path.to_s
end
end
end
# Generates a header which ensures that all header files are exported
# in the module map
#
# @yield_param [Generator::UmbrellaHeader]
# yielded once to configure the imports
#
def create_umbrella_header
path = target.umbrella_header_path
UI.message "- Generating umbrella header at #{UI.path(path)}" do
generator = Generator::UmbrellaHeader.new(target)
yield generator if block_given?
generator.save_as(path)
# Add the file to the support group and the native target,
# so it will been added to the header build phase
file_ref = add_file_to_support_group(path)
native_target.add_file_references([file_ref])
# Make the umbrella header public
build_file = native_target.headers_build_phase.build_file(file_ref)
build_file.settings ||= {}
build_file.settings['ATTRIBUTES'] = ['Public']
end
end
# Generates a dummy source file for each target so libraries that contain # Generates a dummy source file for each target so libraries that contain
# only categories build. # only categories build.
# #
......
...@@ -12,8 +12,14 @@ module Pod ...@@ -12,8 +12,14 @@ module Pod
UI.message "- Installing target `#{target.name}` #{target.platform}" do UI.message "- Installing target `#{target.name}` #{target.platform}" do
add_target add_target
create_support_files_dir create_support_files_dir
create_suport_files_group create_support_files_group
create_xcconfig_file create_xcconfig_file
if target.requires_frameworks?
create_info_plist_file
create_module_map
create_umbrella_header
create_embed_frameworks_script
end
create_target_environment_header create_target_environment_header
create_bridge_support_file create_bridge_support_file
create_copy_resources_script create_copy_resources_script
...@@ -26,12 +32,25 @@ module Pod ...@@ -26,12 +32,25 @@ module Pod
private private
# Ensure that vendored static frameworks and libraries are not linked
# twice to the aggregate target, which shares the xcconfig of the user
# target.
#
def custom_build_settings
settings = {
'OTHER_LDFLAGS' => '',
'OTHER_LIBTOOLFLAGS' => '',
'PODS_ROOT' => '$(SRCROOT)',
}
super.merge(settings)
end
# Creates the group that holds the references to the support files # Creates the group that holds the references to the support files
# generated by this installer. # generated by this installer.
# #
# @return [void] # @return [void]
# #
def create_suport_files_group def create_support_files_group
parent = project.support_files_group parent = project.support_files_group
name = target.name name = target.name
dir = target.support_files_dir dir = target.support_files_dir
...@@ -92,9 +111,12 @@ module Pod ...@@ -92,9 +111,12 @@ module Pod
# #
def create_copy_resources_script def create_copy_resources_script
path = target.copy_resources_script_path path = target.copy_resources_script_path
file_accessors = target.pod_targets.map(&:file_accessors).flatten library_targets = target.pod_targets.reject do |pod_target|
resource_paths = file_accessors.map { |accessor| accessor.resources.flatten.map { |res| res.relative_path_from(project.path.dirname) } }.flatten pod_target.should_build? && pod_target.requires_frameworks?
resource_bundles = file_accessors.map { |accessor| accessor.resource_bundles.keys.map { |name| "${BUILT_PRODUCTS_DIR}/#{name}.bundle" } }.flatten end
file_accessors = library_targets.flat_map(&:file_accessors)
resource_paths = file_accessors.flat_map { |accessor| accessor.resources.flat_map { |res| res.relative_path_from(project.path.dirname) } }
resource_bundles = file_accessors.flat_map { |accessor| accessor.resource_bundles.keys.map { |name| "${BUILT_PRODUCTS_DIR}/#{name}.bundle" } }
resources = [] resources = []
resources.concat(resource_paths) resources.concat(resource_paths)
resources.concat(resource_bundles) resources.concat(resource_bundles)
...@@ -104,6 +126,28 @@ module Pod ...@@ -104,6 +126,28 @@ module Pod
add_file_to_support_group(path) add_file_to_support_group(path)
end end
# Creates a script that embeds the frameworks to the bundle of the client
# target.
#
# @note We can't use Xcode default copy bundle resource phase, because
# we need to ensure that we only copy the resources, which are
# relevant for the current build configuration.
#
# @return [void]
#
def create_embed_frameworks_script
path = target.embed_frameworks_script_path
frameworks_by_config = {}
target.user_build_configurations.keys.each do |config|
frameworks_by_config[config] = target.pod_targets.select do |pod_target|
pod_target.include_in_build_config?(config) && pod_target.should_build?
end.map(&:product_name)
end
generator = Generator::EmbedFrameworksScript.new(target_definition, frameworks_by_config)
generator.save_as(path)
add_file_to_support_group(path)
end
# Generates the acknowledgement files (markdown and plist) for the target. # Generates the acknowledgement files (markdown and plist) for the target.
# #
# @return [void] # @return [void]
......
...@@ -17,9 +17,16 @@ module Pod ...@@ -17,9 +17,16 @@ module Pod
UI.message "- Installing target `#{target.name}` #{target.platform}" do UI.message "- Installing target `#{target.name}` #{target.platform}" do
add_target add_target
create_support_files_dir create_support_files_dir
add_files_to_build_phases
add_resources_bundle_targets add_resources_bundle_targets
add_files_to_build_phases
create_xcconfig_file create_xcconfig_file
if target.requires_frameworks?
create_info_plist_file
create_module_map
create_umbrella_header do |generator|
generator.imports += target.file_accessors.flat_map(&:public_headers).map(&:basename)
end
end
create_prefix_header create_prefix_header
create_dummy_source create_dummy_source
end end
...@@ -41,20 +48,41 @@ module Pod ...@@ -41,20 +48,41 @@ module Pod
target.file_accessors.each do |file_accessor| target.file_accessors.each do |file_accessor|
consumer = file_accessor.spec_consumer consumer = file_accessor.spec_consumer
headers = file_accessor.headers
public_headers = file_accessor.public_headers
other_source_files = file_accessor.source_files.select { |sf| sf.extname == '.d' } other_source_files = file_accessor.source_files.select { |sf| sf.extname == '.d' }
{ {
true => file_accessor.arc_source_files, true => file_accessor.arc_source_files,
false => file_accessor.non_arc_source_files, false => file_accessor.non_arc_source_files,
}.each do |arc, files| }.each do |arc, files|
files = files - other_source_files files = files - headers - other_source_files
flags = compiler_flags_for_consumer(consumer, arc) flags = compiler_flags_for_consumer(consumer, arc)
regular_file_refs = files.map { |sf| project.reference_for_path(sf) } regular_file_refs = files.map { |sf| project.reference_for_path(sf) }
native_target.add_file_references(regular_file_refs, flags) native_target.add_file_references(regular_file_refs, flags)
end end
header_file_refs = headers.map { |sf| project.reference_for_path(sf) }
native_target.add_file_references(header_file_refs) do |build_file|
# Set added headers as public if needed
if target.requires_frameworks?
if public_headers.include?(build_file.file_ref.real_path)
build_file.settings ||= {}
build_file.settings['ATTRIBUTES'] = ['Public']
end
end
end
other_file_refs = other_source_files.map { |sf| project.reference_for_path(sf) } other_file_refs = other_source_files.map { |sf| project.reference_for_path(sf) }
native_target.add_file_references(other_file_refs, nil) native_target.add_file_references(other_file_refs, nil)
next unless target.requires_frameworks?
resource_refs = file_accessor.resources.flatten.map do |res|
project.reference_for_path(res)
end
native_target.add_resources(resource_refs)
end end
end end
...@@ -68,23 +96,34 @@ module Pod ...@@ -68,23 +96,34 @@ module Pod
def add_resources_bundle_targets def add_resources_bundle_targets
target.file_accessors.each do |file_accessor| target.file_accessors.each do |file_accessor|
file_accessor.resource_bundles.each do |bundle_name, paths| file_accessor.resource_bundles.each do |bundle_name, paths|
# Add a dependency on an existing Resource Bundle target if possible
bundle_target = project.targets.find { |target| target.name == bundle_name }
unless bundle_target
file_references = paths.map { |sf| project.reference_for_path(sf) } file_references = paths.map { |sf| project.reference_for_path(sf) }
bundle_target = project.new_resources_bundle(bundle_name, file_accessor.spec_consumer.platform_name) label = target.resources_bundle_target_label(bundle_name)
bundle_target = project.new_resources_bundle(label, file_accessor.spec_consumer.platform_name)
bundle_target.product_reference.tap do |bundle_product|
bundle_file_name = "#{bundle_name}.bundle"
bundle_product.name = bundle_file_name
bundle_product.path = bundle_file_name
end
bundle_target.add_resources(file_references) bundle_target.add_resources(file_references)
target.user_build_configurations.each do |bc_name, type| target.user_build_configurations.each do |bc_name, type|
bundle_target.add_build_configuration(bc_name, type) bundle_target.add_build_configuration(bc_name, type)
end end
end
target.resource_bundle_targets << bundle_target target.resource_bundle_targets << bundle_target
if target.should_build? if target.should_build?
native_target.add_dependency(bundle_target) native_target.add_dependency(bundle_target)
if target.requires_frameworks?
native_target.add_resources([bundle_target.product_reference])
end
end
bundle_target.build_configurations.each do |c|
c.build_settings['PRODUCT_NAME'] = bundle_name
if target.requires_frameworks?
c.build_settings['CONFIGURATION_BUILD_DIR'] = target.configuration_build_dir
end
end end
end end
end end
......
...@@ -132,7 +132,8 @@ module Pod ...@@ -132,7 +132,8 @@ module Pod
end end
end end
INHERITED_FLAGS = ['$(inherited)', '${inherited}'] IGNORED_KEYS = %w(CODE_SIGN_IDENTITY).freeze
INHERITED_FLAGS = %w($(inherited) ${inherited}).freeze
# Checks whether the settings of the CocoaPods generated xcconfig are # Checks whether the settings of the CocoaPods generated xcconfig are
# overridden by the build configuration of a target and prints a # overridden by the build configuration of a target and prints a
...@@ -144,7 +145,7 @@ module Pod ...@@ -144,7 +145,7 @@ module Pod
user_target.build_configurations.each do |config| user_target.build_configurations.each do |config|
xcconfig = aggregate_target.xcconfigs[config.name] xcconfig = aggregate_target.xcconfigs[config.name]
if xcconfig if xcconfig
xcconfig.to_hash.keys.each do |key| (xcconfig.to_hash.keys - IGNORED_KEYS).each do |key|
target_values = config.build_settings[key] target_values = config.build_settings[key]
if target_values && if target_values &&
!INHERITED_FLAGS.any? { |flag| target_values.include?(flag) } !INHERITED_FLAGS.any? { |flag| target_values.include?(flag) }
......
...@@ -31,8 +31,10 @@ module Pod ...@@ -31,8 +31,10 @@ module Pod
project_is_dirty = [ project_is_dirty = [
XCConfigIntegrator.integrate(target, native_targets), XCConfigIntegrator.integrate(target, native_targets),
update_to_cocoapods_0_34, update_to_cocoapods_0_34,
remove_embed_frameworks_script_phases,
unless native_targets_to_integrate.empty? unless native_targets_to_integrate.empty?
add_pods_library add_pods_library
add_embed_frameworks_script_phase if target.requires_frameworks?
add_copy_resources_script_phase add_copy_resources_script_phase
add_check_manifest_lock_script_phase add_check_manifest_lock_script_phase
true true
...@@ -91,9 +93,9 @@ module Pod ...@@ -91,9 +93,9 @@ module Pod
changes changes
end end
# Adds spec libraries to the frameworks build phase of the # Adds spec product reference to the frameworks build phase of the
# {TargetDefinition} integration libraries. Adds a file reference to # {TargetDefinition} integration libraries. Adds a file reference to
# the library of the {TargetDefinition} and adds it to the frameworks # the frameworks group of the project and adds it to the frameworks
# build phase of the targets. # build phase of the targets.
# #
# @return [void] # @return [void]
...@@ -101,12 +103,71 @@ module Pod ...@@ -101,12 +103,71 @@ module Pod
def add_pods_library def add_pods_library
frameworks = user_project.frameworks_group frameworks = user_project.frameworks_group
native_targets_to_integrate.each do |native_target| native_targets_to_integrate.each do |native_target|
library = frameworks.files.select { |f| f.path == target.product_name }.first || build_phase = native_target.frameworks_build_phase
frameworks.new_product_ref_for_target(target.name, :static_library)
unless native_target.frameworks_build_phase.files_references.include?(library) # Find and delete possible reference for the other product type
native_target.frameworks_build_phase.add_file_reference(library) old_product_name = target.requires_frameworks? ? target.static_library_name : target.framework_name
old_product_ref = frameworks.files.find { |f| f.path == old_product_name }
if old_product_ref.present?
UI.message("Removing old Pod product reference #{old_product_name} from project.")
build_phase.remove_file_reference(old_product_ref)
frameworks.remove_reference(old_product_ref)
end
# Find or create and add a reference for the current product type
target_basename = target.product_basename
new_product_ref = frameworks.files.find { |f| f.path == target.product_name } ||
frameworks.new_product_ref_for_target(target_basename, target.product_type)
build_file = build_phase.build_file(new_product_ref) ||
build_phase.add_file_reference(new_product_ref)
if target.requires_frameworks?
# Weak link the aggregate target's product, because as it contains
# no symbols, it isn't copied into the app bundle. dyld will so
# never try to find the missing executable at runtime.
build_file.settings ||= {}
build_file.settings['ATTRIBUTES'] = ['Weak']
end
end
end
# Find or create a 'Embed Pods Frameworks' Copy Files Build Phase
#
# @return [void]
#
def add_embed_frameworks_script_phase
phase_name = 'Embed Pods Frameworks'
native_targets_to_integrate.each do |native_target|
embed_build_phase = native_target.shell_script_build_phases.find { |bp| bp.name == phase_name }
unless embed_build_phase.present?
UI.message("Adding Build Phase '#{phase_name}' to project.")
embed_build_phase = native_target.new_shell_script_build_phase(phase_name)
end
script_path = target.embed_frameworks_script_relative_path
embed_build_phase.shell_script = %("#{script_path}"\n)
embed_build_phase.show_env_vars_in_log = '0'
end
end end
# Delete 'Embed Pods Frameworks' Build Phases, if they exist
# and are not needed anymore due to not integrating the
# dependencies by frameworks.
#
# @return [Bool] whether any changes to the project were made.
#
def remove_embed_frameworks_script_phases
return false if target.requires_frameworks?
phase_name = 'Embed Pods Frameworks'
result = false
native_targets.each do |native_target|
embed_build_phase = native_target.shell_script_build_phases.find { |bp| bp.name == phase_name }
next unless embed_build_phase.present?
native_target.build_phases.delete(embed_build_phase)
result = true
end end
result
end end
# Adds a shell script build phase responsible to copy the resources # Adds a shell script build phase responsible to copy the resources
......
...@@ -12,7 +12,7 @@ module Pod ...@@ -12,7 +12,7 @@ module Pod
GLOB_PATTERNS = { GLOB_PATTERNS = {
:readme => 'readme{*,.*}'.freeze, :readme => 'readme{*,.*}'.freeze,
:license => 'licen{c,s}e{*,.*}'.freeze, :license => 'licen{c,s}e{*,.*}'.freeze,
:source_files => '*.{h,hpp,hh,m,mm,c,cpp}'.freeze, :source_files => '*.{h,hpp,hh,m,mm,c,cpp,swift}'.freeze,
:public_header_files => "*{#{HEADER_EXTENSIONS.join(',')}}".freeze, :public_header_files => "*{#{HEADER_EXTENSIONS.join(',')}}".freeze,
}.freeze }.freeze
......
...@@ -26,6 +26,10 @@ module Pod ...@@ -26,6 +26,10 @@ module Pod
@search_paths = [] @search_paths = []
end end
# @param [Platform] platform
# the platform for which the header search paths should be
# returned
#
# @return [Array<String>] All the search paths of the header directory in # @return [Array<String>] All the search paths of the header directory in
# xcconfig format. The paths are specified relative to the pods # xcconfig format. The paths are specified relative to the pods
# root with the `${PODS_ROOT}` variable. # root with the `${PODS_ROOT}` variable.
......
...@@ -15,18 +15,65 @@ module Pod ...@@ -15,18 +15,65 @@ module Pod
# #
attr_reader :sandbox attr_reader :sandbox
# @return [Boolean] Whether the target needs to be implemented as a framework.
# Computed by analyzer.
#
attr_accessor :host_requires_frameworks
alias_method :host_requires_frameworks?, :host_requires_frameworks
# @return [String] the name of the library. # @return [String] the name of the library.
# #
def name def name
label label
end end
# @return [String] the name of the library. # @return [String] the name of the product.
# #
def product_name def product_name
if requires_frameworks?
framework_name
else
static_library_name
end
end
# @return [String] the name of the product excluding the file extension or
# a product type specific prefix, depends on #requires_frameworks?
# and #product_module_name or #label.
#
def product_basename
if requires_frameworks?
product_module_name
else
label
end
end
# @return [String] the name of the framework, depends on #label.
#
# @note This may not depend on #requires_frameworks? indirectly as it is
# used for migration.
#
def framework_name
"#{product_module_name}.framework"
end
# @return [String] the name of the library, depends on #label.
#
# @note This may not depend on #requires_frameworks? indirectly as it is
# used for migration.
#
def static_library_name
"lib#{label}.a" "lib#{label}.a"
end end
# @return [Symbol] either :framework or :static_library, depends on
# #requires_frameworks?.
#
def product_type
requires_frameworks? ? :framework : :static_library
end
# @return [String] the XCConfig namespaced prefix. # @return [String] the XCConfig namespaced prefix.
# #
def xcconfig_prefix def xcconfig_prefix
...@@ -41,6 +88,20 @@ module Pod ...@@ -41,6 +88,20 @@ module Pod
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
# @return [Boolean] whether the generated target needs to be implemented
# as a framework
#
# @note This applies either if Swift was used by the host, which was checked
# eagerly by the analyzer before, or in the given target or its
# dependents, which can only be checked after the specs were been
# fetched.
#
def requires_frameworks?
host_requires_frameworks? || uses_swift?
end
#-------------------------------------------------------------------------#
# @!group Information storage # @!group Information storage
# @return [Hash{String=>Symbol}] A hash representing the user build # @return [Hash{String=>Symbol}] A hash representing the user build
...@@ -95,6 +156,22 @@ module Pod ...@@ -95,6 +156,22 @@ module Pod
support_files_dir + "#{label}-Private.xcconfig" support_files_dir + "#{label}-Private.xcconfig"
end end
# @return [Pathname] the absolute path of the header file which contains
# the exported foundation constants with framework version
# information and all headers, which should been exported in the
# module map.
#
def umbrella_header_path
support_files_dir + "#{label}-umbrella.h"
end
# @return [Pathname] the absolute path of the LLVM module map file that
# defines the module structure for the compiler.
#
def module_map_path
support_files_dir + "#{label}.modulemap"
end
# @return [Pathname] the absolute path of the header file which contains # @return [Pathname] the absolute path of the header file which contains
# the information about the installed pods. # the information about the installed pods.
# #
...@@ -115,12 +192,51 @@ module Pod ...@@ -115,12 +192,51 @@ module Pod
support_files_dir + "#{label}.bridgesupport" support_files_dir + "#{label}.bridgesupport"
end end
# @return [Pathname] the absolute path of the Info.plist file.
#
def info_plist_path
support_files_dir + "Info.plist"
end
# @return [Pathname] the path of the dummy source generated by CocoaPods # @return [Pathname] the path of the dummy source generated by CocoaPods
# #
def dummy_source_path def dummy_source_path
support_files_dir + "#{label}-dummy.m" support_files_dir + "#{label}-dummy.m"
end end
# @return [String] The configuration build dir, if the target is integrated
# as framework.
#
# @note Namespace the pod target product with its target definition name.
# Pod target products are named after their specs. The namespacing
# cannot directly happen in the product name itself, because this
# must be equal to the module name and this will be used in source
# code, which should stay agnostic over the dependency manager.
# We need namespacing at all because multiple targets can exist for
# the same podspec and their products should not collide. This
# happens when multiple user targets require the same pod, because
# they could require different sets of subspecs.
#
def configuration_build_dir
"$(BUILD_DIR)/$(CONFIGURATION)$(EFFECTIVE_PLATFORM_NAME)/#{target_definition.label}"
end
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
private
# Transforms the given string into a valid +identifier+ after C99ext
# standard, so that it can be used in source code where escaping of
# ambiguous characters is not applicable.
#
# @param [String] name
# any name, which may contain leading numbers, spaces or invalid
# characters.
#
# @return [String]
#
def c99ext_identifier(name)
name.gsub(/^([0-9])/, '_\1').gsub(/[^a-zA-Z0-9_]/, '_')
end
end end
end end
...@@ -20,6 +20,14 @@ module Pod ...@@ -20,6 +20,14 @@ module Pod
target_definition.label.to_s target_definition.label.to_s
end end
# @return [String] the name to use for the source code module constructed
# for this target, and which will be used to import the module in
# implementation source files.
#
def product_module_name
c99ext_identifier(label)
end
# @return [Pathname] the folder where the client is stored used for # @return [Pathname] the folder where the client is stored used for
# computing the relative paths. If integrating it should be the # computing the relative paths. If integrating it should be the
# folder where the user project is stored, otherwise it should # folder where the user project is stored, otherwise it should
...@@ -71,21 +79,32 @@ module Pod ...@@ -71,21 +79,32 @@ module Pod
# #
attr_accessor :pod_targets attr_accessor :pod_targets
# @param [String] build_configuration The build configuration for which the
# the pod targets should be returned.
#
# @return [Array<PodTarget>] the pod targets for the given build
# configuration.
#
def pod_targets_for_build_configuration(build_configuration)
pod_targets.select do |pod_target|
pod_target.include_in_build_config?(build_configuration)
end
end
# @return [Array<Specification>] The specifications used by this aggregate target. # @return [Array<Specification>] The specifications used by this aggregate target.
# #
def specs def specs
pod_targets.map(&:specs).flatten pod_targets.map(&:specs).flatten
end end
# @return [Hash{Symbol => Array<PodTarget>}] The pod targets for each # @return [Hash{Symbol => Array<Specification>}] The pod targets for each
# build configuration. # build configuration.
# #
def specs_by_build_configuration def specs_by_build_configuration
result = {} result = {}
user_build_configurations.keys.each do |build_configuration| user_build_configurations.keys.each do |build_configuration|
result[build_configuration] = pod_targets.select do |pod_target| result[build_configuration] = pod_targets_for_build_configuration(build_configuration).
pod_target.include_in_build_config?(build_configuration) flat_map(&:specs)
end.map(&:specs).flatten
end end
result result
end end
...@@ -96,6 +115,16 @@ module Pod ...@@ -96,6 +115,16 @@ module Pod
specs.map { |spec| spec.consumer(platform) } specs.map { |spec| spec.consumer(platform) }
end end
# @return [Boolean] Whether the target uses Swift code
#
def uses_swift?
pod_targets.any?(&:uses_swift?)
end
#-------------------------------------------------------------------------#
# @!group Support files
# @return [Pathname] The absolute path of acknowledgements file. # @return [Pathname] The absolute path of acknowledgements file.
# #
# @note The acknowledgements generators add the extension according to # @note The acknowledgements generators add the extension according to
...@@ -111,6 +140,12 @@ module Pod ...@@ -111,6 +140,12 @@ module Pod
support_files_dir + "#{label}-resources.sh" support_files_dir + "#{label}-resources.sh"
end end
# @return [Pathname] The absolute path of the embed frameworks script.
#
def embed_frameworks_script_path
support_files_dir + "#{label}-frameworks.sh"
end
# @return [String] The xcconfig path of the root from the `$(SRCROOT)` # @return [String] The xcconfig path of the root from the `$(SRCROOT)`
# variable of the user's project. # variable of the user's project.
# #
...@@ -133,6 +168,13 @@ module Pod ...@@ -133,6 +168,13 @@ module Pod
"${SRCROOT}/#{relative_to_srcroot(copy_resources_script_path)}" "${SRCROOT}/#{relative_to_srcroot(copy_resources_script_path)}"
end end
# @return [String] The path of the embed frameworks relative to the
# root of the user project.
#
def embed_frameworks_script_relative_path
"${SRCROOT}/#{relative_to_srcroot(embed_frameworks_script_path)}"
end
private private
# @!group Private Helpers # @!group Private Helpers
......
...@@ -30,6 +30,14 @@ module Pod ...@@ -30,6 +30,14 @@ module Pod
"#{target_definition.label}-#{root_spec.name}" "#{target_definition.label}-#{root_spec.name}"
end end
# @return [String] The name to use for the source code module constructed
# for this target, and which will be used to import the module in
# implementation source files.
#
def product_module_name
root_spec.module_name
end
# @return [Array<Sandbox::FileAccessor>] the file accessors for the # @return [Array<Sandbox::FileAccessor>] the file accessors for the
# specifications of this target. # specifications of this target.
# #
...@@ -54,6 +62,14 @@ module Pod ...@@ -54,6 +62,14 @@ module Pod
specs.map { |spec| spec.consumer(platform) } specs.map { |spec| spec.consumer(platform) }
end end
# @return [Boolean] Whether the target uses Swift code
#
def uses_swift?
file_accessors.any? do |file_accessor|
file_accessor.source_files.any? { |sf| sf.extname == ".swift" }
end
end
# @return [Specification] The root specification for the target. # @return [Specification] The root specification for the target.
# #
def root_spec def root_spec
...@@ -66,6 +82,15 @@ module Pod ...@@ -66,6 +82,15 @@ module Pod
root_spec.name root_spec.name
end end
# @param [String] bundle_name
# The name of the bundle product, which is given by the +spec+.
#
# @return [String] The derived name of the resource bundle target.
#
def resources_bundle_target_label(bundle_name)
"#{label}-#{bundle_name}"
end
# @return [Array<String>] The names of the Pods on which this target # @return [Array<String>] The names of the Pods on which this target
# depends. # depends.
# #
......
...@@ -143,6 +143,10 @@ module Pod ...@@ -143,6 +143,10 @@ module Pod
# #
attr_accessor :no_subspecs attr_accessor :no_subspecs
# @return [Bool] Whether frameworks should be used for the installation.
#
attr_accessor :use_frameworks
#-------------------------------------------------------------------------# #-------------------------------------------------------------------------#
# !@group Lint results # !@group Lint results
...@@ -299,7 +303,7 @@ module Pod ...@@ -299,7 +303,7 @@ module Pod
# #
def install_pod def install_pod
deployment_target = spec.subspec_by_name(subspec_name).deployment_target(consumer.platform_name) deployment_target = spec.subspec_by_name(subspec_name).deployment_target(consumer.platform_name)
podfile = podfile_from_spec(consumer.platform_name, deployment_target) podfile = podfile_from_spec(consumer.platform_name, deployment_target, use_frameworks)
sandbox = Sandbox.new(config.sandbox_root) sandbox = Sandbox.new(config.sandbox_root)
installer = Installer.new(sandbox, podfile) installer = Installer.new(sandbox, podfile)
installer.install! installer.install!
...@@ -449,19 +453,31 @@ module Pod ...@@ -449,19 +453,31 @@ module Pod
# #
attr_reader :source_urls attr_reader :source_urls
# @param [String] platform_name
# the name of the platform, which should be declared
# in the Podfile.
#
# @param [String] deployment_target
# the deployment target, which should be declared in
# the Podfile.
#
# @param [Bool] use_frameworks
# whether frameworks should be used for the installation
#
# @return [Podfile] a podfile that requires the specification on the # @return [Podfile] a podfile that requires the specification on the
# current platform. # current platform.
# #
# @note The generated podfile takes into account whether the linter is # @note The generated podfile takes into account whether the linter is
# in local mode. # in local mode.
# #
def podfile_from_spec(platform_name, deployment_target) def podfile_from_spec(platform_name, deployment_target, use_frameworks = nil)
name = subspec_name ? subspec_name : spec.name name = subspec_name ? subspec_name : spec.name
podspec = file.realpath podspec = file.realpath
local = local? local = local?
urls = source_urls urls = source_urls
podfile = Pod::Podfile.new do podfile = Pod::Podfile.new do
urls.each { |u| source(u) } urls.each { |u| source(u) }
use_frameworks!(use_frameworks) unless use_frameworks.nil?
platform(platform_name, deployment_target) platform(platform_name, deployment_target)
if local if local
pod name, :path => podspec.dirname.to_s pod name, :path => podspec.dirname.to_s
......
Subproject commit 3d83baf65d54e6abae10d480bdeb4f00a11e3682 Subproject commit 5ad1e8ba91444988fcc96379fd986f5b8641ded2
Pod::Spec.new do |s|
s.name = "monkey"
s.version = "1.0.2"
s.author = { "Funky Monkey" => "funky@monkey.local" }
s.summary = "🙈🙉🙊"
s.description = "See no evil! Hear no evil! Speak no evil!"
s.homepage = "http://httpbin.org/html"
s.source = { :git => "http://monkey.local/monkey.git", :tag => s.version.to_s }
s.license = 'MIT'
s.vendored_library = 'monkey.a'
end
# OS X
.DS_Store
# Xcode
build/
*.pbxuser
!default.pbxuser
*.mode1v3
!default.mode1v3
*.mode2v3
!default.mode2v3
*.perspectivev3
!default.perspectivev3
xcuserdata
*.xccheckout
profile
*.moved-aside
DerivedData
*.hmap
*.ipa
# Bundler
.bundle
# We recommend against adding the Pods directory to your .gitignore. However
# you should judge for yourself, the pros and cons are mentioned at:
# http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control
#
# Note: if you ignore the Pods directory, make sure to uncomment
# `pod install` in .travis.yml
#
# Pods/
Copyright (c) 2014 Marius Rackwitz <git@mariusrackwitz.de>
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
furnished to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
THE SOFTWARE.
Pod::Spec.new do |s|
s.name = "OrangeFramework"
s.version = "0.1.0"
s.author = { "Swiftest Orang-Utan" => "swiftest@orang.utan.local" }
s.summary = "Fresh juice!"
s.description = "Blends fresh orange juice."
s.homepage = "http://httpbin.org/html"
s.source = { :git => "http://utan.local/orange-framework.git", :tag => s.version.to_s }
s.license = 'MIT'
s.platform = :ios, '8.0'
s.source_files = 'Source/Juicer.swift'
s.frameworks = 'UIKit'
end
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleDevelopmentRegion</key>
<string>en</string>
<key>CFBundleExecutable</key>
<string>$(EXECUTABLE_NAME)</string>
<key>CFBundleIdentifier</key>
<string>org.cocoapods.$(PRODUCT_NAME:rfc1034identifier)</string>
<key>CFBundleInfoDictionaryVersion</key>
<string>6.0</string>
<key>CFBundleName</key>
<string>$(PRODUCT_NAME)</string>
<key>CFBundlePackageType</key>
<string>FMWK</string>
<key>CFBundleShortVersionString</key>
<string>1.0</string>
<key>CFBundleSignature</key>
<string>????</string>
<key>CFBundleVersion</key>
<string>$(CURRENT_PROJECT_VERSION)</string>
<key>NSPrincipalClass</key>
<string></string>
</dict>
</plist>
import Foundation
public struct Orange {
public var weight: Float
public init(weight: Float) {
self.weight = weight
}
}
public struct Glass : Equatable {
public var volume: Float
public init(volume: Float) {
self.volume = volume
}
public static func empty() -> Glass {
return Glass(volume: 0)
}
public func pour(additionalVolume: Float) -> Glass {
return Glass(volume: self.volume + additionalVolume)
}
}
public class Juicer {
public required init() {}
public func pressOut(fruits: [Orange]) -> Glass {
return reduce(fruits, Glass.empty()) { (glass, fruit) in
glass.pour(self.juiceOf(fruit))
}
}
public func juiceOf(fruit: Orange) -> Float {
return fruit.weight * 0.5;
}
}
public func ==(lhs: Glass, rhs: Glass) -> Bool {
return lhs.volume == rhs.volume
}
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
This diff is collapsed.
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment