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 | ||
| + | ||
| + | ||
| +[](https://travis-ci.org/SwiftKitz/Appz) | ||
| + | ||
| + | ||
| + | ||
| +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