Permalink
Please sign in to comment.
Showing
with
2,091 additions
and 0 deletions.
- +223 −0 .gitignore
- +30 −0 .travis.yml
- +10 −0 Appz.xcworkspace/contents.xcworkspacedata
- +479 −0 Appz/Appz.xcodeproj/project.pbxproj
- +100 −0 Appz/Appz.xcodeproj/xcshareddata/xcschemes/Appz-ios.xcscheme
- +50 −0 Appz/Appz/Apps/AppStore.swift
- +35 −0 Appz/Appz/Apps/Settings.swift
- +119 −0 Appz/Appz/Apps/Twitter.swift
- +19 −0 Appz/Appz/Appz.h
- +48 −0 Appz/Appz/Entity/ApplicationCaller.swift
- +21 −0 Appz/Appz/Entity/AvailableApplications.swift
- +40 −0 Appz/Appz/Entity/ExternalApplication.swift
- +24 −0 Appz/Appz/Extensions/NSExtensionContext+Appz.swift
- +12 −0 Appz/Appz/Extensions/UIApplication+Appz.swift
- +26 −0 Appz/Appz/Info.plist
- +41 −0 Appz/AppzTests/AppStoreTests.swift
- +96 −0 Appz/AppzTests/ApplicationCallerTests.swift
- +24 −0 Appz/AppzTests/Info.plist
- +34 −0 Appz/AppzTests/Mocks/ApplicationCallerMock.swift
- +30 −0 Appz/AppzTests/SettingsTests.swift
- +41 −0 Appz/AppzTests/TwitterTests.swift
- +21 −0 LICENSE
- +37 −0 Playground/Playground.playground/Contents.swift
- +430 −0 Playground/Playground.playground/Sources/Appz.xcodeproj/project.pbxproj
- +4 −0 Playground/Playground.playground/contents.xcplayground
- +7 −0 Playground/Playground.playground/playground.xcworkspace/contents.xcworkspacedata
- +6 −0 Playground/Playground.playground/timeline.xctimeline
- +84 −0 README.md
223
.gitignore
@@ -0,0 +1,223 @@ | ||
+ | ||
+# PYSCRIPT-XCODE-IGNORE-START | ||
+ | ||
+######################### | ||
+# .gitignore file for Xcode4 and Xcode5 Source projects | ||
+# | ||
+# Apple bugs, waiting for Apple to fix/respond: | ||
+# | ||
+# 15564624 - what does the xccheckout file in Xcode5 do? Where's the documentation? | ||
+# | ||
+# Version 2.6 | ||
+# For latest version, see: http://stackoverflow.com/questions/49478/git-ignore-file-for-xcode-projects | ||
+# | ||
+# 2015 updates: | ||
+# - Fixed typo in "xccheckout" line - thanks to @lyck for pointing it out! | ||
+# - Fixed the .idea optional ignore. Thanks to @hashier for pointing this out | ||
+# - Finally added "xccheckout" to the ignore. Apple still refuses to answer support requests about this, but in practice it seems you should ignore it. | ||
+# - minor tweaks from Jona and Coeur (slightly more precise xc* filtering/names) | ||
+# 2014 updates: | ||
+# - appended non-standard items DISABLED by default (uncomment if you use those tools) | ||
+# - removed the edit that an SO.com moderator made without bothering to ask me | ||
+# - researched CocoaPods .lock more carefully, thanks to Gokhan Celiker | ||
+# 2013 updates: | ||
+# - fixed the broken "save personal Schemes" | ||
+# - added line-by-line explanations for EVERYTHING (some were missing) | ||
+# | ||
+# NB: if you are storing "built" products, this WILL NOT WORK, | ||
+# and you should use a different .gitignore (or none at all) | ||
+# This file is for SOURCE projects, where there are many extra | ||
+# files that we want to exclude | ||
+# | ||
+######################### | ||
+ | ||
+##### | ||
+# OS X temporary files that should never be committed | ||
+# | ||
+# c.f. http://www.westwind.com/reference/os-x/invisibles.html | ||
+ | ||
+.DS_Store | ||
+ | ||
+# c.f. http://www.westwind.com/reference/os-x/invisibles.html | ||
+ | ||
+.Trashes | ||
+ | ||
+# c.f. http://www.westwind.com/reference/os-x/invisibles.html | ||
+ | ||
+*.swp | ||
+ | ||
+# | ||
+# *.lock - this is used and abused by many editors for many different things. | ||
+# For the main ones I use (e.g. Eclipse), it should be excluded | ||
+# from source-control, but YMMV. | ||
+# (lock files are usually local-only file-synchronization on the local FS that should NOT go in git) | ||
+# c.f. the "OPTIONAL" section at bottom though, for tool-specific variations! | ||
+# | ||
+# In particular, if you're using CocoaPods, you'll want to comment-out this line: | ||
+*.lock | ||
+ | ||
+ | ||
+# | ||
+# profile - REMOVED temporarily (on double-checking, I can't find it in OS X docs?) | ||
+#profile | ||
+ | ||
+ | ||
+#### | ||
+# Xcode temporary files that should never be committed | ||
+# | ||
+# NB: NIB/XIB files still exist even on Storyboard projects, so we want this... | ||
+ | ||
+*~.nib | ||
+ | ||
+ | ||
+#### | ||
+# Xcode build files - | ||
+# | ||
+# NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "DerivedData" | ||
+ | ||
+DerivedData/ | ||
+ | ||
+# NB: slash on the end, so we only remove the FOLDER, not any files that were badly named "build" | ||
+ | ||
+build/ | ||
+ | ||
+ | ||
+##### | ||
+# Xcode private settings (window sizes, bookmarks, breakpoints, custom executables, smart groups) | ||
+# | ||
+# This is complicated: | ||
+# | ||
+# SOMETIMES you need to put this file in version control. | ||
+# Apple designed it poorly - if you use "custom executables", they are | ||
+# saved in this file. | ||
+# 99% of projects do NOT use those, so they do NOT want to version control this file. | ||
+# ..but if you're in the 1%, comment out the line "*.pbxuser" | ||
+ | ||
+# .pbxuser: http://lists.apple.com/archives/xcode-users/2004/Jan/msg00193.html | ||
+ | ||
+*.pbxuser | ||
+ | ||
+# .mode1v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html | ||
+ | ||
+*.mode1v3 | ||
+ | ||
+# .mode2v3: http://lists.apple.com/archives/xcode-users/2007/Oct/msg00465.html | ||
+ | ||
+*.mode2v3 | ||
+ | ||
+# .perspectivev3: http://stackoverflow.com/questions/5223297/xcode-projects-what-is-a-perspectivev3-file | ||
+ | ||
+*.perspectivev3 | ||
+ | ||
+# NB: also, whitelist the default ones, some projects need to use these | ||
+!default.pbxuser | ||
+!default.mode1v3 | ||
+!default.mode2v3 | ||
+!default.perspectivev3 | ||
+ | ||
+ | ||
+#### | ||
+# Xcode 4 - semi-personal settings | ||
+# | ||
+# Apple Shared data that Apple put in the wrong folder | ||
+# c.f. http://stackoverflow.com/a/19260712/153422 | ||
+# FROM ANSWER: Apple says "don't ignore it" | ||
+# FROM COMMENTS: Apple is wrong; Apple code is too buggy to trust; there are no known negative side-effects to ignoring Apple's unofficial advice and instead doing the thing that actively fixes bugs in Xcode | ||
+# Up to you, but ... current advice: ignore it. | ||
+*.xccheckout | ||
+ | ||
+# | ||
+# | ||
+# OPTION 1: --------------------------------- | ||
+# throw away ALL personal settings (including custom schemes! | ||
+# - unless they are "shared") | ||
+# As per build/ and DerivedData/, this ought to have a trailing slash | ||
+# | ||
+# NB: this is exclusive with OPTION 2 below | ||
+xcuserdata/ | ||
+ | ||
+# OPTION 2: --------------------------------- | ||
+# get rid of ALL personal settings, but KEEP SOME OF THEM | ||
+# - NB: you must manually uncomment the bits you want to keep | ||
+# | ||
+# NB: this *requires* git v1.8.2 or above; you may need to upgrade to latest OS X, | ||
+# or manually install git over the top of the OS X version | ||
+# NB: this is exclusive with OPTION 1 above | ||
+# | ||
+#xcuserdata/**/* | ||
+ | ||
+# (requires option 2 above): Personal Schemes | ||
+# | ||
+#!xcuserdata/**/xcschemes/* | ||
+ | ||
+#### | ||
+# XCode 4 workspaces - more detailed | ||
+# | ||
+# Workspaces are important! They are a core feature of Xcode - don't exclude them :) | ||
+# | ||
+# Workspace layout is quite spammy. For reference: | ||
+# | ||
+# /(root)/ | ||
+# /(project-name).xcodeproj/ | ||
+# project.pbxproj | ||
+# /project.xcworkspace/ | ||
+# contents.xcworkspacedata | ||
+# /xcuserdata/ | ||
+# /(your name)/xcuserdatad/ | ||
+# UserInterfaceState.xcuserstate | ||
+# /xcshareddata/ | ||
+# /xcschemes/ | ||
+# (shared scheme name).xcscheme | ||
+# /xcuserdata/ | ||
+# /(your name)/xcuserdatad/ | ||
+# (private scheme).xcscheme | ||
+# xcschememanagement.plist | ||
+# | ||
+# | ||
+ | ||
+#### | ||
+# Xcode 4 - Deprecated classes | ||
+# | ||
+# Allegedly, if you manually "deprecate" your classes, they get moved here. | ||
+# | ||
+# We're using source-control, so this is a "feature" that we do not want! | ||
+ | ||
+*.moved-aside | ||
+ | ||
+#### | ||
+# OPTIONAL: Some well-known tools that people use side-by-side with Xcode / iOS development | ||
+# | ||
+# NB: I'd rather not include these here, but gitignore's design is weak and doesn't allow | ||
+# modular gitignore: you have to put EVERYTHING in one file. | ||
+# | ||
+# COCOAPODS: | ||
+# | ||
+# c.f. http://guides.cocoapods.org/using/using-cocoapods.html#what-is-a-podfilelock | ||
+# c.f. http://guides.cocoapods.org/using/using-cocoapods.html#should-i-ignore-the-pods-directory-in-source-control | ||
+# | ||
+!Podfile.lock | ||
+# | ||
+# RUBY: | ||
+# | ||
+# c.f. http://yehudakatz.com/2010/12/16/clarifying-the-roles-of-the-gemspec-and-gemfile/ | ||
+# | ||
+!Gemfile.lock | ||
+# | ||
+# IDEA: | ||
+# | ||
+# c.f. https://www.jetbrains.com/objc/help/managing-projects-under-version-control.html?search=workspace.xml | ||
+# | ||
+#.idea/workspace.xml | ||
+# | ||
+# TEXTMATE: | ||
+# | ||
+# -- UNVERIFIED: c.f. http://stackoverflow.com/a/50283/153422 | ||
+# | ||
+#tm_build_errors | ||
+ | ||
+#### | ||
+# UNKNOWN: recommended by others, but I can't discover what these files are | ||
+# | ||
+ | ||
+# PYSCRIPT-XCODE-IGNORE-END | ||
+ |
30
.travis.yml
@@ -0,0 +1,30 @@ | ||
+language: objective-c | ||
+osx_image: xcode7.1 | ||
+env: | ||
+ global: | ||
+ - LC_CTYPE=en_US.UTF-8 | ||
+ - LANG=en_US.UTF-8 | ||
+ - WORKSPACE=Appz.xcworkspace | ||
+ - IOS_FRAMEWORK_SCHEME="Appz-ios" | ||
+ - IOS_SDK=iphonesimulator9.1 | ||
+ matrix: | ||
+ - DESTINATION="OS=8.1,name=iPhone 4S" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" RUN_TESTS="YES" | ||
+ - DESTINATION="OS=8.2,name=iPhone 5" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" RUN_TESTS="YES" | ||
+ - DESTINATION="OS=8.3,name=iPhone 5S" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" RUN_TESTS="YES" | ||
+ - DESTINATION="OS=8.4,name=iPhone 6" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" RUN_TESTS="YES" | ||
+ - DESTINATION="OS=9.1,name=iPhone 6S" SCHEME="$IOS_FRAMEWORK_SCHEME" SDK="$IOS_SDK" RUN_TESTS="YES" | ||
+before_install: | ||
+- gem install xcpretty --no-rdoc --no-ri --no-document --quiet | ||
+script: | ||
+- set -o pipefail | ||
+- xcodebuild -version | ||
+- xcodebuild -showsdks | ||
+- if [ $RUN_TESTS == "YES" ]; then xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" | ||
+ -sdk "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO | ||
+ test | xcpretty -c; else xcodebuild -workspace "$WORKSPACE" -scheme "$SCHEME" -sdk | ||
+ "$SDK" -destination "$DESTINATION" -configuration Debug ONLY_ACTIVE_ARCH=NO build | ||
+ | xcpretty -c; fi | ||
+notifications: | ||
+ email: false | ||
+ slack: | ||
+ secure: NhKT0y5VJ4NlgSXk3KZ+NdMnSFNi3c+VBhSBO7/sizMuFSRtUXNnRQ2MFsxO4uDtm/CIv0YPOQr2GpJsb7aRU/erpxKAaDjVtx3MM4xS34W+QhYDmF+P+T6phDRZwuuwsLVwVQrTiyNLULUrEExIh7tatcrYmYYBO3J8qqz884uPJOF0+roxi/2Gjm/CKhXS+vHvaBKS0sK47LtD3y6Tuvus5QPGd7fwUmhR53Yzpn8+7QW2tw4Yfzk9KyFrFX4NC3b6WpjKq0oL9JwNiKJvox+/MJY4moXh73IqE7iVOcDslWnCsos4QXMaGdugYiQrnvLGAQuVVLupeeF0V/QzVDBp5qb6fdtQc5mU6ijRelqhrRDRpop/yylVSIxEs0eFenPJtTNRZbAQI1qkJ7XRYHXpQH/armaF5nhi3gTbIgOu/0CFJsccQeBK8hIYyQFHswXsaxeY0pOjuHxgkrRLz82vjWnXf3jlxnxbCbYhsgRIp15dnxXt5G1zh6drQ4tuB9G/K6MhmB5MGhfkGsu66Gg0IsZAGDdNw8sA4QvK2hz9jzcDe1YiD4nlQq82JilZCnCG4m6WSALMvlyX7UZNcOkaJjb6vxj1KfwgMBv2kkyy7cuHmwWgDGVLwxqiPJ1P1camMV0iatKCGQEKBmvB8h2jEgH+S/dRHlUldVr5gAg= |
10
Appz.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,10 @@ | ||
+<?xml version="1.0" encoding="UTF-8"?> | ||
+<Workspace | ||
+ version = "1.0"> | ||
+ <FileRef | ||
+ location = "group:Playground/Playground.playground"> | ||
+ </FileRef> | ||
+ <FileRef | ||
+ location = "group:Appz/Appz.xcodeproj"> | ||
+ </FileRef> | ||
+</Workspace> |
479
Appz/Appz.xcodeproj/project.pbxproj
@@ -0,0 +1,479 @@ | ||
+// !$*UTF8*$! | ||
+{ | ||
+ archiveVersion = 1; | ||
+ classes = { | ||
+ }; | ||
+ objectVersion = 46; | ||
+ objects = { | ||
+ | ||
+/* Begin PBXBuildFile section */ | ||
+ 826ACEE21BF1B10A00B5FC5D /* Appz.h in Headers */ = {isa = PBXBuildFile; fileRef = 826ACEE11BF1B10A00B5FC5D /* Appz.h */; settings = {ATTRIBUTES = (Public, ); }; }; | ||
+ 826ACEE91BF1B10A00B5FC5D /* Appz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 826ACEDE1BF1B10A00B5FC5D /* Appz.framework */; }; | ||
+ 826ACF191BF1BD1F00B5FC5D /* AvailableApplications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF181BF1BD1F00B5FC5D /* AvailableApplications.swift */; }; | ||
+ 826ACF1B1BF1BD7F00B5FC5D /* ExternalApplication.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF1A1BF1BD7F00B5FC5D /* ExternalApplication.swift */; }; | ||
+ 826ACF1E1BF1BEB000B5FC5D /* Twitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF1D1BF1BEB000B5FC5D /* Twitter.swift */; }; | ||
+ 826ACF201BF1BEB800B5FC5D /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF1F1BF1BEB800B5FC5D /* Settings.swift */; }; | ||
+ 826ACF221BF1BEBF00B5FC5D /* AppStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF211BF1BEBF00B5FC5D /* AppStore.swift */; }; | ||
+ 826ACF251BF1C00800B5FC5D /* UIApplication+Appz.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF241BF1C00800B5FC5D /* UIApplication+Appz.swift */; }; | ||
+ 826ACF271BF1C1CF00B5FC5D /* TwitterTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF261BF1C1CF00B5FC5D /* TwitterTests.swift */; }; | ||
+ 826ACF291BF1C99600B5FC5D /* ApplicationCallerTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF281BF1C99600B5FC5D /* ApplicationCallerTests.swift */; }; | ||
+ 826ACF5C1BF1E26B00B5FC5D /* ApplicationCaller.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF5B1BF1E26B00B5FC5D /* ApplicationCaller.swift */; }; | ||
+ 826ACF5E1BF1E4BE00B5FC5D /* NSExtensionContext+Appz.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF5D1BF1E4BE00B5FC5D /* NSExtensionContext+Appz.swift */; }; | ||
+ 827EF6171BF2756C000B1607 /* ApplicationCallerMock.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827EF6161BF2756C000B1607 /* ApplicationCallerMock.swift */; }; | ||
+ 827EF61B1BF2EAA0000B1607 /* SettingsTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827EF61A1BF2EAA0000B1607 /* SettingsTests.swift */; }; | ||
+ 827EF61D1BF2EBAC000B1607 /* AppStoreTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 827EF61C1BF2EBAC000B1607 /* AppStoreTests.swift */; }; | ||
+/* End PBXBuildFile section */ | ||
+ | ||
+/* Begin PBXContainerItemProxy section */ | ||
+ 826ACEEA1BF1B10A00B5FC5D /* PBXContainerItemProxy */ = { | ||
+ isa = PBXContainerItemProxy; | ||
+ containerPortal = 826ACED51BF1B10A00B5FC5D /* Project object */; | ||
+ proxyType = 1; | ||
+ remoteGlobalIDString = 826ACEDD1BF1B10A00B5FC5D; | ||
+ remoteInfo = Appz; | ||
+ }; | ||
+/* End PBXContainerItemProxy section */ | ||
+ | ||
+/* Begin PBXFileReference section */ | ||
+ 826ACEDE1BF1B10A00B5FC5D /* Appz.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Appz.framework; sourceTree = BUILT_PRODUCTS_DIR; }; | ||
+ 826ACEE11BF1B10A00B5FC5D /* Appz.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Appz.h; sourceTree = "<group>"; }; | ||
+ 826ACEE31BF1B10A00B5FC5D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; | ||
+ 826ACEE81BF1B10A00B5FC5D /* AppzTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AppzTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; | ||
+ 826ACEEF1BF1B10A00B5FC5D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; | ||
+ 826ACF181BF1BD1F00B5FC5D /* AvailableApplications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AvailableApplications.swift; sourceTree = "<group>"; }; | ||
+ 826ACF1A1BF1BD7F00B5FC5D /* ExternalApplication.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ExternalApplication.swift; sourceTree = "<group>"; }; | ||
+ 826ACF1D1BF1BEB000B5FC5D /* Twitter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Twitter.swift; sourceTree = "<group>"; }; | ||
+ 826ACF1F1BF1BEB800B5FC5D /* Settings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; }; | ||
+ 826ACF211BF1BEBF00B5FC5D /* AppStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppStore.swift; sourceTree = "<group>"; }; | ||
+ 826ACF241BF1C00800B5FC5D /* UIApplication+Appz.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "UIApplication+Appz.swift"; sourceTree = "<group>"; }; | ||
+ 826ACF261BF1C1CF00B5FC5D /* TwitterTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = TwitterTests.swift; sourceTree = "<group>"; }; | ||
+ 826ACF281BF1C99600B5FC5D /* ApplicationCallerTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplicationCallerTests.swift; sourceTree = "<group>"; }; | ||
+ 826ACF5B1BF1E26B00B5FC5D /* ApplicationCaller.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplicationCaller.swift; sourceTree = "<group>"; }; | ||
+ 826ACF5D1BF1E4BE00B5FC5D /* NSExtensionContext+Appz.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = "NSExtensionContext+Appz.swift"; sourceTree = "<group>"; }; | ||
+ 827EF6161BF2756C000B1607 /* ApplicationCallerMock.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplicationCallerMock.swift; sourceTree = "<group>"; }; | ||
+ 827EF61A1BF2EAA0000B1607 /* SettingsTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SettingsTests.swift; sourceTree = "<group>"; }; | ||
+ 827EF61C1BF2EBAC000B1607 /* AppStoreTests.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppStoreTests.swift; sourceTree = "<group>"; }; | ||
+/* End PBXFileReference section */ | ||
+ | ||
+/* Begin PBXFrameworksBuildPhase section */ | ||
+ 826ACEDA1BF1B10A00B5FC5D /* Frameworks */ = { | ||
+ isa = PBXFrameworksBuildPhase; | ||
+ buildActionMask = 2147483647; | ||
+ files = ( | ||
+ ); | ||
+ runOnlyForDeploymentPostprocessing = 0; | ||
+ }; | ||
+ 826ACEE51BF1B10A00B5FC5D /* Frameworks */ = { | ||
+ isa = PBXFrameworksBuildPhase; | ||
+ buildActionMask = 2147483647; | ||
+ files = ( | ||
+ 826ACEE91BF1B10A00B5FC5D /* Appz.framework in Frameworks */, | ||
+ ); | ||
+ runOnlyForDeploymentPostprocessing = 0; | ||
+ }; | ||
+/* End PBXFrameworksBuildPhase section */ | ||
+ | ||
+/* Begin PBXGroup section */ | ||
+ 826ACED41BF1B10A00B5FC5D = { | ||
+ isa = PBXGroup; | ||
+ children = ( | ||
+ 826ACEE01BF1B10A00B5FC5D /* Appz */, | ||
+ 826ACEEC1BF1B10A00B5FC5D /* AppzTests */, | ||
+ 826ACEDF1BF1B10A00B5FC5D /* Products */, | ||
+ ); | ||
+ sourceTree = "<group>"; | ||
+ }; | ||
+ 826ACEDF1BF1B10A00B5FC5D /* Products */ = { | ||
+ isa = PBXGroup; | ||
+ children = ( | ||
+ 826ACEDE1BF1B10A00B5FC5D /* Appz.framework */, | ||
+ 826ACEE81BF1B10A00B5FC5D /* AppzTests.xctest */, | ||
+ ); | ||
+ name = Products; | ||
+ sourceTree = "<group>"; | ||
+ }; | ||
+ 826ACEE01BF1B10A00B5FC5D /* Appz */ = { | ||
+ isa = PBXGroup; | ||
+ children = ( | ||
+ 826ACF231BF1BFE100B5FC5D /* Extensions */, | ||
+ 826ACF1C1BF1BE9C00B5FC5D /* Apps */, | ||
+ 826ACF171BF1BCF500B5FC5D /* Entity */, | ||
+ 826ACEE11BF1B10A00B5FC5D /* Appz.h */, | ||
+ 826ACEE31BF1B10A00B5FC5D /* Info.plist */, | ||
+ ); | ||
+ path = Appz; | ||
+ sourceTree = "<group>"; | ||
+ }; | ||
+ 826ACEEC1BF1B10A00B5FC5D /* AppzTests */ = { | ||
+ isa = PBXGroup; | ||
+ children = ( | ||
+ 827EF6151BF2751C000B1607 /* Mocks */, | ||
+ 826ACF281BF1C99600B5FC5D /* ApplicationCallerTests.swift */, | ||
+ 826ACF261BF1C1CF00B5FC5D /* TwitterTests.swift */, | ||
+ 827EF61A1BF2EAA0000B1607 /* SettingsTests.swift */, | ||
+ 827EF61C1BF2EBAC000B1607 /* AppStoreTests.swift */, | ||
+ 826ACEEF1BF1B10A00B5FC5D /* Info.plist */, | ||
+ ); | ||
+ path = AppzTests; | ||
+ sourceTree = "<group>"; | ||
+ }; | ||
+ 826ACF171BF1BCF500B5FC5D /* Entity */ = { | ||
+ isa = PBXGroup; | ||
+ children = ( | ||
+ 826ACF181BF1BD1F00B5FC5D /* AvailableApplications.swift */, | ||
+ 826ACF1A1BF1BD7F00B5FC5D /* ExternalApplication.swift */, | ||
+ 826ACF5B1BF1E26B00B5FC5D /* ApplicationCaller.swift */, | ||
+ ); | ||
+ path = Entity; | ||
+ sourceTree = "<group>"; | ||
+ }; | ||
+ 826ACF1C1BF1BE9C00B5FC5D /* Apps */ = { | ||
+ isa = PBXGroup; | ||
+ children = ( | ||
+ 826ACF1D1BF1BEB000B5FC5D /* Twitter.swift */, | ||
+ 826ACF1F1BF1BEB800B5FC5D /* Settings.swift */, | ||
+ 826ACF211BF1BEBF00B5FC5D /* AppStore.swift */, | ||
+ ); | ||
+ path = Apps; | ||
+ sourceTree = "<group>"; | ||
+ }; | ||
+ 826ACF231BF1BFE100B5FC5D /* Extensions */ = { | ||
+ isa = PBXGroup; | ||
+ children = ( | ||
+ 826ACF241BF1C00800B5FC5D /* UIApplication+Appz.swift */, | ||
+ 826ACF5D1BF1E4BE00B5FC5D /* NSExtensionContext+Appz.swift */, | ||
+ ); | ||
+ path = Extensions; | ||
+ sourceTree = "<group>"; | ||
+ }; | ||
+ 827EF6151BF2751C000B1607 /* Mocks */ = { | ||
+ isa = PBXGroup; | ||
+ children = ( | ||
+ 827EF6161BF2756C000B1607 /* ApplicationCallerMock.swift */, | ||
+ ); | ||
+ path = Mocks; | ||
+ sourceTree = "<group>"; | ||
+ }; | ||
+/* End PBXGroup section */ | ||
+ | ||
+/* Begin PBXHeadersBuildPhase section */ | ||
+ 826ACEDB1BF1B10A00B5FC5D /* Headers */ = { | ||
+ isa = PBXHeadersBuildPhase; | ||
+ buildActionMask = 2147483647; | ||
+ files = ( | ||
+ 826ACEE21BF1B10A00B5FC5D /* Appz.h in Headers */, | ||
+ ); | ||
+ runOnlyForDeploymentPostprocessing = 0; | ||
+ }; | ||
+/* End PBXHeadersBuildPhase section */ | ||
+ | ||
+/* Begin PBXNativeTarget section */ | ||
+ 826ACEDD1BF1B10A00B5FC5D /* Appz-ios */ = { | ||
+ isa = PBXNativeTarget; | ||
+ buildConfigurationList = 826ACEF21BF1B10A00B5FC5D /* Build configuration list for PBXNativeTarget "Appz-ios" */; | ||
+ buildPhases = ( | ||
+ 826ACED91BF1B10A00B5FC5D /* Sources */, | ||
+ 826ACEDA1BF1B10A00B5FC5D /* Frameworks */, | ||
+ 826ACEDB1BF1B10A00B5FC5D /* Headers */, | ||
+ 826ACEDC1BF1B10A00B5FC5D /* Resources */, | ||
+ ); | ||
+ buildRules = ( | ||
+ ); | ||
+ dependencies = ( | ||
+ ); | ||
+ name = "Appz-ios"; | ||
+ productName = Appz; | ||
+ productReference = 826ACEDE1BF1B10A00B5FC5D /* Appz.framework */; | ||
+ productType = "com.apple.product-type.framework"; | ||
+ }; | ||
+ 826ACEE71BF1B10A00B5FC5D /* AppzTests */ = { | ||
+ isa = PBXNativeTarget; | ||
+ buildConfigurationList = 826ACEF51BF1B10A00B5FC5D /* Build configuration list for PBXNativeTarget "AppzTests" */; | ||
+ buildPhases = ( | ||
+ 826ACEE41BF1B10A00B5FC5D /* Sources */, | ||
+ 826ACEE51BF1B10A00B5FC5D /* Frameworks */, | ||
+ 826ACEE61BF1B10A00B5FC5D /* Resources */, | ||
+ ); | ||
+ buildRules = ( | ||
+ ); | ||
+ dependencies = ( | ||
+ 826ACEEB1BF1B10A00B5FC5D /* PBXTargetDependency */, | ||
+ ); | ||
+ name = AppzTests; | ||
+ productName = AppzTests; | ||
+ productReference = 826ACEE81BF1B10A00B5FC5D /* AppzTests.xctest */; | ||
+ productType = "com.apple.product-type.bundle.unit-test"; | ||
+ }; | ||
+/* End PBXNativeTarget section */ | ||
+ | ||
+/* Begin PBXProject section */ | ||
+ 826ACED51BF1B10A00B5FC5D /* Project object */ = { | ||
+ isa = PBXProject; | ||
+ attributes = { | ||
+ LastSwiftUpdateCheck = 0710; | ||
+ LastUpgradeCheck = 0710; | ||
+ ORGANIZATIONNAME = kitz; | ||
+ TargetAttributes = { | ||
+ 826ACEDD1BF1B10A00B5FC5D = { | ||
+ CreatedOnToolsVersion = 7.1; | ||
+ }; | ||
+ 826ACEE71BF1B10A00B5FC5D = { | ||
+ CreatedOnToolsVersion = 7.1; | ||
+ }; | ||
+ }; | ||
+ }; | ||
+ buildConfigurationList = 826ACED81BF1B10A00B5FC5D /* Build configuration list for PBXProject "Appz" */; | ||
+ compatibilityVersion = "Xcode 3.2"; | ||
+ developmentRegion = English; | ||
+ hasScannedForEncodings = 0; | ||
+ knownRegions = ( | ||
+ en, | ||
+ ); | ||
+ mainGroup = 826ACED41BF1B10A00B5FC5D; | ||
+ productRefGroup = 826ACEDF1BF1B10A00B5FC5D /* Products */; | ||
+ projectDirPath = ""; | ||
+ projectRoot = ""; | ||
+ targets = ( | ||
+ 826ACEDD1BF1B10A00B5FC5D /* Appz-ios */, | ||
+ 826ACEE71BF1B10A00B5FC5D /* AppzTests */, | ||
+ ); | ||
+ }; | ||
+/* End PBXProject section */ | ||
+ | ||
+/* Begin PBXResourcesBuildPhase section */ | ||
+ 826ACEDC1BF1B10A00B5FC5D /* Resources */ = { | ||
+ isa = PBXResourcesBuildPhase; | ||
+ buildActionMask = 2147483647; | ||
+ files = ( | ||
+ ); | ||
+ runOnlyForDeploymentPostprocessing = 0; | ||
+ }; | ||
+ 826ACEE61BF1B10A00B5FC5D /* Resources */ = { | ||
+ isa = PBXResourcesBuildPhase; | ||
+ buildActionMask = 2147483647; | ||
+ files = ( | ||
+ ); | ||
+ runOnlyForDeploymentPostprocessing = 0; | ||
+ }; | ||
+/* End PBXResourcesBuildPhase section */ | ||
+ | ||
+/* Begin PBXSourcesBuildPhase section */ | ||
+ 826ACED91BF1B10A00B5FC5D /* Sources */ = { | ||
+ isa = PBXSourcesBuildPhase; | ||
+ buildActionMask = 2147483647; | ||
+ files = ( | ||
+ 826ACF1B1BF1BD7F00B5FC5D /* ExternalApplication.swift in Sources */, | ||
+ 826ACF5E1BF1E4BE00B5FC5D /* NSExtensionContext+Appz.swift in Sources */, | ||
+ 826ACF221BF1BEBF00B5FC5D /* AppStore.swift in Sources */, | ||
+ 826ACF1E1BF1BEB000B5FC5D /* Twitter.swift in Sources */, | ||
+ 826ACF201BF1BEB800B5FC5D /* Settings.swift in Sources */, | ||
+ 826ACF191BF1BD1F00B5FC5D /* AvailableApplications.swift in Sources */, | ||
+ 826ACF5C1BF1E26B00B5FC5D /* ApplicationCaller.swift in Sources */, | ||
+ 826ACF251BF1C00800B5FC5D /* UIApplication+Appz.swift in Sources */, | ||
+ ); | ||
+ runOnlyForDeploymentPostprocessing = 0; | ||
+ }; | ||
+ 826ACEE41BF1B10A00B5FC5D /* Sources */ = { | ||
+ isa = PBXSourcesBuildPhase; | ||
+ buildActionMask = 2147483647; | ||
+ files = ( | ||
+ 826ACF291BF1C99600B5FC5D /* ApplicationCallerTests.swift in Sources */, | ||
+ 827EF6171BF2756C000B1607 /* ApplicationCallerMock.swift in Sources */, | ||
+ 827EF61D1BF2EBAC000B1607 /* AppStoreTests.swift in Sources */, | ||
+ 827EF61B1BF2EAA0000B1607 /* SettingsTests.swift in Sources */, | ||
+ 826ACF271BF1C1CF00B5FC5D /* TwitterTests.swift in Sources */, | ||
+ ); | ||
+ runOnlyForDeploymentPostprocessing = 0; | ||
+ }; | ||
+/* End PBXSourcesBuildPhase section */ | ||
+ | ||
+/* Begin PBXTargetDependency section */ | ||
+ 826ACEEB1BF1B10A00B5FC5D /* PBXTargetDependency */ = { | ||
+ isa = PBXTargetDependency; | ||
+ target = 826ACEDD1BF1B10A00B5FC5D /* Appz-ios */; | ||
+ targetProxy = 826ACEEA1BF1B10A00B5FC5D /* PBXContainerItemProxy */; | ||
+ }; | ||
+/* End PBXTargetDependency section */ | ||
+ | ||
+/* Begin XCBuildConfiguration section */ | ||
+ 826ACEF01BF1B10A00B5FC5D /* Debug */ = { | ||
+ isa = XCBuildConfiguration; | ||
+ buildSettings = { | ||
+ ALWAYS_SEARCH_USER_PATHS = NO; | ||
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; | ||
+ CLANG_CXX_LIBRARY = "libc++"; | ||
+ CLANG_ENABLE_MODULES = YES; | ||
+ CLANG_ENABLE_OBJC_ARC = YES; | ||
+ CLANG_WARN_BOOL_CONVERSION = YES; | ||
+ CLANG_WARN_CONSTANT_CONVERSION = YES; | ||
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | ||
+ CLANG_WARN_EMPTY_BODY = YES; | ||
+ CLANG_WARN_ENUM_CONVERSION = YES; | ||
+ CLANG_WARN_INT_CONVERSION = YES; | ||
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | ||
+ CLANG_WARN_UNREACHABLE_CODE = YES; | ||
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | ||
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; | ||
+ COPY_PHASE_STRIP = NO; | ||
+ CURRENT_PROJECT_VERSION = 1; | ||
+ DEBUG_INFORMATION_FORMAT = dwarf; | ||
+ ENABLE_STRICT_OBJC_MSGSEND = YES; | ||
+ ENABLE_TESTABILITY = YES; | ||
+ GCC_C_LANGUAGE_STANDARD = gnu99; | ||
+ GCC_DYNAMIC_NO_PIC = NO; | ||
+ GCC_NO_COMMON_BLOCKS = YES; | ||
+ GCC_OPTIMIZATION_LEVEL = 0; | ||
+ GCC_PREPROCESSOR_DEFINITIONS = ( | ||
+ "DEBUG=1", | ||
+ "$(inherited)", | ||
+ ); | ||
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | ||
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | ||
+ GCC_WARN_UNDECLARED_SELECTOR = YES; | ||
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | ||
+ GCC_WARN_UNUSED_FUNCTION = YES; | ||
+ GCC_WARN_UNUSED_VARIABLE = YES; | ||
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0; | ||
+ MTL_ENABLE_DEBUG_INFO = YES; | ||
+ ONLY_ACTIVE_ARCH = YES; | ||
+ SDKROOT = iphoneos; | ||
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone"; | ||
+ TARGETED_DEVICE_FAMILY = "1,2"; | ||
+ VERSIONING_SYSTEM = "apple-generic"; | ||
+ VERSION_INFO_PREFIX = ""; | ||
+ }; | ||
+ name = Debug; | ||
+ }; | ||
+ 826ACEF11BF1B10A00B5FC5D /* Release */ = { | ||
+ isa = XCBuildConfiguration; | ||
+ buildSettings = { | ||
+ ALWAYS_SEARCH_USER_PATHS = NO; | ||
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; | ||
+ CLANG_CXX_LIBRARY = "libc++"; | ||
+ CLANG_ENABLE_MODULES = YES; | ||
+ CLANG_ENABLE_OBJC_ARC = YES; | ||
+ CLANG_WARN_BOOL_CONVERSION = YES; | ||
+ CLANG_WARN_CONSTANT_CONVERSION = YES; | ||
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | ||
+ CLANG_WARN_EMPTY_BODY = YES; | ||
+ CLANG_WARN_ENUM_CONVERSION = YES; | ||
+ CLANG_WARN_INT_CONVERSION = YES; | ||
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | ||
+ CLANG_WARN_UNREACHABLE_CODE = YES; | ||
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | ||
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; | ||
+ COPY_PHASE_STRIP = NO; | ||
+ CURRENT_PROJECT_VERSION = 1; | ||
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; | ||
+ ENABLE_NS_ASSERTIONS = NO; | ||
+ ENABLE_STRICT_OBJC_MSGSEND = YES; | ||
+ GCC_C_LANGUAGE_STANDARD = gnu99; | ||
+ GCC_NO_COMMON_BLOCKS = YES; | ||
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | ||
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | ||
+ GCC_WARN_UNDECLARED_SELECTOR = YES; | ||
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | ||
+ GCC_WARN_UNUSED_FUNCTION = YES; | ||
+ GCC_WARN_UNUSED_VARIABLE = YES; | ||
+ IPHONEOS_DEPLOYMENT_TARGET = 8.0; | ||
+ MTL_ENABLE_DEBUG_INFO = NO; | ||
+ SDKROOT = iphoneos; | ||
+ TARGETED_DEVICE_FAMILY = "1,2"; | ||
+ VALIDATE_PRODUCT = YES; | ||
+ VERSIONING_SYSTEM = "apple-generic"; | ||
+ VERSION_INFO_PREFIX = ""; | ||
+ }; | ||
+ name = Release; | ||
+ }; | ||
+ 826ACEF31BF1B10A00B5FC5D /* Debug */ = { | ||
+ isa = XCBuildConfiguration; | ||
+ buildSettings = { | ||
+ CLANG_ENABLE_MODULES = YES; | ||
+ DEFINES_MODULE = YES; | ||
+ DYLIB_COMPATIBILITY_VERSION = 1; | ||
+ DYLIB_CURRENT_VERSION = 1; | ||
+ DYLIB_INSTALL_NAME_BASE = "@rpath"; | ||
+ INFOPLIST_FILE = Appz/Info.plist; | ||
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; | ||
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; | ||
+ PRODUCT_BUNDLE_IDENTIFIER = io.kitz.Appz; | ||
+ PRODUCT_NAME = Appz; | ||
+ SKIP_INSTALL = YES; | ||
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone"; | ||
+ }; | ||
+ name = Debug; | ||
+ }; | ||
+ 826ACEF41BF1B10A00B5FC5D /* Release */ = { | ||
+ isa = XCBuildConfiguration; | ||
+ buildSettings = { | ||
+ CLANG_ENABLE_MODULES = YES; | ||
+ DEFINES_MODULE = YES; | ||
+ DYLIB_COMPATIBILITY_VERSION = 1; | ||
+ DYLIB_CURRENT_VERSION = 1; | ||
+ DYLIB_INSTALL_NAME_BASE = "@rpath"; | ||
+ INFOPLIST_FILE = Appz/Info.plist; | ||
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; | ||
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; | ||
+ PRODUCT_BUNDLE_IDENTIFIER = io.kitz.Appz; | ||
+ PRODUCT_NAME = Appz; | ||
+ SKIP_INSTALL = YES; | ||
+ }; | ||
+ name = Release; | ||
+ }; | ||
+ 826ACEF61BF1B10A00B5FC5D /* Debug */ = { | ||
+ isa = XCBuildConfiguration; | ||
+ buildSettings = { | ||
+ CLANG_ENABLE_MODULES = YES; | ||
+ INFOPLIST_FILE = AppzTests/Info.plist; | ||
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; | ||
+ PRODUCT_BUNDLE_IDENTIFIER = io.kitz.AppzTests; | ||
+ PRODUCT_NAME = "$(TARGET_NAME)"; | ||
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone"; | ||
+ }; | ||
+ name = Debug; | ||
+ }; | ||
+ 826ACEF71BF1B10A00B5FC5D /* Release */ = { | ||
+ isa = XCBuildConfiguration; | ||
+ buildSettings = { | ||
+ CLANG_ENABLE_MODULES = YES; | ||
+ INFOPLIST_FILE = AppzTests/Info.plist; | ||
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; | ||
+ PRODUCT_BUNDLE_IDENTIFIER = io.kitz.AppzTests; | ||
+ PRODUCT_NAME = "$(TARGET_NAME)"; | ||
+ }; | ||
+ name = Release; | ||
+ }; | ||
+/* End XCBuildConfiguration section */ | ||
+ | ||
+/* Begin XCConfigurationList section */ | ||
+ 826ACED81BF1B10A00B5FC5D /* Build configuration list for PBXProject "Appz" */ = { | ||
+ isa = XCConfigurationList; | ||
+ buildConfigurations = ( | ||
+ 826ACEF01BF1B10A00B5FC5D /* Debug */, | ||
+ 826ACEF11BF1B10A00B5FC5D /* Release */, | ||
+ ); | ||
+ defaultConfigurationIsVisible = 0; | ||
+ defaultConfigurationName = Release; | ||
+ }; | ||
+ 826ACEF21BF1B10A00B5FC5D /* Build configuration list for PBXNativeTarget "Appz-ios" */ = { | ||
+ isa = XCConfigurationList; | ||
+ buildConfigurations = ( | ||
+ 826ACEF31BF1B10A00B5FC5D /* Debug */, | ||
+ 826ACEF41BF1B10A00B5FC5D /* Release */, | ||
+ ); | ||
+ defaultConfigurationIsVisible = 0; | ||
+ defaultConfigurationName = Release; | ||
+ }; | ||
+ 826ACEF51BF1B10A00B5FC5D /* Build configuration list for PBXNativeTarget "AppzTests" */ = { | ||
+ isa = XCConfigurationList; | ||
+ buildConfigurations = ( | ||
+ 826ACEF61BF1B10A00B5FC5D /* Debug */, | ||
+ 826ACEF71BF1B10A00B5FC5D /* Release */, | ||
+ ); | ||
+ defaultConfigurationIsVisible = 0; | ||
+ defaultConfigurationName = Release; | ||
+ }; | ||
+/* End XCConfigurationList section */ | ||
+ }; | ||
+ rootObject = 826ACED51BF1B10A00B5FC5D /* Project object */; | ||
+} |
100
Appz/Appz.xcodeproj/xcshareddata/xcschemes/Appz-ios.xcscheme
@@ -0,0 +1,100 @@ | ||
+<?xml version="1.0" encoding="UTF-8"?> | ||
+<Scheme | ||
+ LastUpgradeVersion = "0710" | ||
+ version = "1.3"> | ||
+ <BuildAction | ||
+ parallelizeBuildables = "YES" | ||
+ buildImplicitDependencies = "YES"> | ||
+ <BuildActionEntries> | ||
+ <BuildActionEntry | ||
+ buildForTesting = "YES" | ||
+ buildForRunning = "YES" | ||
+ buildForProfiling = "YES" | ||
+ buildForArchiving = "YES" | ||
+ buildForAnalyzing = "YES"> | ||
+ <BuildableReference | ||
+ BuildableIdentifier = "primary" | ||
+ BlueprintIdentifier = "826ACEDD1BF1B10A00B5FC5D" | ||
+ BuildableName = "Appz-ios.framework" | ||
+ BlueprintName = "Appz-ios" | ||
+ ReferencedContainer = "container:Appz.xcodeproj"> | ||
+ </BuildableReference> | ||
+ </BuildActionEntry> | ||
+ </BuildActionEntries> | ||
+ </BuildAction> | ||
+ <TestAction | ||
+ buildConfiguration = "Debug" | ||
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | ||
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | ||
+ shouldUseLaunchSchemeArgsEnv = "YES" | ||
+ codeCoverageEnabled = "YES"> | ||
+ <Testables> | ||
+ <TestableReference | ||
+ skipped = "NO"> | ||
+ <BuildableReference | ||
+ BuildableIdentifier = "primary" | ||
+ BlueprintIdentifier = "826ACEE71BF1B10A00B5FC5D" | ||
+ BuildableName = "AppzTests.xctest" | ||
+ BlueprintName = "AppzTests" | ||
+ ReferencedContainer = "container:Appz.xcodeproj"> | ||
+ </BuildableReference> | ||
+ </TestableReference> | ||
+ </Testables> | ||
+ <MacroExpansion> | ||
+ <BuildableReference | ||
+ BuildableIdentifier = "primary" | ||
+ BlueprintIdentifier = "826ACEDD1BF1B10A00B5FC5D" | ||
+ BuildableName = "Appz-ios.framework" | ||
+ BlueprintName = "Appz-ios" | ||
+ ReferencedContainer = "container:Appz.xcodeproj"> | ||
+ </BuildableReference> | ||
+ </MacroExpansion> | ||
+ <AdditionalOptions> | ||
+ </AdditionalOptions> | ||
+ </TestAction> | ||
+ <LaunchAction | ||
+ buildConfiguration = "Debug" | ||
+ selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB" | ||
+ selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB" | ||
+ launchStyle = "0" | ||
+ useCustomWorkingDirectory = "NO" | ||
+ ignoresPersistentStateOnLaunch = "NO" | ||
+ debugDocumentVersioning = "YES" | ||
+ debugServiceExtension = "internal" | ||
+ allowLocationSimulation = "YES"> | ||
+ <MacroExpansion> | ||
+ <BuildableReference | ||
+ BuildableIdentifier = "primary" | ||
+ BlueprintIdentifier = "826ACEDD1BF1B10A00B5FC5D" | ||
+ BuildableName = "Appz-ios.framework" | ||
+ BlueprintName = "Appz-ios" | ||
+ ReferencedContainer = "container:Appz.xcodeproj"> | ||
+ </BuildableReference> | ||
+ </MacroExpansion> | ||
+ <AdditionalOptions> | ||
+ </AdditionalOptions> | ||
+ </LaunchAction> | ||
+ <ProfileAction | ||
+ buildConfiguration = "Release" | ||
+ shouldUseLaunchSchemeArgsEnv = "YES" | ||
+ savedToolIdentifier = "" | ||
+ useCustomWorkingDirectory = "NO" | ||
+ debugDocumentVersioning = "YES"> | ||
+ <MacroExpansion> | ||
+ <BuildableReference | ||
+ BuildableIdentifier = "primary" | ||
+ BlueprintIdentifier = "826ACEDD1BF1B10A00B5FC5D" | ||
+ BuildableName = "Appz-ios.framework" | ||
+ BlueprintName = "Appz-ios" | ||
+ ReferencedContainer = "container:Appz.xcodeproj"> | ||
+ </BuildableReference> | ||
+ </MacroExpansion> | ||
+ </ProfileAction> | ||
+ <AnalyzeAction | ||
+ buildConfiguration = "Debug"> | ||
+ </AnalyzeAction> | ||
+ <ArchiveAction | ||
+ buildConfiguration = "Release" | ||
+ revealArchiveInOrganizer = "YES"> | ||
+ </ArchiveAction> | ||
+</Scheme> |
50
Appz/Appz/Apps/AppStore.swift
@@ -0,0 +1,50 @@ | ||
+// | ||
+// AppStore.swift | ||
+// Appz | ||
+// | ||
+// Created by Mazyad Alabduljaleel on 11/9/15. | ||
+// Copyright © 2015 kitz. All rights reserved. | ||
+// | ||
+ | ||
+import Foundation | ||
+ | ||
+ | ||
+public extension AvailableApplications { | ||
+ | ||
+ public struct AppStore: ExternalApplication { | ||
+ | ||
+ public let scheme = "itms-apps:" | ||
+ public let fallbackURL: String? = "http:" | ||
+ } | ||
+ | ||
+ public func appStore(action: AppStore.Action) -> Bool { | ||
+ return appCaller.launch(AppStore(), action: action) | ||
+ } | ||
+} | ||
+ | ||
+// MARK: - Actions | ||
+ | ||
+public extension AvailableApplications.AppStore { | ||
+ | ||
+ public enum Action { | ||
+ | ||
+ case Account(id: String) | ||
+ case App(id: String) | ||
+ } | ||
+} | ||
+ | ||
+ | ||
+extension AvailableApplications.AppStore.Action: ExternalApplicationAction { | ||
+ | ||
+ public var path: String { | ||
+ | ||
+ switch self { | ||
+ case .Account(let id): | ||
+ return "itunes.apple.com/developer/id\(id)" | ||
+ | ||
+ case .App(let id): | ||
+ return "itunes.apple.com/apps/id\(id)" | ||
+ } | ||
+ } | ||
+} | ||
+ |
35
Appz/Appz/Apps/Settings.swift
@@ -0,0 +1,35 @@ | ||
+// | ||
+// Settings.swift | ||
+// Appz | ||
+// | ||
+// Created by Mazyad Alabduljaleel on 11/9/15. | ||
+// Copyright © 2015 kitz. All rights reserved. | ||
+// | ||
+ | ||
+import UIKit | ||
+ | ||
+ | ||
+public extension AvailableApplications { | ||
+ | ||
+ public struct AppSettings: ExternalApplication { | ||
+ | ||
+ public let scheme = UIApplicationOpenSettingsURLString | ||
+ public let fallbackURL: String? = nil | ||
+ } | ||
+ | ||
+ func appSettings(action: AppSettings.Action) -> Bool { | ||
+ return appCaller.launch(AppSettings(), action: action) | ||
+ } | ||
+} | ||
+ | ||
+// MARK: - Actions | ||
+ | ||
+public extension AvailableApplications.AppSettings { | ||
+ | ||
+ public enum Action { | ||
+ | ||
+ case Open | ||
+ } | ||
+} | ||
+ | ||
+extension AvailableApplications.AppSettings.Action: ExternalApplicationAction {} |
119
Appz/Appz/Apps/Twitter.swift
@@ -0,0 +1,119 @@ | ||
+// | ||
+// Twitter.swift | ||
+// Appz | ||
+// | ||
+// Created by Mazyad Alabduljaleel on 11/9/15. | ||
+// Copyright © 2015 kitz. All rights reserved. | ||
+// | ||
+ | ||
+import Foundation | ||
+ | ||
+ | ||
+public extension AvailableApplications { | ||
+ | ||
+ public struct Twitter: ExternalApplication { | ||
+ | ||
+ public let scheme = "twitter:" | ||
+ public let fallbackURL: String? = "https://twitter.com/" | ||
+ } | ||
+ | ||
+ public func twitter(action: Twitter.Action) -> Bool { | ||
+ return appCaller.launch(Twitter(), action: action) | ||
+ } | ||
+} | ||
+ | ||
+// MARK: - Actions | ||
+ | ||
+public extension AvailableApplications.Twitter { | ||
+ | ||
+ public enum Action { | ||
+ | ||
+ case Status(id: String) | ||
+ case UserHandle(String) | ||
+ case UserId(String) | ||
+ case List(handle: String, slug: String) | ||
+ case Post(message: String, repliedStatusId: String?) | ||
+ case Search(query: String) | ||
+ case Timeline | ||
+ case Mentions | ||
+ case Messages | ||
+ } | ||
+} | ||
+ | ||
+extension AvailableApplications.Twitter.Action: ExternalApplicationAction { | ||
+ | ||
+ public var path: String { | ||
+ | ||
+ switch self { | ||
+ case .Status(let id): | ||
+ return "status?id=\(id)" | ||
+ | ||
+ case .UserHandle(let handle): | ||
+ return "user?screen_name=\(handle)" | ||
+ | ||
+ case .UserId(let id): | ||
+ return "user?id=\(id)" | ||
+ | ||
+ case .Post(let message, let statusId): | ||
+ | ||
+ var path = "post?message=\(escape(message))" | ||
+ if let statusId = statusId { | ||
+ path += "&in_reply_to_status_id=\(statusId)" | ||
+ } | ||
+ return path | ||
+ | ||
+ case .List(let handle, let slug): | ||
+ return "list?screen_name=\(handle)&slug=\(escape(slug))" | ||
+ | ||
+ case .Search(let query): | ||
+ return "search?query=\(escape(query))" | ||
+ | ||
+ case .Timeline: | ||
+ return "timeline" | ||
+ | ||
+ case .Mentions: | ||
+ return "mentions" | ||
+ | ||
+ case .Messages: | ||
+ return "messages" | ||
+ } | ||
+ } | ||
+ | ||
+ public var fallbackPath: String? { | ||
+ | ||
+ switch self { | ||
+ case .Status(let id): | ||
+ return "statuses/\(id)" | ||
+ | ||
+ case .UserHandle(let handle): | ||
+ return handle | ||
+ | ||
+ case .UserId(let id): | ||
+ return "intent/user?user_id=\(id)" | ||
+ | ||
+ case .Post(let message, let statusId): | ||
+ | ||
+ var path = "intent/tweet?text=\(escape(message))" | ||
+ if let statusId = statusId { | ||
+ path += "&in_reply_to=\(statusId)" | ||
+ } | ||
+ return path | ||
+ | ||
+ case .List(let handle, let slug): | ||
+ return "\(handle)/lists/\(slug)" | ||
+ | ||
+ case .Search(let query): | ||
+ return "search?q=\(escape(query))" | ||
+ | ||
+ case .Timeline: | ||
+ return "" // Just open twitter | ||
+ | ||
+ case .Mentions: | ||
+ return "mentions" | ||
+ | ||
+ case .Messages: | ||
+ return "messages" | ||
+ } | ||
+ } | ||
+} | ||
+ |
19
Appz/Appz/Appz.h
@@ -0,0 +1,19 @@ | ||
+// | ||
+// Appz.h | ||
+// Appz | ||
+// | ||
+// Created by Mazyad Alabduljaleel on 11/9/15. | ||
+// Copyright © 2015 kitz. All rights reserved. | ||
+// | ||
+ | ||
+#import <UIKit/UIKit.h> | ||
+ | ||
+//! Project version number for Appz. | ||
+FOUNDATION_EXPORT double AppzVersionNumber; | ||
+ | ||
+//! Project version string for Appz. | ||
+FOUNDATION_EXPORT const unsigned char AppzVersionString[]; | ||
+ | ||
+// In this header, you should import all the public headers of your framework using statements like #import <Appz/PublicHeader.h> | ||
+ | ||
+ |
48
Appz/Appz/Entity/ApplicationCaller.swift
@@ -0,0 +1,48 @@ | ||
+// | ||
+// ApplicationCaller.swift | ||
+// Appz | ||
+// | ||
+// Created by Mazyad Alabduljaleel on 11/10/15. | ||
+// Copyright © 2015 kitz. All rights reserved. | ||
+// | ||
+ | ||
+import Foundation | ||
+ | ||
+ | ||
+/** Encapsulate the object which launches the apps. Useful for | ||
+ UIApplication, NSExtensionContext, and testing. | ||
+*/ | ||
+public protocol ApplicationCaller { | ||
+ | ||
+ func canOpenURL(url: NSURL) -> Bool | ||
+ func openURL(url: NSURL) -> Bool | ||
+} | ||
+ | ||
+public extension ApplicationCaller { | ||
+ | ||
+ public var open: AvailableApplications { | ||
+ return AvailableApplications(appCaller: self) | ||
+ } | ||
+ | ||
+ func launch(externalApp: ExternalApplication, action: ExternalApplicationAction) -> Bool { | ||
+ | ||
+ let fallbackPath = action.fallbackPath ?? action.path | ||
+ | ||
+ let scheme = (externalApp.scheme ?? "") + "//" | ||
+ let baseURL = NSURL(string: scheme) | ||
+ | ||
+ if let url = baseURL where canOpenURL(url), | ||
+ let fullURL = NSURL(string: scheme + action.path) | ||
+ { | ||
+ return openURL(fullURL) | ||
+ } | ||
+ | ||
+ if let fallbackURL = externalApp.fallbackURL, | ||
+ let url = NSURL(string: fallbackURL + fallbackPath) | ||
+ { | ||
+ return openURL(url) | ||
+ } | ||
+ | ||
+ return false | ||
+ } | ||
+} |
21
Appz/Appz/Entity/AvailableApplications.swift
@@ -0,0 +1,21 @@ | ||
+// | ||
+// AvailableApplications.swift | ||
+// Appz | ||
+// | ||
+// Created by Mazyad Alabduljaleel on 11/9/15. | ||
+// Copyright © 2015 kitz. All rights reserved. | ||
+// | ||
+ | ||
+import Foundation | ||
+ | ||
+ | ||
+/** Base for aggregating the available applications. | ||
+ */ | ||
+public struct AvailableApplications { | ||
+ | ||
+ public let appCaller: ApplicationCaller | ||
+ | ||
+ init(appCaller: ApplicationCaller) { | ||
+ self.appCaller = appCaller | ||
+ } | ||
+} |
40
Appz/Appz/Entity/ExternalApplication.swift
@@ -0,0 +1,40 @@ | ||
+// | ||
+// ExternalApplication.swift | ||
+// Appz | ||
+// | ||
+// Created by Mazyad Alabduljaleel on 11/9/15. | ||
+// Copyright © 2015 kitz. All rights reserved. | ||
+// | ||
+ | ||
+import Foundation | ||
+ | ||
+ | ||
+/** Protocol for grouping the external application functionality. | ||
+ For now, it's as simple as calling openURL | ||
+ */ | ||
+public protocol ExternalApplication { | ||
+ | ||
+ var scheme: String { get } | ||
+ var fallbackURL: String? { get } | ||
+} | ||
+ | ||
+public protocol ExternalApplicationAction { | ||
+ | ||
+ var path: String { get } | ||
+ var fallbackPath: String? { get } | ||
+} | ||
+ | ||
+public extension ExternalApplicationAction { | ||
+ | ||
+ var path: String { | ||
+ return "" | ||
+ } | ||
+ | ||
+ var fallbackPath: String? { | ||
+ return nil | ||
+ } | ||
+ | ||
+ func escape(string: String) -> String { | ||
+ return string.stringByAddingPercentEncodingWithAllowedCharacters(NSCharacterSet.URLQueryAllowedCharacterSet()) ?? "" | ||
+ } | ||
+} |
24
Appz/Appz/Extensions/NSExtensionContext+Appz.swift
@@ -0,0 +1,24 @@ | ||
+// | ||
+// NSExtensionContext+Appz.swift | ||
+// Appz | ||
+// | ||
+// Created by Mazyad Alabduljaleel on 11/10/15. | ||
+// Copyright © 2015 kitz. All rights reserved. | ||
+// | ||
+ | ||
+import Foundation | ||
+ | ||
+ | ||
+extension NSExtensionContext: ApplicationCaller { | ||
+ | ||
+ /** Unconditionally fail to the failover code. See rdar://18107612 | ||
+ */ | ||
+ public func canOpenURL(url: NSURL) -> Bool { | ||
+ return false | ||
+ } | ||
+ | ||
+ public func openURL(url: NSURL) -> Bool { | ||
+ openURL(url, completionHandler: nil) | ||
+ return true // maybe use a semaphore instead | ||
+ } | ||
+} |
12
Appz/Appz/Extensions/UIApplication+Appz.swift
@@ -0,0 +1,12 @@ | ||
+// | ||
+// UIApplication+Appz.swift | ||
+// Appz | ||
+// | ||
+// Created by Mazyad Alabduljaleel on 11/9/15. | ||
+// Copyright © 2015 kitz. All rights reserved. | ||
+// | ||
+ | ||
+import UIKit | ||
+ | ||
+ | ||
+extension UIApplication: ApplicationCaller {} |
26
Appz/Appz/Info.plist
@@ -0,0 +1,26 @@ | ||
+<?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>$(PRODUCT_BUNDLE_IDENTIFIER)</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> |
41
Appz/AppzTests/AppStoreTests.swift
@@ -0,0 +1,41 @@ | ||
+// | ||
+// AppStoreTests.swift | ||
+// Appz | ||
+// | ||
+// Created by Mazyad Alabduljaleel on 11/10/15. | ||
+// Copyright © 2015 kitz. All rights reserved. | ||
+// | ||
+ | ||
+import XCTest | ||
+@testable import Appz | ||
+ | ||
+ | ||
+class AppStoreTests: XCTestCase { | ||
+ | ||
+ let appCaller = ApplicationCallerMock() | ||
+ | ||
+ func testConfiguration() { | ||
+ | ||
+ let appStore = AvailableApplications.AppStore() | ||
+ XCTAssertEqual(appStore.scheme, "itms-apps:") | ||
+ XCTAssertEqual(appStore.fallbackURL, "http:") | ||
+ } | ||
+ | ||
+ func testOpenApp() { | ||
+ | ||
+ let appId = "395107915" | ||
+ let action = AvailableApplications.AppStore.Action.App(id: appId) | ||
+ | ||
+ XCTAssertEqual(action.path, "itunes.apple.com/apps/id\(appId)") | ||
+ XCTAssertEqual(action.fallbackPath, nil) | ||
+ } | ||
+ | ||
+ func testOpenAccount() { | ||
+ | ||
+ let accountId = "395107918" | ||
+ let action = AvailableApplications.AppStore.Action.Account(id: accountId) | ||
+ | ||
+ XCTAssertEqual(action.path, "itunes.apple.com/developer/id\(accountId)") | ||
+ XCTAssertEqual(action.fallbackPath, nil) | ||
+ } | ||
+} |
96
Appz/AppzTests/ApplicationCallerTests.swift
@@ -0,0 +1,96 @@ | ||
+// | ||
+// ApplicationCallerTests.swift | ||
+// Appz | ||
+// | ||
+// Created by Mazyad Alabduljaleel on 11/9/15. | ||
+// Copyright © 2015 kitz. All rights reserved. | ||
+// | ||
+ | ||
+import XCTest | ||
+@testable import Appz | ||
+ | ||
+ | ||
+class ApplicationCallerTests: XCTestCase { | ||
+ | ||
+ private struct SampleApp: ExternalApplication { | ||
+ | ||
+ let scheme = "test:" | ||
+ let fallbackURL: String? = "http://google.com/" | ||
+ } | ||
+ | ||
+ private struct SampleAction: ExternalApplicationAction { | ||
+ | ||
+ var path = "search/something?param=5" | ||
+ var fallbackPath: String? = "find/otherThing?param=1" | ||
+ } | ||
+ | ||
+ | ||
+ private let appCallerMock = ApplicationCallerMock() | ||
+ | ||
+ | ||
+ override func setUp() { | ||
+ super.setUp() | ||
+ | ||
+ appCallerMock.clear() | ||
+ } | ||
+ | ||
+ func testQuery() { | ||
+ | ||
+ let sampleApp = SampleApp() | ||
+ appCallerMock.launch(sampleApp, action: SampleAction()) | ||
+ | ||
+ let expectedURL = NSURL(string: "\(sampleApp.scheme)//") | ||
+ XCTAssertEqual(appCallerMock.queriedURLs[0], expectedURL) | ||
+ } | ||
+ | ||
+ func testOpenEmptyPath() { | ||
+ | ||
+ let sampleApp = SampleApp() | ||
+ var sampleAction = SampleAction() | ||
+ sampleAction.path = "" | ||
+ | ||
+ appCallerMock.canOpenURLs = true | ||
+ appCallerMock.launch(sampleApp, action: sampleAction) | ||
+ | ||
+ let expectedURL = NSURL(string: "\(sampleApp.scheme)//") | ||
+ XCTAssertEqual(appCallerMock.openedURLs[0], expectedURL) | ||
+ } | ||
+ | ||
+ func testOpenPath() { | ||
+ | ||
+ let sampleApp = SampleApp() | ||
+ let sampleAction = SampleAction() | ||
+ | ||
+ appCallerMock.canOpenURLs = true | ||
+ appCallerMock.launch(sampleApp, action: sampleAction) | ||
+ | ||
+ let expectedURL = NSURL(string: "\(sampleApp.scheme)//" + sampleAction.path) | ||
+ XCTAssertEqual(appCallerMock.openedURLs[0], expectedURL) | ||
+ } | ||
+ | ||
+ func testOpenFallbackPath() { | ||
+ | ||
+ let sampleApp = SampleApp() | ||
+ let sampleAction = SampleAction() | ||
+ | ||
+ appCallerMock.canOpenURLs = false | ||
+ appCallerMock.launch(sampleApp, action: sampleAction) | ||
+ | ||
+ let expectedURL = NSURL(string: sampleApp.fallbackURL! + sampleAction.fallbackPath!) | ||
+ XCTAssertEqual(appCallerMock.openedURLs[0], expectedURL) | ||
+ } | ||
+ | ||
+ func testOpenNilFallbackPath() { | ||
+ | ||
+ let sampleApp = SampleApp() | ||
+ var sampleAction = SampleAction() | ||
+ sampleAction.fallbackPath = nil | ||
+ | ||
+ appCallerMock.canOpenURLs = false | ||
+ appCallerMock.launch(sampleApp, action: sampleAction) | ||
+ | ||
+ // it should use path as the fallbackPath | ||
+ let expectedURL = NSURL(string: sampleApp.fallbackURL! + sampleAction.path) | ||
+ XCTAssertEqual(appCallerMock.openedURLs[0], expectedURL) | ||
+ } | ||
+} |
24
Appz/AppzTests/Info.plist
@@ -0,0 +1,24 @@ | ||
+<?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>$(PRODUCT_BUNDLE_IDENTIFIER)</string> | ||
+ <key>CFBundleInfoDictionaryVersion</key> | ||
+ <string>6.0</string> | ||
+ <key>CFBundleName</key> | ||
+ <string>$(PRODUCT_NAME)</string> | ||
+ <key>CFBundlePackageType</key> | ||
+ <string>BNDL</string> | ||
+ <key>CFBundleShortVersionString</key> | ||
+ <string>1.0</string> | ||
+ <key>CFBundleSignature</key> | ||
+ <string>????</string> | ||
+ <key>CFBundleVersion</key> | ||
+ <string>1</string> | ||
+</dict> | ||
+</plist> |
34
Appz/AppzTests/Mocks/ApplicationCallerMock.swift
@@ -0,0 +1,34 @@ | ||
+// | ||
+// ApplicationCallerMock.swift | ||
+// Appz | ||
+// | ||
+// Created by Mazyad Alabduljaleel on 11/10/15. | ||
+// Copyright © 2015 kitz. All rights reserved. | ||
+// | ||
+ | ||
+import Foundation | ||
+@testable import Appz | ||
+ | ||
+ | ||
+class ApplicationCallerMock: ApplicationCaller { | ||
+ | ||
+ var canOpenURLs = true | ||
+ | ||
+ var queriedURLs = [NSURL]() | ||
+ var openedURLs = [NSURL]() | ||
+ | ||
+ func openURL(url: NSURL) -> Bool { | ||
+ openedURLs.append(url) | ||
+ return true | ||
+ } | ||
+ | ||
+ func canOpenURL(url: NSURL) -> Bool { | ||
+ queriedURLs.append(url) | ||
+ return canOpenURLs | ||
+ } | ||
+ | ||
+ func clear() { | ||
+ queriedURLs.removeAll() | ||
+ openedURLs.removeAll() | ||
+ } | ||
+} |
30
Appz/AppzTests/SettingsTests.swift
@@ -0,0 +1,30 @@ | ||
+// | ||
+// SettingsTests.swift | ||
+// Appz | ||
+// | ||
+// Created by Mazyad Alabduljaleel on 11/10/15. | ||
+// Copyright © 2015 kitz. All rights reserved. | ||
+// | ||
+ | ||
+import XCTest | ||
+@testable import Appz | ||
+ | ||
+ | ||
+class SettingsTests: XCTestCase { | ||
+ | ||
+ let appCaller = ApplicationCallerMock() | ||
+ | ||
+ func testConfiguration() { | ||
+ | ||
+ let appSettings = AvailableApplications.AppSettings() | ||
+ XCTAssertEqual(appSettings.scheme, "app-settings:") | ||
+ XCTAssertEqual(appSettings.fallbackURL, nil) | ||
+ } | ||
+ | ||
+ func testOpenHome() { | ||
+ | ||
+ let action = AvailableApplications.AppSettings.Action.Open | ||
+ XCTAssertEqual(action.path, "") | ||
+ XCTAssertEqual(action.fallbackPath, nil) | ||
+ } | ||
+} |
41
Appz/AppzTests/TwitterTests.swift
@@ -0,0 +1,41 @@ | ||
+// | ||
+// TwitterTests.swift | ||
+// Appz | ||
+// | ||
+// Created by Mazyad Alabduljaleel on 11/9/15. | ||
+// Copyright © 2015 kitz. All rights reserved. | ||
+// | ||
+ | ||
+import XCTest | ||
+@testable import Appz | ||
+ | ||
+ | ||
+class TwitterTests: XCTestCase { | ||
+ | ||
+ let appCaller = ApplicationCallerMock() | ||
+ | ||
+ func testConfiguration() { | ||
+ | ||
+ let twitter = AvailableApplications.Twitter() | ||
+ XCTAssertEqual(twitter.scheme, "twitter:") | ||
+ XCTAssertEqual(twitter.fallbackURL, "https://twitter.com/") | ||
+ } | ||
+ | ||
+ func testOpenUserHandle() { | ||
+ | ||
+ let handle = "mazyod" | ||
+ let action = AvailableApplications.Twitter.Action.UserHandle(handle) | ||
+ | ||
+ XCTAssertEqual(action.path, "user?screen_name=\(handle)") | ||
+ XCTAssertEqual(action.fallbackPath, handle) | ||
+ } | ||
+ | ||
+ func testOpenStatus() { | ||
+ | ||
+ let statusId = "663797797234323456" | ||
+ let action = AvailableApplications.Twitter.Action.Status(id: statusId) | ||
+ | ||
+ XCTAssertEqual(action.path, "status?id=\(statusId)") | ||
+ XCTAssertEqual(action.fallbackPath, "statuses/\(statusId)") | ||
+ } | ||
+} |
21
LICENSE
@@ -0,0 +1,21 @@ | ||
+The MIT License (MIT) | ||
+ | ||
+Copyright (c) 2015 Kitz | ||
+ | ||
+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. |
37
Playground/Playground.playground/Contents.swift
@@ -0,0 +1,37 @@ | ||
+//: Playground - noun: a place where people can play | ||
+ | ||
+import UIKit | ||
+import Appz | ||
+ | ||
+//: ## Features | ||
+//: Concise syntax to trigger deeplinking | ||
+ | ||
+let app = UIApplication.sharedApplication() | ||
+app.open.appStore(.Account(id: "395107918")) | ||
+app.open.twitter(.UserHandle("mazyod")) | ||
+app.open.appSettings(.Open) | ||
+ | ||
+//: Add your own application | ||
+ | ||
+extension AvailableApplications { | ||
+ | ||
+ struct MyApp: ExternalApplication { | ||
+ | ||
+ let scheme = "myapp:" | ||
+ let fallbackURL: String? = nil | ||
+ } | ||
+ | ||
+ func myApp(action: MyApp.Action) -> Bool { | ||
+ return appCaller.launch(MyApp(), action: action) | ||
+ } | ||
+} | ||
+ | ||
+extension AvailableApplications.MyApp { | ||
+ | ||
+ enum Action: ExternalApplicationAction { | ||
+ | ||
+ case Open | ||
+ } | ||
+} | ||
+ | ||
+app.open.myApp(.Open) |
430
Playground/Playground.playground/Sources/Appz.xcodeproj/project.pbxproj
@@ -0,0 +1,430 @@ | ||
+// !$*UTF8*$! | ||
+{ | ||
+ archiveVersion = 1; | ||
+ classes = { | ||
+ }; | ||
+ objectVersion = 46; | ||
+ objects = { | ||
+ | ||
+/* Begin PBXBuildFile section */ | ||
+ 826ACEE21BF1B10A00B5FC5D /* Appz.h in Headers */ = {isa = PBXBuildFile; fileRef = 826ACEE11BF1B10A00B5FC5D /* Appz.h */; settings = {ATTRIBUTES = (Public, ); }; }; | ||
+ 826ACEE91BF1B10A00B5FC5D /* Appz.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 826ACEDE1BF1B10A00B5FC5D /* Appz.framework */; }; | ||
+ 826ACEEE1BF1B10A00B5FC5D /* AppzTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACEED1BF1B10A00B5FC5D /* AppzTests.swift */; }; | ||
+ 826ACF191BF1BD1F00B5FC5D /* AvailableApplications.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF181BF1BD1F00B5FC5D /* AvailableApplications.swift */; }; | ||
+ 826ACF1B1BF1BD7F00B5FC5D /* ApplicationAccess.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF1A1BF1BD7F00B5FC5D /* ApplicationAccess.swift */; }; | ||
+ 826ACF1E1BF1BEB000B5FC5D /* Twitter.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF1D1BF1BEB000B5FC5D /* Twitter.swift */; }; | ||
+ 826ACF201BF1BEB800B5FC5D /* Settings.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF1F1BF1BEB800B5FC5D /* Settings.swift */; }; | ||
+ 826ACF221BF1BEBF00B5FC5D /* AppStore.swift in Sources */ = {isa = PBXBuildFile; fileRef = 826ACF211BF1BEBF00B5FC5D /* AppStore.swift */; }; | ||
+/* End PBXBuildFile section */ | ||
+ | ||
+/* Begin PBXContainerItemProxy section */ | ||
+ 826ACEEA1BF1B10A00B5FC5D /* PBXContainerItemProxy */ = { | ||
+ isa = PBXContainerItemProxy; | ||
+ containerPortal = 826ACED51BF1B10A00B5FC5D /* Project object */; | ||
+ proxyType = 1; | ||
+ remoteGlobalIDString = 826ACEDD1BF1B10A00B5FC5D; | ||
+ remoteInfo = Appz; | ||
+ }; | ||
+/* End PBXContainerItemProxy section */ | ||
+ | ||
+/* Begin PBXFileReference section */ | ||
+ 826ACEDE1BF1B10A00B5FC5D /* Appz.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Appz.framework; sourceTree = BUILT_PRODUCTS_DIR; }; | ||
+ 826ACEE11BF1B10A00B5FC5D /* Appz.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Appz.h; sourceTree = "<group>"; }; | ||
+ 826ACEE31BF1B10A00B5FC5D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; | ||
+ 826ACEE81BF1B10A00B5FC5D /* AppzTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = AppzTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; | ||
+ 826ACEED1BF1B10A00B5FC5D /* AppzTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = AppzTests.swift; sourceTree = "<group>"; }; | ||
+ 826ACEEF1BF1B10A00B5FC5D /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = "<group>"; }; | ||
+ 826ACF181BF1BD1F00B5FC5D /* AvailableApplications.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AvailableApplications.swift; sourceTree = "<group>"; }; | ||
+ 826ACF1A1BF1BD7F00B5FC5D /* ApplicationAccess.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ApplicationAccess.swift; sourceTree = "<group>"; }; | ||
+ 826ACF1D1BF1BEB000B5FC5D /* Twitter.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Twitter.swift; sourceTree = "<group>"; }; | ||
+ 826ACF1F1BF1BEB800B5FC5D /* Settings.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Settings.swift; sourceTree = "<group>"; }; | ||
+ 826ACF211BF1BEBF00B5FC5D /* AppStore.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppStore.swift; sourceTree = "<group>"; }; | ||
+/* End PBXFileReference section */ | ||
+ | ||
+/* Begin PBXFrameworksBuildPhase section */ | ||
+ 826ACEDA1BF1B10A00B5FC5D /* Frameworks */ = { | ||
+ isa = PBXFrameworksBuildPhase; | ||
+ buildActionMask = 2147483647; | ||
+ files = ( | ||
+ ); | ||
+ runOnlyForDeploymentPostprocessing = 0; | ||
+ }; | ||
+ 826ACEE51BF1B10A00B5FC5D /* Frameworks */ = { | ||
+ isa = PBXFrameworksBuildPhase; | ||
+ buildActionMask = 2147483647; | ||
+ files = ( | ||
+ 826ACEE91BF1B10A00B5FC5D /* Appz.framework in Frameworks */, | ||
+ ); | ||
+ runOnlyForDeploymentPostprocessing = 0; | ||
+ }; | ||
+/* End PBXFrameworksBuildPhase section */ | ||
+ | ||
+/* Begin PBXGroup section */ | ||
+ 826ACED41BF1B10A00B5FC5D = { | ||
+ isa = PBXGroup; | ||
+ children = ( | ||
+ 826ACEE01BF1B10A00B5FC5D /* Appz */, | ||
+ 826ACEEC1BF1B10A00B5FC5D /* AppzTests */, | ||
+ 826ACEDF1BF1B10A00B5FC5D /* Products */, | ||
+ ); | ||
+ sourceTree = "<group>"; | ||
+ }; | ||
+ 826ACEDF1BF1B10A00B5FC5D /* Products */ = { | ||
+ isa = PBXGroup; | ||
+ children = ( | ||
+ 826ACEDE1BF1B10A00B5FC5D /* Appz.framework */, | ||
+ 826ACEE81BF1B10A00B5FC5D /* AppzTests.xctest */, | ||
+ ); | ||
+ name = Products; | ||
+ sourceTree = "<group>"; | ||
+ }; | ||
+ 826ACEE01BF1B10A00B5FC5D /* Appz */ = { | ||
+ isa = PBXGroup; | ||
+ children = ( | ||
+ 826ACF1C1BF1BE9C00B5FC5D /* Apps */, | ||
+ 826ACF171BF1BCF500B5FC5D /* Entity */, | ||
+ 826ACEE11BF1B10A00B5FC5D /* Appz.h */, | ||
+ 826ACEE31BF1B10A00B5FC5D /* Info.plist */, | ||
+ ); | ||
+ path = Appz; | ||
+ sourceTree = "<group>"; | ||
+ }; | ||
+ 826ACEEC1BF1B10A00B5FC5D /* AppzTests */ = { | ||
+ isa = PBXGroup; | ||
+ children = ( | ||
+ 826ACEED1BF1B10A00B5FC5D /* AppzTests.swift */, | ||
+ 826ACEEF1BF1B10A00B5FC5D /* Info.plist */, | ||
+ ); | ||
+ path = AppzTests; | ||
+ sourceTree = "<group>"; | ||
+ }; | ||
+ 826ACF171BF1BCF500B5FC5D /* Entity */ = { | ||
+ isa = PBXGroup; | ||
+ children = ( | ||
+ 826ACF181BF1BD1F00B5FC5D /* AvailableApplications.swift */, | ||
+ 826ACF1A1BF1BD7F00B5FC5D /* ApplicationAccess.swift */, | ||
+ ); | ||
+ path = Entity; | ||
+ sourceTree = "<group>"; | ||
+ }; | ||
+ 826ACF1C1BF1BE9C00B5FC5D /* Apps */ = { | ||
+ isa = PBXGroup; | ||
+ children = ( | ||
+ 826ACF1D1BF1BEB000B5FC5D /* Twitter.swift */, | ||
+ 826ACF1F1BF1BEB800B5FC5D /* Settings.swift */, | ||
+ 826ACF211BF1BEBF00B5FC5D /* AppStore.swift */, | ||
+ ); | ||
+ path = Apps; | ||
+ sourceTree = "<group>"; | ||
+ }; | ||
+/* End PBXGroup section */ | ||
+ | ||
+/* Begin PBXHeadersBuildPhase section */ | ||
+ 826ACEDB1BF1B10A00B5FC5D /* Headers */ = { | ||
+ isa = PBXHeadersBuildPhase; | ||
+ buildActionMask = 2147483647; | ||
+ files = ( | ||
+ 826ACEE21BF1B10A00B5FC5D /* Appz.h in Headers */, | ||
+ ); | ||
+ runOnlyForDeploymentPostprocessing = 0; | ||
+ }; | ||
+/* End PBXHeadersBuildPhase section */ | ||
+ | ||
+/* Begin PBXNativeTarget section */ | ||
+ 826ACEDD1BF1B10A00B5FC5D /* Appz */ = { | ||
+ isa = PBXNativeTarget; | ||
+ buildConfigurationList = 826ACEF21BF1B10A00B5FC5D /* Build configuration list for PBXNativeTarget "Appz" */; | ||
+ buildPhases = ( | ||
+ 826ACED91BF1B10A00B5FC5D /* Sources */, | ||
+ 826ACEDA1BF1B10A00B5FC5D /* Frameworks */, | ||
+ 826ACEDB1BF1B10A00B5FC5D /* Headers */, | ||
+ 826ACEDC1BF1B10A00B5FC5D /* Resources */, | ||
+ ); | ||
+ buildRules = ( | ||
+ ); | ||
+ dependencies = ( | ||
+ ); | ||
+ name = Appz; | ||
+ productName = Appz; | ||
+ productReference = 826ACEDE1BF1B10A00B5FC5D /* Appz.framework */; | ||
+ productType = "com.apple.product-type.framework"; | ||
+ }; | ||
+ 826ACEE71BF1B10A00B5FC5D /* AppzTests */ = { | ||
+ isa = PBXNativeTarget; | ||
+ buildConfigurationList = 826ACEF51BF1B10A00B5FC5D /* Build configuration list for PBXNativeTarget "AppzTests" */; | ||
+ buildPhases = ( | ||
+ 826ACEE41BF1B10A00B5FC5D /* Sources */, | ||
+ 826ACEE51BF1B10A00B5FC5D /* Frameworks */, | ||
+ 826ACEE61BF1B10A00B5FC5D /* Resources */, | ||
+ ); | ||
+ buildRules = ( | ||
+ ); | ||
+ dependencies = ( | ||
+ 826ACEEB1BF1B10A00B5FC5D /* PBXTargetDependency */, | ||
+ ); | ||
+ name = AppzTests; | ||
+ productName = AppzTests; | ||
+ productReference = 826ACEE81BF1B10A00B5FC5D /* AppzTests.xctest */; | ||
+ productType = "com.apple.product-type.bundle.unit-test"; | ||
+ }; | ||
+/* End PBXNativeTarget section */ | ||
+ | ||
+/* Begin PBXProject section */ | ||
+ 826ACED51BF1B10A00B5FC5D /* Project object */ = { | ||
+ isa = PBXProject; | ||
+ attributes = { | ||
+ LastSwiftUpdateCheck = 0710; | ||
+ LastUpgradeCheck = 0710; | ||
+ ORGANIZATIONNAME = kitz; | ||
+ TargetAttributes = { | ||
+ 826ACEDD1BF1B10A00B5FC5D = { | ||
+ CreatedOnToolsVersion = 7.1; | ||
+ }; | ||
+ 826ACEE71BF1B10A00B5FC5D = { | ||
+ CreatedOnToolsVersion = 7.1; | ||
+ }; | ||
+ }; | ||
+ }; | ||
+ buildConfigurationList = 826ACED81BF1B10A00B5FC5D /* Build configuration list for PBXProject "Appz" */; | ||
+ compatibilityVersion = "Xcode 3.2"; | ||
+ developmentRegion = English; | ||
+ hasScannedForEncodings = 0; | ||
+ knownRegions = ( | ||
+ en, | ||
+ ); | ||
+ mainGroup = 826ACED41BF1B10A00B5FC5D; | ||
+ productRefGroup = 826ACEDF1BF1B10A00B5FC5D /* Products */; | ||
+ projectDirPath = ""; | ||
+ projectRoot = ""; | ||
+ targets = ( | ||
+ 826ACEDD1BF1B10A00B5FC5D /* Appz */, | ||
+ 826ACEE71BF1B10A00B5FC5D /* AppzTests */, | ||
+ ); | ||
+ }; | ||
+/* End PBXProject section */ | ||
+ | ||
+/* Begin PBXResourcesBuildPhase section */ | ||
+ 826ACEDC1BF1B10A00B5FC5D /* Resources */ = { | ||
+ isa = PBXResourcesBuildPhase; | ||
+ buildActionMask = 2147483647; | ||
+ files = ( | ||
+ ); | ||
+ runOnlyForDeploymentPostprocessing = 0; | ||
+ }; | ||
+ 826ACEE61BF1B10A00B5FC5D /* Resources */ = { | ||
+ isa = PBXResourcesBuildPhase; | ||
+ buildActionMask = 2147483647; | ||
+ files = ( | ||
+ ); | ||
+ runOnlyForDeploymentPostprocessing = 0; | ||
+ }; | ||
+/* End PBXResourcesBuildPhase section */ | ||
+ | ||
+/* Begin PBXSourcesBuildPhase section */ | ||
+ 826ACED91BF1B10A00B5FC5D /* Sources */ = { | ||
+ isa = PBXSourcesBuildPhase; | ||
+ buildActionMask = 2147483647; | ||
+ files = ( | ||
+ 826ACF1B1BF1BD7F00B5FC5D /* ApplicationAccess.swift in Sources */, | ||
+ 826ACF221BF1BEBF00B5FC5D /* AppStore.swift in Sources */, | ||
+ 826ACF1E1BF1BEB000B5FC5D /* Twitter.swift in Sources */, | ||
+ 826ACF201BF1BEB800B5FC5D /* Settings.swift in Sources */, | ||
+ 826ACF191BF1BD1F00B5FC5D /* AvailableApplications.swift in Sources */, | ||
+ ); | ||
+ runOnlyForDeploymentPostprocessing = 0; | ||
+ }; | ||
+ 826ACEE41BF1B10A00B5FC5D /* Sources */ = { | ||
+ isa = PBXSourcesBuildPhase; | ||
+ buildActionMask = 2147483647; | ||
+ files = ( | ||
+ 826ACEEE1BF1B10A00B5FC5D /* AppzTests.swift in Sources */, | ||
+ ); | ||
+ runOnlyForDeploymentPostprocessing = 0; | ||
+ }; | ||
+/* End PBXSourcesBuildPhase section */ | ||
+ | ||
+/* Begin PBXTargetDependency section */ | ||
+ 826ACEEB1BF1B10A00B5FC5D /* PBXTargetDependency */ = { | ||
+ isa = PBXTargetDependency; | ||
+ target = 826ACEDD1BF1B10A00B5FC5D /* Appz */; | ||
+ targetProxy = 826ACEEA1BF1B10A00B5FC5D /* PBXContainerItemProxy */; | ||
+ }; | ||
+/* End PBXTargetDependency section */ | ||
+ | ||
+/* Begin XCBuildConfiguration section */ | ||
+ 826ACEF01BF1B10A00B5FC5D /* Debug */ = { | ||
+ isa = XCBuildConfiguration; | ||
+ buildSettings = { | ||
+ ALWAYS_SEARCH_USER_PATHS = NO; | ||
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; | ||
+ CLANG_CXX_LIBRARY = "libc++"; | ||
+ CLANG_ENABLE_MODULES = YES; | ||
+ CLANG_ENABLE_OBJC_ARC = YES; | ||
+ CLANG_WARN_BOOL_CONVERSION = YES; | ||
+ CLANG_WARN_CONSTANT_CONVERSION = YES; | ||
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | ||
+ CLANG_WARN_EMPTY_BODY = YES; | ||
+ CLANG_WARN_ENUM_CONVERSION = YES; | ||
+ CLANG_WARN_INT_CONVERSION = YES; | ||
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | ||
+ CLANG_WARN_UNREACHABLE_CODE = YES; | ||
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | ||
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; | ||
+ COPY_PHASE_STRIP = NO; | ||
+ CURRENT_PROJECT_VERSION = 1; | ||
+ DEBUG_INFORMATION_FORMAT = dwarf; | ||
+ ENABLE_STRICT_OBJC_MSGSEND = YES; | ||
+ ENABLE_TESTABILITY = YES; | ||
+ GCC_C_LANGUAGE_STANDARD = gnu99; | ||
+ GCC_DYNAMIC_NO_PIC = NO; | ||
+ GCC_NO_COMMON_BLOCKS = YES; | ||
+ GCC_OPTIMIZATION_LEVEL = 0; | ||
+ GCC_PREPROCESSOR_DEFINITIONS = ( | ||
+ "DEBUG=1", | ||
+ "$(inherited)", | ||
+ ); | ||
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | ||
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | ||
+ GCC_WARN_UNDECLARED_SELECTOR = YES; | ||
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | ||
+ GCC_WARN_UNUSED_FUNCTION = YES; | ||
+ GCC_WARN_UNUSED_VARIABLE = YES; | ||
+ IPHONEOS_DEPLOYMENT_TARGET = 9.1; | ||
+ MTL_ENABLE_DEBUG_INFO = YES; | ||
+ ONLY_ACTIVE_ARCH = YES; | ||
+ SDKROOT = iphoneos; | ||
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone"; | ||
+ TARGETED_DEVICE_FAMILY = "1,2"; | ||
+ VERSIONING_SYSTEM = "apple-generic"; | ||
+ VERSION_INFO_PREFIX = ""; | ||
+ }; | ||
+ name = Debug; | ||
+ }; | ||
+ 826ACEF11BF1B10A00B5FC5D /* Release */ = { | ||
+ isa = XCBuildConfiguration; | ||
+ buildSettings = { | ||
+ ALWAYS_SEARCH_USER_PATHS = NO; | ||
+ CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; | ||
+ CLANG_CXX_LIBRARY = "libc++"; | ||
+ CLANG_ENABLE_MODULES = YES; | ||
+ CLANG_ENABLE_OBJC_ARC = YES; | ||
+ CLANG_WARN_BOOL_CONVERSION = YES; | ||
+ CLANG_WARN_CONSTANT_CONVERSION = YES; | ||
+ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; | ||
+ CLANG_WARN_EMPTY_BODY = YES; | ||
+ CLANG_WARN_ENUM_CONVERSION = YES; | ||
+ CLANG_WARN_INT_CONVERSION = YES; | ||
+ CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; | ||
+ CLANG_WARN_UNREACHABLE_CODE = YES; | ||
+ CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; | ||
+ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; | ||
+ COPY_PHASE_STRIP = NO; | ||
+ CURRENT_PROJECT_VERSION = 1; | ||
+ DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym"; | ||
+ ENABLE_NS_ASSERTIONS = NO; | ||
+ ENABLE_STRICT_OBJC_MSGSEND = YES; | ||
+ GCC_C_LANGUAGE_STANDARD = gnu99; | ||
+ GCC_NO_COMMON_BLOCKS = YES; | ||
+ GCC_WARN_64_TO_32_BIT_CONVERSION = YES; | ||
+ GCC_WARN_ABOUT_RETURN_TYPE = YES_ERROR; | ||
+ GCC_WARN_UNDECLARED_SELECTOR = YES; | ||
+ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; | ||
+ GCC_WARN_UNUSED_FUNCTION = YES; | ||
+ GCC_WARN_UNUSED_VARIABLE = YES; | ||
+ IPHONEOS_DEPLOYMENT_TARGET = 9.1; | ||
+ MTL_ENABLE_DEBUG_INFO = NO; | ||
+ SDKROOT = iphoneos; | ||
+ TARGETED_DEVICE_FAMILY = "1,2"; | ||
+ VALIDATE_PRODUCT = YES; | ||
+ VERSIONING_SYSTEM = "apple-generic"; | ||
+ VERSION_INFO_PREFIX = ""; | ||
+ }; | ||
+ name = Release; | ||
+ }; | ||
+ 826ACEF31BF1B10A00B5FC5D /* Debug */ = { | ||
+ isa = XCBuildConfiguration; | ||
+ buildSettings = { | ||
+ CLANG_ENABLE_MODULES = YES; | ||
+ DEFINES_MODULE = YES; | ||
+ DYLIB_COMPATIBILITY_VERSION = 1; | ||
+ DYLIB_CURRENT_VERSION = 1; | ||
+ DYLIB_INSTALL_NAME_BASE = "@rpath"; | ||
+ INFOPLIST_FILE = Appz/Info.plist; | ||
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; | ||
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; | ||
+ PRODUCT_BUNDLE_IDENTIFIER = io.kitz.Appz; | ||
+ PRODUCT_NAME = "$(TARGET_NAME)"; | ||
+ SKIP_INSTALL = YES; | ||
+ SWIFT_OPTIMIZATION_LEVEL = "-Onone"; | ||
+ }; | ||
+ name = Debug; | ||
+ }; | ||
+ 826ACEF41BF1B10A00B5FC5D /* Release */ = { | ||
+ isa = XCBuildConfiguration; | ||
+ buildSettings = { | ||
+ CLANG_ENABLE_MODULES = YES; | ||
+ DEFINES_MODULE = YES; | ||
+ DYLIB_COMPATIBILITY_VERSION = 1; | ||
+ DYLIB_CURRENT_VERSION = 1; | ||
+ DYLIB_INSTALL_NAME_BASE = "@rpath"; | ||
+ INFOPLIST_FILE = Appz/Info.plist; | ||
+ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; | ||
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; | ||
+ PRODUCT_BUNDLE_IDENTIFIER = io.kitz.Appz; | ||
+ PRODUCT_NAME = "$(TARGET_NAME)"; | ||
+ SKIP_INSTALL = YES; | ||
+ }; | ||
+ name = Release; | ||
+ }; | ||
+ 826ACEF61BF1B10A00B5FC5D /* Debug */ = { | ||
+ isa = XCBuildConfiguration; | ||
+ buildSettings = { | ||
+ INFOPLIST_FILE = AppzTests/Info.plist; | ||
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; | ||
+ PRODUCT_BUNDLE_IDENTIFIER = io.kitz.AppzTests; | ||
+ PRODUCT_NAME = "$(TARGET_NAME)"; | ||
+ }; | ||
+ name = Debug; | ||
+ }; | ||
+ 826ACEF71BF1B10A00B5FC5D /* Release */ = { | ||
+ isa = XCBuildConfiguration; | ||
+ buildSettings = { | ||
+ INFOPLIST_FILE = AppzTests/Info.plist; | ||
+ LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; | ||
+ PRODUCT_BUNDLE_IDENTIFIER = io.kitz.AppzTests; | ||
+ PRODUCT_NAME = "$(TARGET_NAME)"; | ||
+ }; | ||
+ name = Release; | ||
+ }; | ||
+/* End XCBuildConfiguration section */ | ||
+ | ||
+/* Begin XCConfigurationList section */ | ||
+ 826ACED81BF1B10A00B5FC5D /* Build configuration list for PBXProject "Appz" */ = { | ||
+ isa = XCConfigurationList; | ||
+ buildConfigurations = ( | ||
+ 826ACEF01BF1B10A00B5FC5D /* Debug */, | ||
+ 826ACEF11BF1B10A00B5FC5D /* Release */, | ||
+ ); | ||
+ defaultConfigurationIsVisible = 0; | ||
+ defaultConfigurationName = Release; | ||
+ }; | ||
+ 826ACEF21BF1B10A00B5FC5D /* Build configuration list for PBXNativeTarget "Appz" */ = { | ||
+ isa = XCConfigurationList; | ||
+ buildConfigurations = ( | ||
+ 826ACEF31BF1B10A00B5FC5D /* Debug */, | ||
+ 826ACEF41BF1B10A00B5FC5D /* Release */, | ||
+ ); | ||
+ defaultConfigurationIsVisible = 0; | ||
+ }; | ||
+ 826ACEF51BF1B10A00B5FC5D /* Build configuration list for PBXNativeTarget "AppzTests" */ = { | ||
+ isa = XCConfigurationList; | ||
+ buildConfigurations = ( | ||
+ 826ACEF61BF1B10A00B5FC5D /* Debug */, | ||
+ 826ACEF71BF1B10A00B5FC5D /* Release */, | ||
+ ); | ||
+ defaultConfigurationIsVisible = 0; | ||
+ }; | ||
+/* End XCConfigurationList section */ | ||
+ }; | ||
+ rootObject = 826ACED51BF1B10A00B5FC5D /* Project object */; | ||
+} |
4
Playground/Playground.playground/contents.xcplayground
@@ -0,0 +1,4 @@ | ||
+<?xml version="1.0" encoding="UTF-8" standalone="yes"?> | ||
+<playground version='5.0' target-platform='ios' display-mode='raw'> | ||
+ <timeline fileName='timeline.xctimeline'/> | ||
+</playground> |
7
Playground/Playground.playground/playground.xcworkspace/contents.xcworkspacedata
@@ -0,0 +1,7 @@ | ||
+<?xml version="1.0" encoding="UTF-8"?> | ||
+<Workspace | ||
+ version = "1.0"> | ||
+ <FileRef | ||
+ location = "self:"> | ||
+ </FileRef> | ||
+</Workspace> |
6
Playground/Playground.playground/timeline.xctimeline
@@ -0,0 +1,6 @@ | ||
+<?xml version="1.0" encoding="UTF-8"?> | ||
+<Timeline | ||
+ version = "3.0"> | ||
+ <TimelineItems> | ||
+ </TimelineItems> | ||
+</Timeline> |
@@ -0,0 +1,84 @@ | ||
+ | ||
+# Appz | ||
+ | ||
+![Version](https://img.shields.io/badge/version-prerelease-orange.svg) | ||
+[![Travis CI](https://travis-ci.org/SwiftKitz/Appz.svg?branch=master)](https://travis-ci.org/SwiftKitz/Appz) | ||
+![Swift](https://img.shields.io/badge/swift-2.1-blue.svg) | ||
+![Platforms](https://img.shields.io/badge/platform-ios-lightgrey.svg) | ||
+ | ||
+Deeplinking to external applications made easy! | ||
+ | ||
+_Even though I shipped it with my app, I still need to invest the time to set this up, and finalize the API. Contributors welcome!_ | ||
+ | ||
+## Highlights | ||
+ | ||
++ __Cleanly Separates App Specs:__<br /> | ||
+It was crucial to make sure the library can scale as the number of supported apps increase. Therefor, each supported app is implemented in isolation in a separate file. | ||
+ | ||
++ __Full Autocomplete Support__: | ||
+The API has been carefully designed to make the most out of auto complete features, so you don't have to even peak into any docs nor the code! | ||
+ | ||
++ __Full Testing:__<br /> | ||
+To make the specs as transparent as possible, the library has tests to make sure every external application action has tests with the expected results. | ||
+ | ||
+## Features | ||
+ | ||
+You can try them in the playground shipped with the framework! | ||
+ | ||
+__Concise syntax to trigger deep linking:__ | ||
+ | ||
+```swift | ||
+let app = UIApplication.sharedApplication() | ||
+app.open.appStore(.Account(id: "395107918")) | ||
+app.open.twitter(.UserHandle("mazyod")) | ||
+app.open.appSettings(.Open) | ||
+``` | ||
+ | ||
+__Add your own application:__ | ||
+ | ||
+```swift | ||
+extension AvailableApplications { | ||
+ | ||
+ struct MyApp: ExternalApplication { | ||
+ | ||
+ let scheme = "myapp:" | ||
+ let fallbackURL: String? = nil | ||
+ } | ||
+ | ||
+ func myApp(action: MyApp.Action) -> Bool { | ||
+ return appCaller.launch(MyApp(), action: action) | ||
+ } | ||
+} | ||
+ | ||
+extension AvailableApplications.MyApp { | ||
+ | ||
+ enum Action: ExternalApplicationAction { | ||
+ | ||
+ case Open | ||
+ } | ||
+} | ||
+ | ||
+app.open.myApp(.Open) | ||
+``` | ||
+ | ||
+__Supported Apps (for now!):__ | ||
+ | ||
+App | Actions | ||
+----|-------- | ||
+AppStore | Developer, App | ||
+AppSettings | Open | ||
+Twitter | Status, UserHandle, UserId, List, Post, Search, Timeline, Mentions, Messages | ||
+ | ||
+## Motivation | ||
+ | ||
+I've gone through way too much pain than I am willing to admit integrating deeplinking in my app. It is very easy to forget calling `canOpenURL` or missing a colon somewhere. Another pain point was savaging the web for all the different specs for different applications. | ||
+ | ||
+With this library, you can keep the external application deep linking spec separately and rest assured as it is open source and maintained by the wonderful github community! | ||
+ | ||
+## Author | ||
+ | ||
+Mazyod ([@Mazyod](http://twitter.com/mazyod)) | ||
+ | ||
+## License | ||
+ | ||
+Appz is released under the MIT license. See LICENSE for details. |
0 comments on commit
c1d9904