├── .gitignore ├── Example.xcodeproj ├── project.pbxproj └── project.xcworkspace │ └── contents.xcworkspacedata ├── Example ├── 782-compass.png ├── Example-Info.plist ├── Images.xcassets │ ├── AppIcon.appiconset │ │ └── Contents.json │ └── LaunchImage.launchimage │ │ └── Contents.json ├── KMAppDelegate.h ├── KMAppDelegate.m ├── KMMasterViewController.h ├── KMMasterViewController.m ├── KMWebViewController.h ├── KMWebViewController.m ├── LaunchScreen-iPad.storyboard ├── LaunchScreen-iPhone.storyboard ├── en.lproj │ └── InfoPlist.strings └── main.m ├── LICENSE.txt ├── PBSafariActivity ├── 782-compass.png ├── 782-compass@2x.png ├── PBSafariActivity.h └── PBSafariActivity.m ├── PBWebViewController.podspec ├── PBWebViewController ├── PBWebViewController.h └── PBWebViewController.m └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | # Created by http://www.gitignore.io 2 | 3 | ### Objective-C ### 4 | # Xcode 5 | # 6 | build/ 7 | *.pbxuser 8 | !default.pbxuser 9 | *.mode1v3 10 | !default.mode1v3 11 | *.mode2v3 12 | !default.mode2v3 13 | *.perspectivev3 14 | !default.perspectivev3 15 | xcuserdata 16 | *.xccheckout 17 | *.moved-aside 18 | DerivedData 19 | *.hmap 20 | *.ipa 21 | *.xcuserstate 22 | 23 | ### OSX ### 24 | .DS_Store 25 | .AppleDouble 26 | .LSOverride 27 | 28 | # Icon must end with two \r 29 | Icon 30 | 31 | 32 | # Thumbnails 33 | ._* 34 | 35 | # Files that might appear on external disk 36 | .Spotlight-V100 37 | .Trashes 38 | 39 | # Directories potentially created on remote AFP share 40 | .AppleDB 41 | .AppleDesktop 42 | Network Trash Folder 43 | Temporary Items 44 | .apdisk 45 | -------------------------------------------------------------------------------- /Example.xcodeproj/project.pbxproj: -------------------------------------------------------------------------------- 1 | // !$*UTF8*$! 2 | { 3 | archiveVersion = 1; 4 | classes = { 5 | }; 6 | objectVersion = 46; 7 | objects = { 8 | 9 | /* Begin PBXBuildFile section */ 10 | 18034E4817345E9700439096 /* PBSafariActivity.m in Sources */ = {isa = PBXBuildFile; fileRef = 18034E4717345E9700439096 /* PBSafariActivity.m */; }; 11 | 18510C7C1733EA6100F0206C /* PBWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 18510C7B1733EA6100F0206C /* PBWebViewController.m */; }; 12 | 1882DF8F1733D8CD0030D3E2 /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1882DF8E1733D8CC0030D3E2 /* UIKit.framework */; }; 13 | 1882DF911733D8CD0030D3E2 /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1882DF901733D8CD0030D3E2 /* Foundation.framework */; }; 14 | 1882DF931733D8CD0030D3E2 /* CoreGraphics.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1882DF921733D8CD0030D3E2 /* CoreGraphics.framework */; }; 15 | 1882DF991733D8CD0030D3E2 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 1882DF971733D8CD0030D3E2 /* InfoPlist.strings */; }; 16 | 1882DF9B1733D8CD0030D3E2 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 1882DF9A1733D8CD0030D3E2 /* main.m */; }; 17 | 1882DF9F1733D8CD0030D3E2 /* KMAppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 1882DF9E1733D8CD0030D3E2 /* KMAppDelegate.m */; }; 18 | 1882DFA81733D8CD0030D3E2 /* KMMasterViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1882DFA71733D8CD0030D3E2 /* KMMasterViewController.m */; }; 19 | 1882DFAB1733D8CD0030D3E2 /* KMWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 1882DFAA1733D8CD0030D3E2 /* KMWebViewController.m */; }; 20 | 1D91900E1C65C550001357F4 /* LaunchScreen-iPhone.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1D91900D1C65C550001357F4 /* LaunchScreen-iPhone.storyboard */; }; 21 | 1D9190101C65CCDE001357F4 /* LaunchScreen-iPad.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 1D91900F1C65CCDE001357F4 /* LaunchScreen-iPad.storyboard */; }; 22 | 6401361418198A4B0041A84C /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 6401361318198A4B0041A84C /* Images.xcassets */; }; 23 | 6436E18D19139A3E009673B0 /* 782-compass@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 6436E18C19139A3E009673B0 /* 782-compass@2x.png */; }; 24 | 6436E18F19139A8B009673B0 /* 782-compass.png in Resources */ = {isa = PBXBuildFile; fileRef = 6436E18E19139A8B009673B0 /* 782-compass.png */; }; 25 | /* End PBXBuildFile section */ 26 | 27 | /* Begin PBXFileReference section */ 28 | 18034E4617345E9700439096 /* PBSafariActivity.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PBSafariActivity.h; path = ../PBSafariActivity/PBSafariActivity.h; sourceTree = ""; }; 29 | 18034E4717345E9700439096 /* PBSafariActivity.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PBSafariActivity.m; path = ../PBSafariActivity/PBSafariActivity.m; sourceTree = ""; }; 30 | 18510C7A1733EA6100F0206C /* PBWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = PBWebViewController.h; path = ../PBWebViewController/PBWebViewController.h; sourceTree = ""; }; 31 | 18510C7B1733EA6100F0206C /* PBWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = PBWebViewController.m; path = ../PBWebViewController/PBWebViewController.m; sourceTree = ""; }; 32 | 1882DF8B1733D8CC0030D3E2 /* Example.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = Example.app; sourceTree = BUILT_PRODUCTS_DIR; }; 33 | 1882DF8E1733D8CC0030D3E2 /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 34 | 1882DF901733D8CD0030D3E2 /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; 35 | 1882DF921733D8CD0030D3E2 /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; }; 36 | 1882DF961733D8CD0030D3E2 /* Example-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = "Example-Info.plist"; sourceTree = ""; }; 37 | 1882DF981733D8CD0030D3E2 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = en.lproj/InfoPlist.strings; sourceTree = ""; }; 38 | 1882DF9A1733D8CD0030D3E2 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 39 | 1882DF9D1733D8CD0030D3E2 /* KMAppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KMAppDelegate.h; sourceTree = ""; }; 40 | 1882DF9E1733D8CD0030D3E2 /* KMAppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KMAppDelegate.m; sourceTree = ""; }; 41 | 1882DFA61733D8CD0030D3E2 /* KMMasterViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KMMasterViewController.h; sourceTree = ""; }; 42 | 1882DFA71733D8CD0030D3E2 /* KMMasterViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KMMasterViewController.m; sourceTree = ""; }; 43 | 1882DFA91733D8CD0030D3E2 /* KMWebViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = KMWebViewController.h; sourceTree = ""; }; 44 | 1882DFAA1733D8CD0030D3E2 /* KMWebViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = KMWebViewController.m; sourceTree = ""; }; 45 | 1D91900D1C65C550001357F4 /* LaunchScreen-iPhone.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "LaunchScreen-iPhone.storyboard"; sourceTree = ""; }; 46 | 1D91900F1C65CCDE001357F4 /* LaunchScreen-iPad.storyboard */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.storyboard; path = "LaunchScreen-iPad.storyboard"; sourceTree = ""; }; 47 | 6401361318198A4B0041A84C /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 48 | 6436E18C19139A3E009673B0 /* 782-compass@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = "782-compass@2x.png"; path = "PBSafariActivity/782-compass@2x.png"; sourceTree = SOURCE_ROOT; }; 49 | 6436E18E19139A8B009673B0 /* 782-compass.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "782-compass.png"; sourceTree = ""; }; 50 | /* End PBXFileReference section */ 51 | 52 | /* Begin PBXFrameworksBuildPhase section */ 53 | 1882DF881733D8CC0030D3E2 /* Frameworks */ = { 54 | isa = PBXFrameworksBuildPhase; 55 | buildActionMask = 2147483647; 56 | files = ( 57 | 1882DF8F1733D8CD0030D3E2 /* UIKit.framework in Frameworks */, 58 | 1882DF911733D8CD0030D3E2 /* Foundation.framework in Frameworks */, 59 | 1882DF931733D8CD0030D3E2 /* CoreGraphics.framework in Frameworks */, 60 | ); 61 | runOnlyForDeploymentPostprocessing = 0; 62 | }; 63 | /* End PBXFrameworksBuildPhase section */ 64 | 65 | /* Begin PBXGroup section */ 66 | 1882DF821733D8CC0030D3E2 = { 67 | isa = PBXGroup; 68 | children = ( 69 | 1882DF941733D8CD0030D3E2 /* Example */, 70 | 1882DF8D1733D8CC0030D3E2 /* Frameworks */, 71 | 1882DF8C1733D8CC0030D3E2 /* Products */, 72 | ); 73 | sourceTree = ""; 74 | }; 75 | 1882DF8C1733D8CC0030D3E2 /* Products */ = { 76 | isa = PBXGroup; 77 | children = ( 78 | 1882DF8B1733D8CC0030D3E2 /* Example.app */, 79 | ); 80 | name = Products; 81 | sourceTree = ""; 82 | }; 83 | 1882DF8D1733D8CC0030D3E2 /* Frameworks */ = { 84 | isa = PBXGroup; 85 | children = ( 86 | 1882DF8E1733D8CC0030D3E2 /* UIKit.framework */, 87 | 1882DF901733D8CD0030D3E2 /* Foundation.framework */, 88 | 1882DF921733D8CD0030D3E2 /* CoreGraphics.framework */, 89 | ); 90 | name = Frameworks; 91 | sourceTree = ""; 92 | }; 93 | 1882DF941733D8CD0030D3E2 /* Example */ = { 94 | isa = PBXGroup; 95 | children = ( 96 | 6404E5861913A27700221937 /* Classes */, 97 | 1891119F17350B780089B197 /* PBWebViewController */, 98 | 189111A017350BB60089B197 /* PBSafariActivity */, 99 | 6401361318198A4B0041A84C /* Images.xcassets */, 100 | 1882DF951733D8CD0030D3E2 /* Supporting Files */, 101 | ); 102 | path = Example; 103 | sourceTree = ""; 104 | }; 105 | 1882DF951733D8CD0030D3E2 /* Supporting Files */ = { 106 | isa = PBXGroup; 107 | children = ( 108 | 1882DF961733D8CD0030D3E2 /* Example-Info.plist */, 109 | 1882DF971733D8CD0030D3E2 /* InfoPlist.strings */, 110 | 1882DF9A1733D8CD0030D3E2 /* main.m */, 111 | 1D91900D1C65C550001357F4 /* LaunchScreen-iPhone.storyboard */, 112 | 1D91900F1C65CCDE001357F4 /* LaunchScreen-iPad.storyboard */, 113 | ); 114 | name = "Supporting Files"; 115 | sourceTree = ""; 116 | }; 117 | 1891119F17350B780089B197 /* PBWebViewController */ = { 118 | isa = PBXGroup; 119 | children = ( 120 | 18510C7A1733EA6100F0206C /* PBWebViewController.h */, 121 | 18510C7B1733EA6100F0206C /* PBWebViewController.m */, 122 | ); 123 | name = PBWebViewController; 124 | sourceTree = ""; 125 | }; 126 | 189111A017350BB60089B197 /* PBSafariActivity */ = { 127 | isa = PBXGroup; 128 | children = ( 129 | 18034E4617345E9700439096 /* PBSafariActivity.h */, 130 | 18034E4717345E9700439096 /* PBSafariActivity.m */, 131 | 6436E18E19139A8B009673B0 /* 782-compass.png */, 132 | 6436E18C19139A3E009673B0 /* 782-compass@2x.png */, 133 | ); 134 | name = PBSafariActivity; 135 | sourceTree = ""; 136 | }; 137 | 6404E5861913A27700221937 /* Classes */ = { 138 | isa = PBXGroup; 139 | children = ( 140 | 1882DF9D1733D8CD0030D3E2 /* KMAppDelegate.h */, 141 | 1882DF9E1733D8CD0030D3E2 /* KMAppDelegate.m */, 142 | 1882DFA61733D8CD0030D3E2 /* KMMasterViewController.h */, 143 | 1882DFA71733D8CD0030D3E2 /* KMMasterViewController.m */, 144 | 1882DFA91733D8CD0030D3E2 /* KMWebViewController.h */, 145 | 1882DFAA1733D8CD0030D3E2 /* KMWebViewController.m */, 146 | ); 147 | name = Classes; 148 | sourceTree = ""; 149 | }; 150 | /* End PBXGroup section */ 151 | 152 | /* Begin PBXNativeTarget section */ 153 | 1882DF8A1733D8CC0030D3E2 /* Example */ = { 154 | isa = PBXNativeTarget; 155 | buildConfigurationList = 1882DFBA1733D8CD0030D3E2 /* Build configuration list for PBXNativeTarget "Example" */; 156 | buildPhases = ( 157 | 1882DF871733D8CC0030D3E2 /* Sources */, 158 | 1882DF881733D8CC0030D3E2 /* Frameworks */, 159 | 1882DF891733D8CC0030D3E2 /* Resources */, 160 | ); 161 | buildRules = ( 162 | ); 163 | dependencies = ( 164 | ); 165 | name = Example; 166 | productName = Example; 167 | productReference = 1882DF8B1733D8CC0030D3E2 /* Example.app */; 168 | productType = "com.apple.product-type.application"; 169 | }; 170 | /* End PBXNativeTarget section */ 171 | 172 | /* Begin PBXProject section */ 173 | 1882DF831733D8CC0030D3E2 /* Project object */ = { 174 | isa = PBXProject; 175 | attributes = { 176 | CLASSPREFIX = KM; 177 | LastUpgradeCheck = 0720; 178 | ORGANIZATIONNAME = "Mikael Konutgan"; 179 | }; 180 | buildConfigurationList = 1882DF861733D8CC0030D3E2 /* Build configuration list for PBXProject "Example" */; 181 | compatibilityVersion = "Xcode 3.2"; 182 | developmentRegion = English; 183 | hasScannedForEncodings = 0; 184 | knownRegions = ( 185 | en, 186 | ); 187 | mainGroup = 1882DF821733D8CC0030D3E2; 188 | productRefGroup = 1882DF8C1733D8CC0030D3E2 /* Products */; 189 | projectDirPath = ""; 190 | projectRoot = ""; 191 | targets = ( 192 | 1882DF8A1733D8CC0030D3E2 /* Example */, 193 | ); 194 | }; 195 | /* End PBXProject section */ 196 | 197 | /* Begin PBXResourcesBuildPhase section */ 198 | 1882DF891733D8CC0030D3E2 /* Resources */ = { 199 | isa = PBXResourcesBuildPhase; 200 | buildActionMask = 2147483647; 201 | files = ( 202 | 1D91900E1C65C550001357F4 /* LaunchScreen-iPhone.storyboard in Resources */, 203 | 6401361418198A4B0041A84C /* Images.xcassets in Resources */, 204 | 1D9190101C65CCDE001357F4 /* LaunchScreen-iPad.storyboard in Resources */, 205 | 1882DF991733D8CD0030D3E2 /* InfoPlist.strings in Resources */, 206 | 6436E18F19139A8B009673B0 /* 782-compass.png in Resources */, 207 | 6436E18D19139A3E009673B0 /* 782-compass@2x.png in Resources */, 208 | ); 209 | runOnlyForDeploymentPostprocessing = 0; 210 | }; 211 | /* End PBXResourcesBuildPhase section */ 212 | 213 | /* Begin PBXSourcesBuildPhase section */ 214 | 1882DF871733D8CC0030D3E2 /* Sources */ = { 215 | isa = PBXSourcesBuildPhase; 216 | buildActionMask = 2147483647; 217 | files = ( 218 | 1882DF9B1733D8CD0030D3E2 /* main.m in Sources */, 219 | 1882DF9F1733D8CD0030D3E2 /* KMAppDelegate.m in Sources */, 220 | 1882DFA81733D8CD0030D3E2 /* KMMasterViewController.m in Sources */, 221 | 1882DFAB1733D8CD0030D3E2 /* KMWebViewController.m in Sources */, 222 | 18510C7C1733EA6100F0206C /* PBWebViewController.m in Sources */, 223 | 18034E4817345E9700439096 /* PBSafariActivity.m in Sources */, 224 | ); 225 | runOnlyForDeploymentPostprocessing = 0; 226 | }; 227 | /* End PBXSourcesBuildPhase section */ 228 | 229 | /* Begin PBXVariantGroup section */ 230 | 1882DF971733D8CD0030D3E2 /* InfoPlist.strings */ = { 231 | isa = PBXVariantGroup; 232 | children = ( 233 | 1882DF981733D8CD0030D3E2 /* en */, 234 | ); 235 | name = InfoPlist.strings; 236 | sourceTree = ""; 237 | }; 238 | /* End PBXVariantGroup section */ 239 | 240 | /* Begin XCBuildConfiguration section */ 241 | 1882DFB81733D8CD0030D3E2 /* Debug */ = { 242 | isa = XCBuildConfiguration; 243 | buildSettings = { 244 | ALWAYS_SEARCH_USER_PATHS = NO; 245 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 246 | CLANG_CXX_LIBRARY = "libc++"; 247 | CLANG_ENABLE_MODULES = YES; 248 | CLANG_ENABLE_OBJC_ARC = YES; 249 | CLANG_WARN_CONSTANT_CONVERSION = YES; 250 | CLANG_WARN_EMPTY_BODY = YES; 251 | CLANG_WARN_ENUM_CONVERSION = YES; 252 | CLANG_WARN_INT_CONVERSION = YES; 253 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 254 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 255 | COPY_PHASE_STRIP = NO; 256 | ENABLE_TESTABILITY = YES; 257 | GCC_C_LANGUAGE_STANDARD = gnu99; 258 | GCC_DYNAMIC_NO_PIC = NO; 259 | GCC_OPTIMIZATION_LEVEL = 0; 260 | GCC_PREPROCESSOR_DEFINITIONS = ( 261 | "DEBUG=1", 262 | "$(inherited)", 263 | ); 264 | GCC_SYMBOLS_PRIVATE_EXTERN = NO; 265 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 266 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 267 | GCC_WARN_UNUSED_VARIABLE = YES; 268 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 269 | ONLY_ACTIVE_ARCH = YES; 270 | SDKROOT = iphoneos; 271 | TARGETED_DEVICE_FAMILY = "1,2"; 272 | }; 273 | name = Debug; 274 | }; 275 | 1882DFB91733D8CD0030D3E2 /* Release */ = { 276 | isa = XCBuildConfiguration; 277 | buildSettings = { 278 | ALWAYS_SEARCH_USER_PATHS = NO; 279 | CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; 280 | CLANG_CXX_LIBRARY = "libc++"; 281 | CLANG_ENABLE_MODULES = YES; 282 | CLANG_ENABLE_OBJC_ARC = YES; 283 | CLANG_WARN_CONSTANT_CONVERSION = YES; 284 | CLANG_WARN_EMPTY_BODY = YES; 285 | CLANG_WARN_ENUM_CONVERSION = YES; 286 | CLANG_WARN_INT_CONVERSION = YES; 287 | CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; 288 | "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; 289 | COPY_PHASE_STRIP = YES; 290 | GCC_C_LANGUAGE_STANDARD = gnu99; 291 | GCC_WARN_ABOUT_RETURN_TYPE = YES; 292 | GCC_WARN_UNINITIALIZED_AUTOS = YES; 293 | GCC_WARN_UNUSED_VARIABLE = YES; 294 | IPHONEOS_DEPLOYMENT_TARGET = 8.4; 295 | OTHER_CFLAGS = "-DNS_BLOCK_ASSERTIONS=1"; 296 | SDKROOT = iphoneos; 297 | TARGETED_DEVICE_FAMILY = "1,2"; 298 | VALIDATE_PRODUCT = YES; 299 | }; 300 | name = Release; 301 | }; 302 | 1882DFBB1733D8CD0030D3E2 /* Debug */ = { 303 | isa = XCBuildConfiguration; 304 | buildSettings = { 305 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 306 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 307 | INFOPLIST_FILE = "Example/Example-Info.plist"; 308 | PRODUCT_BUNDLE_IDENTIFIER = "com.kmikael.${PRODUCT_NAME:rfc1034identifier}"; 309 | PRODUCT_NAME = "$(TARGET_NAME)"; 310 | WRAPPER_EXTENSION = app; 311 | }; 312 | name = Debug; 313 | }; 314 | 1882DFBC1733D8CD0030D3E2 /* Release */ = { 315 | isa = XCBuildConfiguration; 316 | buildSettings = { 317 | ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; 318 | ASSETCATALOG_COMPILER_LAUNCHIMAGE_NAME = LaunchImage; 319 | INFOPLIST_FILE = "Example/Example-Info.plist"; 320 | PRODUCT_BUNDLE_IDENTIFIER = "com.kmikael.${PRODUCT_NAME:rfc1034identifier}"; 321 | PRODUCT_NAME = "$(TARGET_NAME)"; 322 | WRAPPER_EXTENSION = app; 323 | }; 324 | name = Release; 325 | }; 326 | /* End XCBuildConfiguration section */ 327 | 328 | /* Begin XCConfigurationList section */ 329 | 1882DF861733D8CC0030D3E2 /* Build configuration list for PBXProject "Example" */ = { 330 | isa = XCConfigurationList; 331 | buildConfigurations = ( 332 | 1882DFB81733D8CD0030D3E2 /* Debug */, 333 | 1882DFB91733D8CD0030D3E2 /* Release */, 334 | ); 335 | defaultConfigurationIsVisible = 0; 336 | defaultConfigurationName = Release; 337 | }; 338 | 1882DFBA1733D8CD0030D3E2 /* Build configuration list for PBXNativeTarget "Example" */ = { 339 | isa = XCConfigurationList; 340 | buildConfigurations = ( 341 | 1882DFBB1733D8CD0030D3E2 /* Debug */, 342 | 1882DFBC1733D8CD0030D3E2 /* Release */, 343 | ); 344 | defaultConfigurationIsVisible = 0; 345 | defaultConfigurationName = Release; 346 | }; 347 | /* End XCConfigurationList section */ 348 | }; 349 | rootObject = 1882DF831733D8CC0030D3E2 /* Project object */; 350 | } 351 | -------------------------------------------------------------------------------- /Example.xcodeproj/project.xcworkspace/contents.xcworkspacedata: -------------------------------------------------------------------------------- 1 | 2 | 4 | 6 | 7 | 8 | -------------------------------------------------------------------------------- /Example/782-compass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmikael/PBWebViewController/7f056c24b9ec03cc6a5aaef5044512d655a17876/Example/782-compass.png -------------------------------------------------------------------------------- /Example/Example-Info.plist: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | CFBundleDevelopmentRegion 6 | en 7 | CFBundleDisplayName 8 | ${PRODUCT_NAME} 9 | CFBundleExecutable 10 | ${EXECUTABLE_NAME} 11 | CFBundleIcons 12 | 13 | CFBundleIcons~ipad 14 | 15 | CFBundleIdentifier 16 | $(PRODUCT_BUNDLE_IDENTIFIER) 17 | CFBundleInfoDictionaryVersion 18 | 6.0 19 | CFBundleName 20 | ${PRODUCT_NAME} 21 | CFBundlePackageType 22 | APPL 23 | CFBundleShortVersionString 24 | 1.1 25 | CFBundleSignature 26 | ???? 27 | CFBundleVersion 28 | 2 29 | LSRequiresIPhoneOS 30 | 31 | NSAppTransportSecurity 32 | 33 | NSAllowsArbitraryLoads 34 | 35 | 36 | UILaunchStoryboardName~ipad 37 | LaunchScreen-iPad.storyboard 38 | UILaunchStoryboardName~iphone 39 | LaunchScreen-iPhone.storyboard 40 | UIRequiredDeviceCapabilities 41 | 42 | armv7 43 | 44 | UIStatusBarTintParameters 45 | 46 | UINavigationBar 47 | 48 | Style 49 | UIBarStyleDefault 50 | Translucent 51 | 52 | 53 | 54 | UISupportedInterfaceOrientations 55 | 56 | UIInterfaceOrientationPortrait 57 | UIInterfaceOrientationLandscapeLeft 58 | UIInterfaceOrientationLandscapeRight 59 | 60 | UISupportedInterfaceOrientations~ipad 61 | 62 | UIInterfaceOrientationPortrait 63 | UIInterfaceOrientationPortraitUpsideDown 64 | UIInterfaceOrientationLandscapeLeft 65 | UIInterfaceOrientationLandscapeRight 66 | 67 | 68 | 69 | -------------------------------------------------------------------------------- /Example/Images.xcassets/AppIcon.appiconset/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "idiom" : "iphone", 5 | "size" : "29x29", 6 | "scale" : "1x" 7 | }, 8 | { 9 | "idiom" : "iphone", 10 | "size" : "29x29", 11 | "scale" : "2x" 12 | }, 13 | { 14 | "idiom" : "iphone", 15 | "size" : "29x29", 16 | "scale" : "3x" 17 | }, 18 | { 19 | "idiom" : "iphone", 20 | "size" : "40x40", 21 | "scale" : "2x" 22 | }, 23 | { 24 | "idiom" : "iphone", 25 | "size" : "40x40", 26 | "scale" : "3x" 27 | }, 28 | { 29 | "idiom" : "iphone", 30 | "size" : "57x57", 31 | "scale" : "1x" 32 | }, 33 | { 34 | "idiom" : "iphone", 35 | "size" : "57x57", 36 | "scale" : "2x" 37 | }, 38 | { 39 | "idiom" : "iphone", 40 | "size" : "60x60", 41 | "scale" : "2x" 42 | }, 43 | { 44 | "idiom" : "iphone", 45 | "size" : "60x60", 46 | "scale" : "3x" 47 | }, 48 | { 49 | "idiom" : "ipad", 50 | "size" : "29x29", 51 | "scale" : "1x" 52 | }, 53 | { 54 | "idiom" : "ipad", 55 | "size" : "29x29", 56 | "scale" : "2x" 57 | }, 58 | { 59 | "idiom" : "ipad", 60 | "size" : "40x40", 61 | "scale" : "1x" 62 | }, 63 | { 64 | "idiom" : "ipad", 65 | "size" : "40x40", 66 | "scale" : "2x" 67 | }, 68 | { 69 | "idiom" : "ipad", 70 | "size" : "50x50", 71 | "scale" : "1x" 72 | }, 73 | { 74 | "idiom" : "ipad", 75 | "size" : "50x50", 76 | "scale" : "2x" 77 | }, 78 | { 79 | "idiom" : "ipad", 80 | "size" : "72x72", 81 | "scale" : "1x" 82 | }, 83 | { 84 | "idiom" : "ipad", 85 | "size" : "72x72", 86 | "scale" : "2x" 87 | }, 88 | { 89 | "idiom" : "ipad", 90 | "size" : "76x76", 91 | "scale" : "1x" 92 | }, 93 | { 94 | "idiom" : "ipad", 95 | "size" : "76x76", 96 | "scale" : "2x" 97 | }, 98 | { 99 | "idiom" : "ipad", 100 | "size" : "83.5x83.5", 101 | "scale" : "2x" 102 | } 103 | ], 104 | "info" : { 105 | "version" : 1, 106 | "author" : "xcode" 107 | } 108 | } -------------------------------------------------------------------------------- /Example/Images.xcassets/LaunchImage.launchimage/Contents.json: -------------------------------------------------------------------------------- 1 | { 2 | "images" : [ 3 | { 4 | "orientation" : "portrait", 5 | "idiom" : "ipad", 6 | "extent" : "full-screen", 7 | "minimum-system-version" : "7.0", 8 | "scale" : "1x" 9 | }, 10 | { 11 | "orientation" : "landscape", 12 | "idiom" : "ipad", 13 | "extent" : "full-screen", 14 | "minimum-system-version" : "7.0", 15 | "scale" : "1x" 16 | }, 17 | { 18 | "orientation" : "portrait", 19 | "idiom" : "ipad", 20 | "extent" : "full-screen", 21 | "minimum-system-version" : "7.0", 22 | "scale" : "2x" 23 | }, 24 | { 25 | "orientation" : "landscape", 26 | "idiom" : "ipad", 27 | "extent" : "full-screen", 28 | "minimum-system-version" : "7.0", 29 | "scale" : "2x" 30 | }, 31 | { 32 | "orientation" : "portrait", 33 | "idiom" : "ipad", 34 | "extent" : "to-status-bar", 35 | "scale" : "1x" 36 | }, 37 | { 38 | "orientation" : "landscape", 39 | "idiom" : "ipad", 40 | "extent" : "to-status-bar", 41 | "scale" : "1x" 42 | }, 43 | { 44 | "orientation" : "portrait", 45 | "idiom" : "ipad", 46 | "extent" : "to-status-bar", 47 | "scale" : "2x" 48 | }, 49 | { 50 | "orientation" : "landscape", 51 | "idiom" : "ipad", 52 | "extent" : "to-status-bar", 53 | "scale" : "2x" 54 | } 55 | ], 56 | "info" : { 57 | "version" : 1, 58 | "author" : "xcode" 59 | } 60 | } -------------------------------------------------------------------------------- /Example/KMAppDelegate.h: -------------------------------------------------------------------------------- 1 | // 2 | // KMAppDelegate.h 3 | // Example 4 | // 5 | // Created by Mikael Konutgan on 03/05/2013. 6 | // Copyright (c) 2013 Mikael Konutgan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @interface KMAppDelegate : UIResponder 12 | 13 | @property (strong, nonatomic) UIWindow *window; 14 | 15 | @property (strong, nonatomic) UINavigationController *navigationController; 16 | @property (strong, nonatomic) UISplitViewController *splitViewController; 17 | 18 | @end 19 | -------------------------------------------------------------------------------- /Example/KMAppDelegate.m: -------------------------------------------------------------------------------- 1 | // 2 | // KMAppDelegate.m 3 | // Example 4 | // 5 | // Created by Mikael Konutgan on 03/05/2013. 6 | // Copyright (c) 2013 Mikael Konutgan. All rights reserved. 7 | // 8 | 9 | #import "KMAppDelegate.h" 10 | #import "KMMasterViewController.h" 11 | #import "KMWebViewController.h" 12 | 13 | @implementation KMAppDelegate 14 | 15 | - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 16 | { 17 | NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 18 | diskCapacity:20 * 1024 * 1024 19 | diskPath:nil]; 20 | [NSURLCache setSharedURLCache:URLCache]; 21 | 22 | self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 23 | 24 | KMMasterViewController *masterViewController = [[KMMasterViewController alloc] init]; 25 | if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) { 26 | self.navigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController]; 27 | self.window.rootViewController = self.navigationController; 28 | } else { 29 | UINavigationController *masterNavigationController = [[UINavigationController alloc] initWithRootViewController:masterViewController]; 30 | KMWebViewController *webViewController = [[KMWebViewController alloc] init]; 31 | UINavigationController *webNavigationController = [[UINavigationController alloc] initWithRootViewController:webViewController]; 32 | masterViewController.webViewController = webViewController; 33 | self.splitViewController = [[UISplitViewController alloc] init]; 34 | self.splitViewController.delegate = webViewController; 35 | self.splitViewController.viewControllers = @[masterNavigationController, webNavigationController]; 36 | self.window.rootViewController = self.splitViewController; 37 | } 38 | [self.window makeKeyAndVisible]; 39 | return YES; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Example/KMMasterViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KMMasterViewController.h 3 | // Example 4 | // 5 | // Created by Mikael Konutgan on 03/05/2013. 6 | // Copyright (c) 2013 Mikael Konutgan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | @class PBWebViewController; 12 | 13 | @interface KMMasterViewController : UITableViewController 14 | 15 | @property (strong, nonatomic) PBWebViewController *webViewController; 16 | 17 | @end 18 | -------------------------------------------------------------------------------- /Example/KMMasterViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KMMasterViewController.m 3 | // Example 4 | // 5 | // Created by Mikael Konutgan on 03/05/2013. 6 | // Copyright (c) 2013 Mikael Konutgan. All rights reserved. 7 | // 8 | 9 | #import "KMMasterViewController.h" 10 | #import "PBWebViewController.h" 11 | #import "PBSafariActivity.h" 12 | 13 | @interface KMMasterViewController () 14 | 15 | @property (strong, nonatomic) NSArray *bookmarks; 16 | 17 | @end 18 | 19 | @implementation KMMasterViewController 20 | 21 | - (NSArray *)bookmarks 22 | { 23 | if (!_bookmarks) { 24 | _bookmarks = @[ 25 | @"http://www.apple.com", 26 | @"http://daringfireball.net", 27 | @"http://www.macstories.net", 28 | @"http://www.macdrifter.com", 29 | @"http://brettterpstra.com", 30 | @"http://www.pinbrowser.co", 31 | @"http://kmikael.com", 32 | @"https://twitter.com/mkonutgan", 33 | @"http://nshipster.com/" 34 | ]; 35 | } 36 | 37 | return _bookmarks; 38 | } 39 | 40 | - (void)viewDidLoad 41 | { 42 | [super viewDidLoad]; 43 | self.title = NSLocalizedString(@"Bookmarks", @"Bookmarks"); 44 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad) { 45 | self.clearsSelectionOnViewWillAppear = NO; 46 | } 47 | } 48 | 49 | - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section 50 | { 51 | return [self.bookmarks count]; 52 | } 53 | 54 | - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 55 | { 56 | static NSString *CellIdentifier = @"Cell"; 57 | UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 58 | if (cell == nil) { 59 | cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 60 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { 61 | cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator; 62 | } 63 | } 64 | cell.textLabel.text = self.bookmarks[indexPath.row]; 65 | return cell; 66 | } 67 | 68 | - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath 69 | { 70 | NSString *bookmark = self.bookmarks[indexPath.row]; 71 | 72 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { 73 | self.webViewController = [[PBWebViewController alloc] init]; 74 | } 75 | 76 | PBSafariActivity *activity = [[PBSafariActivity alloc] init]; 77 | 78 | NSURL *URL = [NSURL URLWithString:bookmark]; 79 | 80 | if (indexPath.row != self.bookmarks.count - 1) { 81 | self.webViewController.URL = URL; 82 | } else { 83 | NSURLRequest *URLRequest = [NSURLRequest requestWithURL:URL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:10.0]; 84 | self.webViewController.URLRequest = URLRequest; 85 | } 86 | 87 | self.webViewController.applicationActivities = @[activity]; 88 | self.webViewController.excludedActivityTypes = @[UIActivityTypeMail, UIActivityTypeMessage, UIActivityTypePostToWeibo]; 89 | 90 | if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPhone) { 91 | [self.navigationController pushViewController:self.webViewController animated:YES]; 92 | } else { 93 | [self.webViewController load]; 94 | } 95 | } 96 | 97 | @end 98 | -------------------------------------------------------------------------------- /Example/KMWebViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // KMWebViewController.h 3 | // Example 4 | // 5 | // Created by Mikael Konutgan on 03/05/2013. 6 | // Copyright (c) 2013 Mikael Konutgan. All rights reserved. 7 | // 8 | 9 | #import 10 | #import "PBWebViewController.h" 11 | 12 | @interface KMWebViewController : PBWebViewController 13 | 14 | @end 15 | -------------------------------------------------------------------------------- /Example/KMWebViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // KMWebViewController.m 3 | // Example 4 | // 5 | // Created by Mikael Konutgan on 03/05/2013. 6 | // Copyright (c) 2013 Mikael Konutgan. All rights reserved. 7 | // 8 | 9 | #import "KMWebViewController.h" 10 | 11 | @interface KMWebViewController () 12 | 13 | @property (strong, nonatomic) UIPopoverController *masterPopoverController; 14 | 15 | @end 16 | 17 | @implementation KMWebViewController 18 | 19 | - (void)load 20 | { 21 | [super load]; 22 | if (self.masterPopoverController.isPopoverVisible) { 23 | [self.masterPopoverController dismissPopoverAnimated:YES]; 24 | } 25 | } 26 | 27 | #pragma mark - Split view 28 | 29 | - (void)splitViewController:(UISplitViewController *)splitController willHideViewController:(UIViewController *)viewController withBarButtonItem:(UIBarButtonItem *)barButtonItem forPopoverController:(UIPopoverController *)popoverController 30 | { 31 | barButtonItem.title = NSLocalizedString(@"Bookmarks", @"Bookmarks"); 32 | [self.navigationItem setLeftBarButtonItem:barButtonItem animated:YES]; 33 | self.masterPopoverController = popoverController; 34 | } 35 | 36 | - (void)splitViewController:(UISplitViewController *)splitController willShowViewController:(UIViewController *)viewController invalidatingBarButtonItem:(UIBarButtonItem *)barButtonItem 37 | { 38 | [self.navigationItem setLeftBarButtonItem:nil animated:YES]; 39 | self.masterPopoverController = nil; 40 | } 41 | 42 | @end 43 | -------------------------------------------------------------------------------- /Example/LaunchScreen-iPad.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | -------------------------------------------------------------------------------- /Example/LaunchScreen-iPhone.storyboard: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | 53 | 54 | 55 | -------------------------------------------------------------------------------- /Example/en.lproj/InfoPlist.strings: -------------------------------------------------------------------------------- 1 | /* Localized versions of Info.plist keys */ 2 | 3 | -------------------------------------------------------------------------------- /Example/main.m: -------------------------------------------------------------------------------- 1 | // 2 | // main.m 3 | // Example 4 | // 5 | // Created by Mikael Konutgan on 03/05/2013. 6 | // Copyright (c) 2013 Mikael Konutgan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | #import "KMAppDelegate.h" 12 | 13 | int main(int argc, char *argv[]) 14 | { 15 | @autoreleasepool { 16 | return UIApplicationMain(argc, argv, nil, NSStringFromClass([KMAppDelegate class])); 17 | } 18 | } 19 | -------------------------------------------------------------------------------- /LICENSE.txt: -------------------------------------------------------------------------------- 1 | Copyright (c) 2014 Mikael Konutgan 2 | 3 | MIT License 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining 6 | a copy of this software and associated documentation files (the 7 | "Software"), to deal in the Software without restriction, including 8 | without limitation the rights to use, copy, modify, merge, publish, 9 | distribute, sublicense, and/or sell copies of the Software, and to 10 | permit persons to whom the Software is furnished to do so, subject to 11 | the following conditions: 12 | 13 | The above copyright notice and this permission notice shall be 14 | included in all copies or substantial portions of the Software. 15 | 16 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 | MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 | LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 | OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 | WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /PBSafariActivity/782-compass.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmikael/PBWebViewController/7f056c24b9ec03cc6a5aaef5044512d655a17876/PBSafariActivity/782-compass.png -------------------------------------------------------------------------------- /PBSafariActivity/782-compass@2x.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/kmikael/PBWebViewController/7f056c24b9ec03cc6a5aaef5044512d655a17876/PBSafariActivity/782-compass@2x.png -------------------------------------------------------------------------------- /PBSafariActivity/PBSafariActivity.h: -------------------------------------------------------------------------------- 1 | // 2 | // PBSafariActivity.h 3 | // Pinbrowser 4 | // 5 | // Created by Mikael Konutgan on 12/02/2013. 6 | // Copyright (c) 2013 Mikael Konutgan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | /* 12 | * A `UIActivity` subclass to be used with a `UIActivityViewController` that opens a URL in Safari. 13 | */ 14 | @interface PBSafariActivity : UIActivity 15 | 16 | @end 17 | -------------------------------------------------------------------------------- /PBSafariActivity/PBSafariActivity.m: -------------------------------------------------------------------------------- 1 | // 2 | // PBSafariActivity.m 3 | // Pinbrowser 4 | // 5 | // Created by Mikael Konutgan on 12/02/2013. 6 | // Copyright (c) 2013 Mikael Konutgan. All rights reserved. 7 | // 8 | 9 | #import "PBSafariActivity.h" 10 | 11 | @interface PBSafariActivity () 12 | 13 | @property (strong, nonatomic) NSURL *URL; 14 | 15 | @end 16 | 17 | @implementation PBSafariActivity 18 | 19 | - (NSString *)activityType 20 | { 21 | return NSStringFromClass([self class]); 22 | } 23 | 24 | - (NSString *)activityTitle 25 | { 26 | return NSLocalizedString(@"Open in Safari", @"Open the URL in Safari."); 27 | } 28 | 29 | - (UIImage *)activityImage 30 | { 31 | return [UIImage imageNamed:@"782-compass"]; 32 | } 33 | 34 | - (BOOL)canPerformWithActivityItems:(NSArray *)activityItems 35 | { 36 | for (id activityItem in activityItems) { 37 | if ([activityItem isKindOfClass:[NSURL class]] && [[UIApplication sharedApplication] canOpenURL:activityItem]) { 38 | return YES; 39 | } 40 | } 41 | 42 | return NO; 43 | } 44 | 45 | - (void)prepareWithActivityItems:(NSArray *)activityItems 46 | { 47 | for (id activityItem in activityItems) { 48 | if ([activityItem isKindOfClass:[NSURL class]] && [[UIApplication sharedApplication] canOpenURL:activityItem]) { 49 | self.URL = activityItem; 50 | 51 | return; 52 | } 53 | } 54 | } 55 | 56 | - (void)performActivity 57 | { 58 | [[UIApplication sharedApplication] openURL:self.URL]; 59 | 60 | [self activityDidFinish:YES]; 61 | } 62 | 63 | @end 64 | -------------------------------------------------------------------------------- /PBWebViewController.podspec: -------------------------------------------------------------------------------- 1 | Pod::Spec.new do |s| 2 | s.name = 'PBWebViewController' 3 | s.version = '0.5.0' 4 | s.summary = 'A light-weight, simple and extendible web browser component for iOS.' 5 | s.homepage = 'https://github.com/kmikael/PBWebViewController' 6 | s.license = {:type => 'MIT', :file => 'LICENSE.txt'} 7 | s.author = {'Mikael Konutgan' => "me@kmikael.com"} 8 | s.source = {:git => 'https://github.com/kmikael/PBWebViewController.git', :tag => '0.5.0'} 9 | s.platform = :ios, '8.0' 10 | s.source_files = 'PBWebViewController/' 11 | s.requires_arc = true 12 | end 13 | -------------------------------------------------------------------------------- /PBWebViewController/PBWebViewController.h: -------------------------------------------------------------------------------- 1 | // 2 | // PBWebViewController.h 3 | // Pinbrowser 4 | // 5 | // Created by Mikael Konutgan on 11/02/2013. 6 | // Copyright (c) 2013 Mikael Konutgan. All rights reserved. 7 | // 8 | 9 | #import 10 | 11 | NS_ASSUME_NONNULL_BEGIN 12 | 13 | /** 14 | * The `PBWebViewController` class is a view controller that displays the contents of a URL 15 | * along tith a navigation toolbar with buttons to stop/refresh the loading of the page 16 | * as well as buttons to go back, forward and to share the URL using a `UIActivityViewController`. 17 | */ 18 | @interface PBWebViewController : UIViewController 19 | 20 | /** 21 | * The URL that will be loaded by the web view controller. 22 | * If there is one present when the web view appears, it will be automatically loaded, by calling `load`, 23 | * Otherwise, you can set a `URL` after the web view has already been loaded and then manually call `load`. 24 | * Automatically creates a NSURLRequest for you. 25 | */ 26 | @property (strong, nonatomic, nullable) NSURL *URL; 27 | 28 | /** 29 | * The URL request that will be loaded by the web view controller. 30 | * If there is one present when the web view appears, it will be automatically loaded, by calling `load`, 31 | * Otherwise, you can set a `URLRequest` after the web view has already been loaded and then manually call `load`. 32 | * Use this to set your own request with custom headers. 33 | */ 34 | @property (strong, nonatomic, nullable) NSURLRequest *URLRequest; 35 | 36 | /** 37 | * The array of data objects on which to perform the activity. 38 | * `@[self.URL]` is used if nothing is provided. 39 | */ 40 | @property (strong, nonatomic, nullable) NSArray *activityItems; 41 | 42 | /** 43 | * An array of `UIActivity` objects representing the custom services that your application supports. 44 | */ 45 | @property (strong, nonatomic, nullable) NSArray *applicationActivities; 46 | 47 | /** 48 | * The list of services that should not be displayed. 49 | */ 50 | @property (strong, nonatomic, nullable) NSArray *excludedActivityTypes; 51 | 52 | /** 53 | * A Boolean indicating whether the web view controller’s toolbar, 54 | * which displays a stop/refresh, back, forward and share button, is shown. 55 | * The default value of this property is `YES`. 56 | */ 57 | @property (assign, nonatomic) BOOL showsNavigationToolbar; 58 | 59 | /** 60 | * Loads the given `URL`. 61 | * This is called automatically when the when the web view appears if a `URL` exists, 62 | * otehrwise it can be called manually. 63 | */ 64 | - (void)load; 65 | 66 | /** 67 | * Clears the contents of the web view. 68 | */ 69 | - (void)clear; 70 | 71 | @end 72 | 73 | NS_ASSUME_NONNULL_END 74 | -------------------------------------------------------------------------------- /PBWebViewController/PBWebViewController.m: -------------------------------------------------------------------------------- 1 | // 2 | // PBWebViewController.m 3 | // Pinbrowser 4 | // 5 | // Created by Mikael Konutgan on 11/02/2013. 6 | // Copyright (c) 2013 Mikael Konutgan. All rights reserved. 7 | // 8 | 9 | #import "PBWebViewController.h" 10 | 11 | @interface PBWebViewController () 12 | 13 | @property (strong, nonatomic) UIWebView *webView; 14 | 15 | @property (strong, nonatomic) UIBarButtonItem *stopLoadingButton; 16 | @property (strong, nonatomic) UIBarButtonItem *reloadButton; 17 | @property (strong, nonatomic) UIBarButtonItem *backButton; 18 | @property (strong, nonatomic) UIBarButtonItem *forwardButton; 19 | 20 | @property (assign, nonatomic) BOOL toolbarPreviouslyHidden; 21 | 22 | @end 23 | 24 | @implementation PBWebViewController 25 | 26 | - (instancetype)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil 27 | { 28 | self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil]; 29 | if (self) { 30 | [self commonInit]; 31 | } 32 | return self; 33 | } 34 | 35 | - (instancetype)initWithCoder:(NSCoder *)aDecoder 36 | { 37 | self = [super initWithCoder:aDecoder]; 38 | if (self) { 39 | [self commonInit]; 40 | } 41 | return self; 42 | } 43 | 44 | - (void)commonInit 45 | { 46 | _showsNavigationToolbar = YES; 47 | } 48 | 49 | - (void)load 50 | { 51 | [self.webView loadRequest:self.URLRequest]; 52 | 53 | if (self.navigationController.toolbarHidden) { 54 | self.toolbarPreviouslyHidden = YES; 55 | if (self.showsNavigationToolbar) { 56 | [self.navigationController setToolbarHidden:NO animated:YES]; 57 | } 58 | } 59 | } 60 | 61 | - (void)clear 62 | { 63 | [self.webView loadHTMLString:@"" baseURL:nil]; 64 | self.title = @""; 65 | } 66 | 67 | #pragma mark - View controller lifecycle 68 | 69 | - (void)loadView 70 | { 71 | self.webView = [[UIWebView alloc] init]; 72 | self.webView.scalesPageToFit = YES; 73 | self.view = self.webView; 74 | } 75 | 76 | - (void)viewDidLoad 77 | { 78 | [super viewDidLoad]; 79 | [self setupToolBarItems]; 80 | } 81 | 82 | - (void)viewWillAppear:(BOOL)animated 83 | { 84 | [super viewWillAppear:animated]; 85 | self.webView.delegate = self; 86 | if (self.URL) { 87 | [self load]; 88 | } 89 | } 90 | 91 | - (void)viewWillDisappear:(BOOL)animated 92 | { 93 | [super viewWillDisappear:animated]; 94 | [self.webView stopLoading]; 95 | self.webView.delegate = nil; 96 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 97 | 98 | if (self.toolbarPreviouslyHidden && self.showsNavigationToolbar) { 99 | [self.navigationController setToolbarHidden:YES animated:YES]; 100 | } 101 | } 102 | 103 | #pragma mark - URL setter/getter 104 | 105 | - (void)setURL:(NSURL *)URL { 106 | self.URLRequest = [NSURLRequest requestWithURL:URL cachePolicy:NSURLRequestReloadIgnoringLocalCacheData timeoutInterval:60.0]; 107 | } 108 | 109 | - (NSURL *)URL { 110 | return self.URLRequest.URL; 111 | } 112 | 113 | #pragma mark - Helpers 114 | 115 | - (UIImage *)backButtonImage 116 | { 117 | static UIImage *image; 118 | 119 | static dispatch_once_t predicate; 120 | dispatch_once(&predicate, ^{ 121 | CGSize size = CGSizeMake(12.0, 21.0); 122 | UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); 123 | 124 | UIBezierPath *path = [UIBezierPath bezierPath]; 125 | path.lineWidth = 1.5; 126 | path.lineCapStyle = kCGLineCapButt; 127 | path.lineJoinStyle = kCGLineJoinMiter; 128 | [path moveToPoint:CGPointMake(11.0, 1.0)]; 129 | [path addLineToPoint:CGPointMake(1.0, 11.0)]; 130 | [path addLineToPoint:CGPointMake(11.0, 20.0)]; 131 | [path stroke]; 132 | 133 | image = UIGraphicsGetImageFromCurrentImageContext(); 134 | UIGraphicsEndImageContext(); 135 | }); 136 | 137 | return image; 138 | } 139 | 140 | - (UIImage *)forwardButtonImage 141 | { 142 | static UIImage *image; 143 | 144 | static dispatch_once_t predicate; 145 | dispatch_once(&predicate, ^{ 146 | UIImage *backButtonImage = [self backButtonImage]; 147 | 148 | CGSize size = backButtonImage.size; 149 | UIGraphicsBeginImageContextWithOptions(size, NO, 0.0); 150 | 151 | CGContextRef context = UIGraphicsGetCurrentContext(); 152 | 153 | CGFloat midX = size.width / 2.0; 154 | CGFloat midY = size.height / 2.0; 155 | 156 | CGContextTranslateCTM(context, midX, midY); 157 | CGContextRotateCTM(context, M_PI); 158 | 159 | [backButtonImage drawAtPoint:CGPointMake(-midX, -midY)]; 160 | 161 | image = UIGraphicsGetImageFromCurrentImageContext(); 162 | UIGraphicsEndImageContext(); 163 | }); 164 | 165 | return image; 166 | } 167 | 168 | - (void)setupToolBarItems 169 | { 170 | self.stopLoadingButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemStop target:self.webView action:@selector(stopLoading)]; 171 | self.reloadButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self.webView action:@selector(reload)]; 172 | self.backButton = [[UIBarButtonItem alloc] initWithImage:[self backButtonImage] style:UIBarButtonItemStylePlain target:self.webView action:@selector(goBack)]; 173 | self.forwardButton = [[UIBarButtonItem alloc] initWithImage:[self forwardButtonImage] style:UIBarButtonItemStylePlain target:self.webView action:@selector(goForward)]; 174 | 175 | self.backButton.enabled = NO; 176 | self.forwardButton.enabled = NO; 177 | 178 | UIBarButtonItem *actionButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemAction target:self action:@selector(action:)]; 179 | UIBarButtonItem *space = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:nil action:nil]; 180 | UIBarButtonItem *space_ = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFixedSpace target:nil action:nil]; 181 | 182 | space_.width = 60.0; 183 | 184 | self.toolbarItems = @[self.stopLoadingButton, space, self.backButton, space_, self.forwardButton, space, actionButton]; 185 | } 186 | 187 | - (void)toggleState 188 | { 189 | self.backButton.enabled = self.webView.canGoBack; 190 | self.forwardButton.enabled = self.webView.canGoForward; 191 | 192 | NSMutableArray *toolbarItems = [self.toolbarItems mutableCopy]; 193 | 194 | if (self.webView.loading) { 195 | toolbarItems[0] = self.stopLoadingButton; 196 | } else { 197 | toolbarItems[0] = self.reloadButton; 198 | } 199 | 200 | self.toolbarItems = [toolbarItems copy]; 201 | } 202 | 203 | - (void)finishLoad 204 | { 205 | [self toggleState]; 206 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:NO]; 207 | } 208 | 209 | #pragma mark - Button actions 210 | 211 | - (void)action:(id)sender 212 | { 213 | NSArray *activityItems = self.activityItems ? self.activityItems : @[self.URL]; 214 | 215 | UIActivityViewController *activityViewController = [[UIActivityViewController alloc] initWithActivityItems:activityItems applicationActivities:self.applicationActivities]; 216 | 217 | activityViewController.excludedActivityTypes = self.excludedActivityTypes; 218 | 219 | activityViewController.modalPresentationStyle = UIModalPresentationPopover; 220 | activityViewController.popoverPresentationController.barButtonItem = self.toolbarItems.lastObject; 221 | 222 | [self presentViewController:activityViewController animated:YES completion:nil]; 223 | } 224 | 225 | #pragma mark - Web view delegate 226 | 227 | - (void)webViewDidStartLoad:(UIWebView *)webView 228 | { 229 | [[UIApplication sharedApplication] setNetworkActivityIndicatorVisible:YES]; 230 | [self toggleState]; 231 | } 232 | 233 | - (void)webViewDidFinishLoad:(UIWebView *)webView 234 | { 235 | [self finishLoad]; 236 | self.title = [webView stringByEvaluatingJavaScriptFromString:@"document.title"]; 237 | self.URL = self.webView.request.URL; 238 | } 239 | 240 | - (void)webView:(UIWebView *)webView didFailLoadWithError:(NSError *)error 241 | { 242 | [self finishLoad]; 243 | } 244 | 245 | @end 246 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PBWebViewController 2 | 3 | `PBWebViewController` is a light-weight, simple and customizable web browser component for iOS. 4 | It's just 2 source files, image-free, around 300 lines of code and has been built with modern Cocoa development techniques. 5 | 6 | ![PBWebViewController Screenshot](http://f.cl.ly/items/0e3x1u1L133t13230u37/PBWebViewController-Screenshot.jpg) 7 | 8 | ## Installation 9 | 10 | Just drag the `PBWebViewController` folder to your project or add `pod 'PBWebViewController'` to your `Podfile`. 11 | 12 | ## Usage 13 | 14 | `PBWebViewController` works on iPhone and iPad, in all orientations and is meant to be used in a `UINavigationController`. 15 | All you need to do is set up it's properties and then push it. Here's a simple example: 16 | 17 | ```objective-c 18 | // Initialize the web view controller and set it's URL 19 | self.webViewController = [[PBWebViewController alloc] init]; 20 | self.webViewController.URL = [NSURL URLWithString:@"http://www.apple.com"]; 21 | 22 | // These are custom UIActivity subclasses that will show up in the UIActivityViewController 23 | // when the action button is clicked 24 | PBSafariActivity *activity = [[PBSafariActivity alloc] init]; 25 | self.webViewController.applicationActivities = @[activity]; 26 | 27 | // This property also corresponds to the same one on UIActivityViewController 28 | // Both properties do not need to be set unless you want custom actions 29 | self.webViewController.excludedActivityTypes = @[UIActivityTypeMail, UIActivityTypeMessage, UIActivityTypePostToWeibo]; 30 | 31 | // Push it 32 | [self.navigationController pushViewController:self.webViewController animated:YES]; 33 | ``` 34 | 35 | See the example project for more advanced usage. 36 | 37 | ### Subclassing Notes 38 | 39 | `PBWebViewController` can safely be subclassed to implement custom behavior. 40 | Override `load` and the `UIWebViewDelegate` methods to hook in, 41 | just don't forget to call `super` to take advantage of what `PBWebViewController` provides. 42 | 43 | A simple subclass is used in the example project. 44 | 45 | ### Notes on custom activity items and application activities 46 | 47 | `PBWebViewController` sets the current URL as the only activity item, if none or provided, 48 | otherwise the activity items you provide are used. 49 | You can fully customize everything that shows up when the action button is clicked this way. 50 | 51 | Another way to achieve the same result is to override `activityItems` and `applicationActivities` in a subclass. 52 | 53 | Check out the `action:` method in `PBWebViewController.m` for more details. 54 | 55 | ## Contributing 56 | 57 | 1. Fork it 58 | 2. Create your feature branch (`git checkout -b my-new-feature`) 59 | 3. Commit your changes (`git commit -am 'Add some feature'`) 60 | 4. Push to the branch (`git push origin my-new-feature`) 61 | 5. Create new Pull Request 62 | --------------------------------------------------------------------------------