Repository: PSPDFKit-labs/PSTModernizer Branch: master Commit: 2f1787c92f90 Files: 36 Total size: 81.9 KB Directory structure: gitextract_0g2bpret/ ├── .gitignore ├── Example/ │ ├── 26295020, 26294823 - Action Sheet Presentation/ │ │ ├── ActionSheetPresentationIssue.xcodeproj/ │ │ │ ├── project.pbxproj │ │ │ └── project.xcworkspace/ │ │ │ └── contents.xcworkspacedata │ │ ├── Resources/ │ │ │ ├── Base.lproj/ │ │ │ │ └── LaunchScreen.xib │ │ │ ├── Images.xcassets/ │ │ │ │ └── AppIcon.appiconset/ │ │ │ │ └── Contents.json │ │ │ └── Info.plist │ │ └── Source/ │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── NewerWebViewController.h │ │ ├── NewerWebViewController.m │ │ ├── TextViewController.h │ │ ├── TextViewController.m │ │ ├── WebViewController.h │ │ ├── WebViewController.m │ │ ├── Workaround.h │ │ ├── Workaround.mm │ │ └── main.m │ └── 26954460 - UIImageWithDataMultithreaded/ │ ├── UIImageWithDataMultithreaded/ │ │ ├── AppDelegate.h │ │ ├── AppDelegate.m │ │ ├── Assets.xcassets/ │ │ │ └── AppIcon.appiconset/ │ │ │ └── Contents.json │ │ ├── Base.lproj/ │ │ │ ├── LaunchScreen.storyboard │ │ │ └── Main.storyboard │ │ ├── Info.plist │ │ ├── ViewController.h │ │ ├── ViewController.m │ │ └── main.m │ └── UIImageWithDataMultithreaded.xcodeproj/ │ ├── project.pbxproj │ └── project.xcworkspace/ │ └── contents.xcworkspacedata ├── LICENSE ├── PSTModernizer/ │ ├── 1.0.0/ │ │ └── PSTModernizer.podspec │ ├── PSTModernizer.h │ └── PSTModernizer.mm ├── PSTModernizer.podspec ├── PSTModernizer.xcodeproj/ │ ├── project.pbxproj │ └── project.xcworkspace/ │ └── contents.xcworkspacedata └── README.md ================================================ FILE CONTENTS ================================================ ================================================ FILE: .gitignore ================================================ # Xcode # # gitignore contributors: remember to update Global/Xcode.gitignore, Objective-C.gitignore & Swift.gitignore ## Build generated build/ DerivedData/ ## Various settings *.pbxuser !default.pbxuser *.mode1v3 !default.mode1v3 *.mode2v3 !default.mode2v3 *.perspectivev3 !default.perspectivev3 xcuserdata/ ## Other *.moved-aside *.xcuserstate ## Obj-C/Swift specific *.hmap *.ipa *.dSYM.zip *.dSYM # CocoaPods # # We recommend against adding the Pods directory to your .gitignore. However # you should judge for yourself, the pros and cons are mentioned at: # https://guides.cocoapods.org/using/using-cocoapods.html#should-i-check-the-pods-directory-into-source-control # # Pods/ # Carthage # # Add this line if you want to avoid checking in source code from Carthage dependencies. # Carthage/Checkouts Carthage/Build # fastlane # # It is recommended to not store the screenshots in the git repo. Instead, use fastlane to re-generate the # screenshots whenever they are needed. # For more information about the recommended setup visit: # https://github.com/fastlane/fastlane/blob/master/fastlane/docs/Gitignore.md fastlane/report.xml fastlane/screenshots #Code Injection # # After new code Injection tools there's a generated folder /iOSInjectionProject # https://github.com/johnno1962/injectionforxcode iOSInjectionProject/ ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/ActionSheetPresentationIssue.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 780CAFD01CE9C18B00CBBF23 /* Workaround.mm in Sources */ = {isa = PBXBuildFile; fileRef = 780CAFCF1CE9C18B00CBBF23 /* Workaround.mm */; }; 7881AA831D1B7D7D005EC1FF /* PSTModernizer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7881AA821D1B7D7D005EC1FF /* PSTModernizer.mm */; }; A51CD1E51B7CE37500C6E9C3 /* TextViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A51CD1E41B7CE37500C6E9C3 /* TextViewController.m */; }; A56313591CE974B700191654 /* WebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A56313581CE974B700191654 /* WebViewController.m */; }; A59360431A22678800711C3F /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = A59360421A22678700711C3F /* main.m */; }; A59360461A22678800711C3F /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = A59360451A22678800711C3F /* AppDelegate.m */; }; A593604E1A22678800711C3F /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = A593604D1A22678800711C3F /* Images.xcassets */; }; A59360511A22678800711C3F /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = A593604F1A22678800711C3F /* LaunchScreen.xib */; }; A5E68B4F1CE9899A0028420D /* NewerWebViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = A5E68B4E1CE9899A0028420D /* NewerWebViewController.m */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 780CAFCF1CE9C18B00CBBF23 /* Workaround.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = Workaround.mm; sourceTree = ""; }; 780CAFD11CE9C1EB00CBBF23 /* Workaround.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Workaround.h; sourceTree = ""; }; 7881AA811D1B7D7D005EC1FF /* PSTModernizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSTModernizer.h; sourceTree = ""; }; 7881AA821D1B7D7D005EC1FF /* PSTModernizer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PSTModernizer.mm; sourceTree = ""; }; A51CD1E31B7CE37500C6E9C3 /* TextViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = TextViewController.h; sourceTree = ""; }; A51CD1E41B7CE37500C6E9C3 /* TextViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = TextViewController.m; sourceTree = ""; }; A56313571CE974B700191654 /* WebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = WebViewController.h; sourceTree = ""; }; A56313581CE974B700191654 /* WebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = WebViewController.m; sourceTree = ""; }; A593603D1A22678700711C3F /* PresentationPlayground.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = PresentationPlayground.app; sourceTree = BUILT_PRODUCTS_DIR; }; A59360411A22678700711C3F /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; A59360421A22678700711C3F /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; A59360441A22678800711C3F /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; A59360451A22678800711C3F /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; A593604D1A22678800711C3F /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; A59360501A22678800711C3F /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; A5E68B4D1CE9899A0028420D /* NewerWebViewController.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = NewerWebViewController.h; sourceTree = ""; }; A5E68B4E1CE9899A0028420D /* NewerWebViewController.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = NewerWebViewController.m; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ A593603A1A22678700711C3F /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7881AA801D1B7D7D005EC1FF /* PSTModernizer */ = { isa = PBXGroup; children = ( 7881AA811D1B7D7D005EC1FF /* PSTModernizer.h */, 7881AA821D1B7D7D005EC1FF /* PSTModernizer.mm */, ); name = PSTModernizer; path = ../../../PSTModernizer; sourceTree = ""; }; A59360341A22678700711C3F = { isa = PBXGroup; children = ( A59360661A2269BE00711C3F /* Source */, A59360671A2269C200711C3F /* Resources */, A593603E1A22678700711C3F /* Products */, ); sourceTree = ""; }; A593603E1A22678700711C3F /* Products */ = { isa = PBXGroup; children = ( A593603D1A22678700711C3F /* PresentationPlayground.app */, ); name = Products; sourceTree = ""; }; A59360661A2269BE00711C3F /* Source */ = { isa = PBXGroup; children = ( 7881AA801D1B7D7D005EC1FF /* PSTModernizer */, A59360421A22678700711C3F /* main.m */, A59360441A22678800711C3F /* AppDelegate.h */, 780CAFD11CE9C1EB00CBBF23 /* Workaround.h */, 780CAFCF1CE9C18B00CBBF23 /* Workaround.mm */, A59360451A22678800711C3F /* AppDelegate.m */, A51CD1E31B7CE37500C6E9C3 /* TextViewController.h */, A51CD1E41B7CE37500C6E9C3 /* TextViewController.m */, A56313571CE974B700191654 /* WebViewController.h */, A56313581CE974B700191654 /* WebViewController.m */, A5E68B4D1CE9899A0028420D /* NewerWebViewController.h */, A5E68B4E1CE9899A0028420D /* NewerWebViewController.m */, ); path = Source; sourceTree = ""; }; A59360671A2269C200711C3F /* Resources */ = { isa = PBXGroup; children = ( A59360411A22678700711C3F /* Info.plist */, A593604D1A22678800711C3F /* Images.xcassets */, A593604F1A22678800711C3F /* LaunchScreen.xib */, ); path = Resources; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ A593603C1A22678700711C3F /* PresentationPlayground */ = { isa = PBXNativeTarget; buildConfigurationList = A59360601A22678800711C3F /* Build configuration list for PBXNativeTarget "PresentationPlayground" */; buildPhases = ( A59360391A22678700711C3F /* Sources */, A593603A1A22678700711C3F /* Frameworks */, A593603B1A22678700711C3F /* Resources */, ); buildRules = ( ); dependencies = ( ); name = PresentationPlayground; productName = PresentationPlayground; productReference = A593603D1A22678700711C3F /* PresentationPlayground.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ A59360351A22678700711C3F /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Douglas Hill"; TargetAttributes = { A593603C1A22678700711C3F = { CreatedOnToolsVersion = 6.1; }; }; }; buildConfigurationList = A59360381A22678700711C3F /* Build configuration list for PBXProject "ActionSheetPresentationIssue" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = A59360341A22678700711C3F; productRefGroup = A593603E1A22678700711C3F /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( A593603C1A22678700711C3F /* PresentationPlayground */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ A593603B1A22678700711C3F /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( A59360511A22678800711C3F /* LaunchScreen.xib in Resources */, A593604E1A22678800711C3F /* Images.xcassets in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ A59360391A22678700711C3F /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( A59360461A22678800711C3F /* AppDelegate.m in Sources */, A59360431A22678800711C3F /* main.m in Sources */, A5E68B4F1CE9899A0028420D /* NewerWebViewController.m in Sources */, 780CAFD01CE9C18B00CBBF23 /* Workaround.mm in Sources */, A56313591CE974B700191654 /* WebViewController.m in Sources */, A51CD1E51B7CE37500C6E9C3 /* TextViewController.m in Sources */, 7881AA831D1B7D7D005EC1FF /* PSTModernizer.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ A593604F1A22678800711C3F /* LaunchScreen.xib */ = { isa = PBXVariantGroup; children = ( A59360501A22678800711C3F /* Base */, ); name = LaunchScreen.xib; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ A593605E1A22678800711C3F /* 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; ENABLE_STRICT_OBJC_MSGSEND = YES; ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", ); GCC_SYMBOLS_PRIVATE_EXTERN = NO; 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.1; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; A593605F1A22678800711C3F /* 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 = YES; ENABLE_NS_ASSERTIONS = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; GCC_C_LANGUAGE_STANDARD = gnu99; 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.1; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; A59360611A22678800711C3F /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Resources/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.pspdfkit.radar.ActionSheetPresentation; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; A59360621A22678800711C3F /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Resources/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.pspdfkit.radar.ActionSheetPresentation; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ A59360381A22678700711C3F /* Build configuration list for PBXProject "ActionSheetPresentationIssue" */ = { isa = XCConfigurationList; buildConfigurations = ( A593605E1A22678800711C3F /* Debug */, A593605F1A22678800711C3F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; A59360601A22678800711C3F /* Build configuration list for PBXNativeTarget "PresentationPlayground" */ = { isa = XCConfigurationList; buildConfigurations = ( A59360611A22678800711C3F /* Debug */, A59360621A22678800711C3F /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = A59360351A22678700711C3F /* Project object */; } ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/ActionSheetPresentationIssue.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/Resources/Base.lproj/LaunchScreen.xib ================================================ ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/Resources/Images.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/Resources/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/Source/AppDelegate.h ================================================ #import @interface AppDelegate : UIResponder @end ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/Source/AppDelegate.m ================================================ #import "AppDelegate.h" #import "TextViewController.h" #import "WebViewController.h" #import "NewerWebViewController.h" #import "Workaround.h" #import "PSTModernizer.h" @implementation AppDelegate @synthesize window = _window; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { //PSPDFInstallWorkaroundForSheetPresentation(); [PSTModernizer installModernizer]; self.window = [[UIWindow alloc] init]; UIViewController *firstTextViewController = [[TextViewController alloc] init]; firstTextViewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Present Second" style:UIBarButtonItemStylePlain target:self action:@selector(presentSecondTextView:)]; firstTextViewController.title = @"UITextView"; firstTextViewController.navigationItem.title = @"First"; UIViewController *firstWebViewController = [[WebViewController alloc] init]; firstWebViewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Present Second" style:UIBarButtonItemStylePlain target:self action:@selector(presentSecondWebView:)]; firstWebViewController.title = @"UIWebView"; firstWebViewController.navigationItem.title = @"First"; UIViewController *firstNewerWebViewController = [[NewerWebViewController alloc] init]; firstNewerWebViewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Present Second" style:UIBarButtonItemStylePlain target:self action:@selector(presentSecondNewerWebView:)]; firstNewerWebViewController.title = @"WKWebView"; firstNewerWebViewController.navigationItem.title = @"First"; UITabBarController *tabBarController = [[UITabBarController alloc] init]; tabBarController.viewControllers = @[ [[UINavigationController alloc] initWithRootViewController:firstTextViewController], [[UINavigationController alloc] initWithRootViewController:firstWebViewController], [[UINavigationController alloc] initWithRootViewController:firstNewerWebViewController], ]; self.window.rootViewController = tabBarController; [self.window makeKeyAndVisible]; return YES; } - (void)presentSecondTextView:(id)sender { [self presentSecondViewControllerOfClass:[TextViewController class]]; } - (void)presentSecondWebView:(id)sender { [self presentSecondViewControllerOfClass:[WebViewController class]]; } - (void)presentSecondNewerWebView:(id)sender { [self presentSecondViewControllerOfClass:[NewerWebViewController class]]; } - (void)presentSecondViewControllerOfClass:(Class)klass { UIViewController *secondViewController = [[klass alloc] init]; secondViewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemDone target:self action:@selector(dismiss:)]; secondViewController.title = @"Second"; UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:secondViewController]; navigationController.modalPresentationStyle = UIModalPresentationFormSheet; [self.window.rootViewController presentViewController:navigationController animated:YES completion:nil]; } - (void)dismiss:(id)sender { [self.window.rootViewController dismissViewControllerAnimated:YES completion:nil]; } @end ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/Source/NewerWebViewController.h ================================================ #import @interface NewerWebViewController : UIViewController @end ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/Source/NewerWebViewController.m ================================================ #import "NewerWebViewController.h" @import WebKit; @implementation NewerWebViewController - (void)loadView { WKWebView *textView = [[WKWebView alloc] init]; [textView loadHTMLString:@"

This is a WKWebView with an HTML link: PSPDFKit website

" baseURL:nil]; self.view = textView; } @end ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/Source/TextViewController.h ================================================ #import @interface TextViewController : UIViewController @end ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/Source/TextViewController.m ================================================ #import "TextViewController.h" @implementation TextViewController - (void)loadView { UITextView *textView = [[UITextView alloc] init]; textView.dataDetectorTypes = UIDataDetectorTypeAll; textView.editable = NO; textView.font = [UIFont preferredFontForTextStyle:UIFontTextStyleBody]; textView.text = @"This is a UITextView with a phone number: 01234 567890 and web link: https://pspdfkit.com/ and a time: 15:40 tomorrow and an address:\n\n1 Infinite Loop\nCupertino CA 95014\nUnited States"; self.view = textView; } @end ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/Source/WebViewController.h ================================================ #import @interface WebViewController : UIViewController @end ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/Source/WebViewController.m ================================================ #import "WebViewController.h" @implementation WebViewController - (void)loadView { UIWebView *textView = [[UIWebView alloc] init]; textView.dataDetectorTypes = UIDataDetectorTypeAll; [textView loadHTMLString:@"

This is a UIWebView with a phone number: 01234 567890 and a detected web link: https://pspdfkit.com/ and an HTML link: PSPDFKit website and a time: 15:40 tomorrow and an address: 1 Infinite Loop Cupertino CA 95014 United States

" baseURL:nil]; self.view = textView; } @end ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/Source/Workaround.h ================================================ // // Workaround.h // PresentationPlayground // // Created by Peter Steinberger on 16/05/16. // #import FOUNDATION_EXPORT void PSPDFInstallWorkaroundForSheetPresentation(void); ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/Source/Workaround.mm ================================================ // // Workaround.m // PresentationPlayground // // Created by Peter Steinberger on 16/05/16. // #import "Workaround.h" #import #import static IMP pspdf_swizzleSelector(Class clazz, SEL selector, IMP newImplementation) { NSCParameterAssert(clazz); NSCParameterAssert(selector); NSCParameterAssert(newImplementation); // If the method does not exist for this class, do nothing. const Method method = class_getInstanceMethod(clazz, selector); if (!method) { NSLog(@"%@ doesn't exist in %@.", NSStringFromSelector(selector), NSStringFromClass(clazz)); // Cannot swizzle methods which are not implemented by the class or one of its parents. return NULL; } // Make sure the class implements the method. If this is not the case, inject an implementation, only calling 'super'. const char *types = method_getTypeEncoding(method); @synchronized (clazz) { // class_addMethod will simply return NO if the method is already implemented. #if !defined(__arm64__) // Sufficiently large struct typedef struct LargeStruct_ { char dummy[16]; } LargeStruct; NSUInteger retSize = 0; NSGetSizeAndAlignment(types, &retSize, NULL); // Large structs on 32-bit architectures if (sizeof(void *) == 4 && types[0] == _C_STRUCT_B && retSize != 1 && retSize != 2 && retSize != 4 && retSize != 8) { class_addMethod(clazz, selector, imp_implementationWithBlock(^(__unsafe_unretained id self, va_list argp) { struct objc_super super = {.receiver = self, .super_class = class_getSuperclass(clazz)}; return ((LargeStruct (*)(struct objc_super *, SEL, va_list))objc_msgSendSuper_stret)(&super, selector, argp); }), types); } // All other cases else { #endif class_addMethod(clazz, selector, imp_implementationWithBlock(^(__unsafe_unretained id self, va_list argp) { struct objc_super super = {.receiver = self, .super_class = class_getSuperclass(clazz)}; return ((id (*)(struct objc_super *, SEL, va_list))objc_msgSendSuper)(&super, selector, argp); }), types); #if !defined(__arm64__) } #endif // Swizzling return class_replaceMethod(clazz, selector, newImplementation, types); } } IMP pspdf_swizzleSelectorWithBlock(Class clazz, SEL selector, id newImplementationBlock) { IMP const newImplementation = imp_implementationWithBlock(newImplementationBlock); return pspdf_swizzleSelector(clazz, selector, newImplementation); } FOUNDATION_EXPORT void PSPDFInstallWorkaroundForSheetPresentation(void) { __block auto removeWorkaround = ^{}; const auto installWorkaround = ^{ const SEL presentSEL = @selector(presentViewController:animated:completion:); __block IMP origIMP = pspdf_swizzleSelectorWithBlock(UIViewController.class, presentSEL, ^(UIViewController *self, id vC, BOOL animated, id completion) { UIViewController *targetVC = self; while (targetVC.presentedViewController) { targetVC = targetVC.presentedViewController; } ((void (*)(id, SEL, id, BOOL, id))origIMP)(targetVC, presentSEL, vC, animated, completion); }); removeWorkaround = ^{ pspdf_swizzleSelector(UIViewController.class, presentSEL, origIMP); }; }; // Fixes rdar:// const SEL presentSheetSEL = NSSelectorFromString(@"presentSheetFromRect:"); const auto swizzleOnClass = ^(Class klass) { const __block IMP origIMP = pspdf_swizzleSelectorWithBlock(klass, presentSheetSEL, ^(id self, CGRect rect) { // Before calling the original implementation, we swizzle the presentation logic on UIViewController installWorkaround(); // UIKit later presents the sheet on [view.window rootViewController]; // Our workaround forwards this to the topmost presentedViewController instead. ((void (*)(id, SEL, CGRect))origIMP)(self, presentSheetSEL, rect); // Cleaning up again - this workaround would swallow bugs if we let it be there. removeWorkaround(); }); }; swizzleOnClass(NSClassFromString(@"_UIRotatingAlertController")); swizzleOnClass(NSClassFromString(@"WKActionSheet")); } ================================================ FILE: Example/26295020, 26294823 - Action Sheet Presentation/Source/main.m ================================================ @import UIKit; #import "AppDelegate.h" int main(int argc, char *argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ================================================ FILE: Example/26954460 - UIImageWithDataMultithreaded/UIImageWithDataMultithreaded/AppDelegate.h ================================================ // // AppDelegate.h // UIImageWithDataMultithreaded // // Created by Peter Steinberger on 22/06/16. // Copyright © 2016 PSPDFKit GmbH. All rights reserved. // #import @interface AppDelegate : UIResponder @property (strong, nonatomic) UIWindow *window; @end ================================================ FILE: Example/26954460 - UIImageWithDataMultithreaded/UIImageWithDataMultithreaded/AppDelegate.m ================================================ // // AppDelegate.m // UIImageWithDataMultithreaded // // Created by Peter Steinberger on 22/06/16. // Copyright © 2016 PSPDFKit GmbH. All rights reserved. // #import "AppDelegate.h" #import "PSTModernizer.h" @interface AppDelegate () @end @implementation AppDelegate - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { [PSTModernizer installModernizer]; return YES; } @end ================================================ FILE: Example/26954460 - UIImageWithDataMultithreaded/UIImageWithDataMultithreaded/Assets.xcassets/AppIcon.appiconset/Contents.json ================================================ { "images" : [ { "idiom" : "iphone", "size" : "29x29", "scale" : "2x" }, { "idiom" : "iphone", "size" : "29x29", "scale" : "3x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "2x" }, { "idiom" : "iphone", "size" : "40x40", "scale" : "3x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "2x" }, { "idiom" : "iphone", "size" : "60x60", "scale" : "3x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "1x" }, { "idiom" : "ipad", "size" : "29x29", "scale" : "2x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "1x" }, { "idiom" : "ipad", "size" : "40x40", "scale" : "2x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "1x" }, { "idiom" : "ipad", "size" : "76x76", "scale" : "2x" } ], "info" : { "version" : 1, "author" : "xcode" } } ================================================ FILE: Example/26954460 - UIImageWithDataMultithreaded/UIImageWithDataMultithreaded/Base.lproj/LaunchScreen.storyboard ================================================ ================================================ FILE: Example/26954460 - UIImageWithDataMultithreaded/UIImageWithDataMultithreaded/Base.lproj/Main.storyboard ================================================ ================================================ FILE: Example/26954460 - UIImageWithDataMultithreaded/UIImageWithDataMultithreaded/Info.plist ================================================ CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName $(PRODUCT_NAME) CFBundlePackageType APPL CFBundleShortVersionString 1.0 CFBundleSignature ???? CFBundleVersion 1 LSRequiresIPhoneOS UILaunchStoryboardName LaunchScreen UIMainStoryboardFile Main UIRequiredDeviceCapabilities armv7 UISupportedInterfaceOrientations UIInterfaceOrientationPortrait UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight UISupportedInterfaceOrientations~ipad UIInterfaceOrientationPortrait UIInterfaceOrientationPortraitUpsideDown UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight ================================================ FILE: Example/26954460 - UIImageWithDataMultithreaded/UIImageWithDataMultithreaded/ViewController.h ================================================ // // ViewController.h // UIImageWithDataMultithreaded // // Created by Peter Steinberger on 22/06/16. // Copyright © 2016 PSPDFKit GmbH. All rights reserved. // #import @interface ViewController : UIViewController @end ================================================ FILE: Example/26954460 - UIImageWithDataMultithreaded/UIImageWithDataMultithreaded/ViewController.m ================================================ // // ViewController.m // UIImageWithDataMultithreaded // // Created by Peter Steinberger on 22/06/16. // Copyright © 2016 PSPDFKit GmbH. All rights reserved. // #import "ViewController.h" @interface ViewController () @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"meme" withExtension:@"png"]; NSData *data = [NSData dataWithContentsOfURL:fileURL]; dispatch_apply(10000000, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(size_t idx) { @autoreleasepool { UIImage *image = [UIImage imageWithData:data]; assert(image != nil); } }); } @end #import #import // Compile-time selector checks. #if DEBUG #define PROPERTY(propName) NSStringFromSelector(@selector(propName)) #else #define PROPERTY(propName) @#propName #endif // http://www.mikeash.com/pyblog/friday-qa-2010-01-29-method-replacement-for-fun-and-profit.html BOOL PSPDFReplaceMethodWithBlock(Class c, SEL origSEL, SEL newSEL, id block) { NSCParameterAssert(c); NSCParameterAssert(origSEL); NSCParameterAssert(newSEL); NSCParameterAssert(block); if ([c instancesRespondToSelector:newSEL]) return YES; // Selector already implemented, skip silently. Method origMethod = class_getInstanceMethod(c, origSEL); // Add the new method. IMP impl = imp_implementationWithBlock(block); if (!class_addMethod(c, newSEL, impl, method_getTypeEncoding(origMethod))) { NSLog(@"Failed to add method: %@ on %@", NSStringFromSelector(newSEL), c); return NO; }else { Method newMethod = class_getInstanceMethod(c, newSEL); // If original doesn't implement the method we want to swizzle, create it. if (class_addMethod(c, origSEL, method_getImplementation(newMethod), method_getTypeEncoding(origMethod))) { class_replaceMethod(c, newSEL, method_getImplementation(origMethod), method_getTypeEncoding(newMethod)); }else { method_exchangeImplementations(origMethod, newMethod); } } return YES; } SEL _PSPDFPrefixedSelector(SEL selector) { return NSSelectorFromString([NSString stringWithFormat:@"pspdf_%@", NSStringFromSelector(selector)]); } #define PSPDFAssert(expression, ...) \ do { if(!(expression)) { \ NSLog(@"%@", [NSString stringWithFormat: @"Assertion failure: %s in %s on line %s:%d. %@", #expression, __PRETTY_FUNCTION__, __FILE__, __LINE__, [NSString stringWithFormat:@"" __VA_ARGS__]]); \ abort(); }} while(0) void PSPDFAssertIfNotMainThread(void) { PSPDFAssert(NSThread.isMainThread, @"\nERROR: All calls to UIKit need to happen on the main thread. You have a bug in your code. Use dispatch_async(dispatch_get_main_queue(), ^{ ... }); if you're unsure what thread you're in.\n\nBreak on PSPDFAssertIfNotMainThread to find out where.\n\nStacktrace: %@", NSThread.callStackSymbols); } __attribute__((constructor)) static void PSPDFUIKitMainThreadGuard(void) { @autoreleasepool { for (NSString *selStr in @[PROPERTY(setNeedsLayout), PROPERTY(setNeedsDisplay), PROPERTY(setNeedsDisplayInRect:)]) { SEL selector = NSSelectorFromString(selStr); SEL newSelector = NSSelectorFromString([NSString stringWithFormat:@"pspdf_%@", selStr]); if ([selStr hasSuffix:@":"]) { PSPDFReplaceMethodWithBlock(UIView.class, selector, newSelector, ^(__unsafe_unretained UIView *_self, CGRect r) { // Check for window, since *some* UIKit methods are indeed thread safe. // https://developer.apple.com/library/ios/#releasenotes/General/WhatsNewIniPhoneOS/Articles/iPhoneOS4.html /* Drawing to a graphics context in UIKit is now thread-safe. Specifically: The routines used to access and manipulate the graphics context can now correctly handle contexts residing on different threads. String and image drawing is now thread-safe. Using color and font objects in multiple threads is now safe to do. */ if (_self.window) PSPDFAssertIfNotMainThread(); ((void ( *)(id, SEL, CGRect))objc_msgSend)(_self, newSelector, r); }); }else { PSPDFReplaceMethodWithBlock(UIView.class, selector, newSelector, ^(__unsafe_unretained UIView *_self) { if (_self.window) { if (!NSThread.isMainThread) { #pragma clang diagnostic push #pragma clang diagnostic ignored "-Wdeprecated-declarations" dispatch_queue_t queue = dispatch_get_current_queue(); #pragma clang diagnostic pop // iOS 8 layouts the MFMailComposeController in a background thread on an UIKit queue. // https://github.com/PSPDFKit/PSPDFKit/issues/1423 if (!queue || !strstr(dispatch_queue_get_label(queue), "UIKit")) { PSPDFAssertIfNotMainThread(); } } } ((void ( *)(id, SEL))objc_msgSend)(_self, newSelector); }); } } } } ================================================ FILE: Example/26954460 - UIImageWithDataMultithreaded/UIImageWithDataMultithreaded/main.m ================================================ // // main.m // UIImageWithDataMultithreaded // // Created by Peter Steinberger on 22/06/16. // Copyright © 2016 PSPDFKit GmbH. All rights reserved. // #import #import "AppDelegate.h" int main(int argc, char * argv[]) { @autoreleasepool { return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class])); } } ================================================ FILE: Example/26954460 - UIImageWithDataMultithreaded/UIImageWithDataMultithreaded.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7881AA7F1D1B7AE4005EC1FF /* PSTModernizer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7881AA7E1D1B7AE4005EC1FF /* PSTModernizer.mm */; }; 78A341181D1B283D00858C36 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A341171D1B283D00858C36 /* main.m */; }; 78A3411B1D1B283D00858C36 /* AppDelegate.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A3411A1D1B283D00858C36 /* AppDelegate.m */; }; 78A3411E1D1B283D00858C36 /* ViewController.m in Sources */ = {isa = PBXBuildFile; fileRef = 78A3411D1D1B283D00858C36 /* ViewController.m */; }; 78A341211D1B283D00858C36 /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 78A3411F1D1B283D00858C36 /* Main.storyboard */; }; 78A341231D1B283D00858C36 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 78A341221D1B283D00858C36 /* Assets.xcassets */; }; 78A341261D1B283D00858C36 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 78A341241D1B283D00858C36 /* LaunchScreen.storyboard */; }; 78A3412E1D1B288900858C36 /* meme.png in Resources */ = {isa = PBXBuildFile; fileRef = 78A3412D1D1B288900858C36 /* meme.png */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ 7881AA7D1D1B7AE4005EC1FF /* PSTModernizer.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = PSTModernizer.h; sourceTree = ""; }; 7881AA7E1D1B7AE4005EC1FF /* PSTModernizer.mm */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.objcpp; path = PSTModernizer.mm; sourceTree = ""; }; 78A341131D1B283D00858C36 /* UIImageWithDataMultithreaded.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = UIImageWithDataMultithreaded.app; sourceTree = BUILT_PRODUCTS_DIR; }; 78A341171D1B283D00858C36 /* main.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = ""; }; 78A341191D1B283D00858C36 /* AppDelegate.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = AppDelegate.h; sourceTree = ""; }; 78A3411A1D1B283D00858C36 /* AppDelegate.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = AppDelegate.m; sourceTree = ""; }; 78A3411C1D1B283D00858C36 /* ViewController.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = ViewController.h; sourceTree = ""; }; 78A3411D1D1B283D00858C36 /* ViewController.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = ViewController.m; sourceTree = ""; }; 78A341201D1B283D00858C36 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 78A341221D1B283D00858C36 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 78A341251D1B283D00858C36 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 78A341271D1B283D00858C36 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 78A3412D1D1B288900858C36 /* meme.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = meme.png; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 78A341101D1B283D00858C36 /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7881AA7C1D1B7AE4005EC1FF /* PSTModernizer */ = { isa = PBXGroup; children = ( 7881AA7D1D1B7AE4005EC1FF /* PSTModernizer.h */, 7881AA7E1D1B7AE4005EC1FF /* PSTModernizer.mm */, ); name = PSTModernizer; path = ../../../PSTModernizer; sourceTree = ""; }; 78A3410A1D1B283D00858C36 = { isa = PBXGroup; children = ( 78A341151D1B283D00858C36 /* UIImageWithDataMultithreaded */, 78A341141D1B283D00858C36 /* Products */, ); sourceTree = ""; }; 78A341141D1B283D00858C36 /* Products */ = { isa = PBXGroup; children = ( 78A341131D1B283D00858C36 /* UIImageWithDataMultithreaded.app */, ); name = Products; sourceTree = ""; }; 78A341151D1B283D00858C36 /* UIImageWithDataMultithreaded */ = { isa = PBXGroup; children = ( 7881AA7C1D1B7AE4005EC1FF /* PSTModernizer */, 78A3412D1D1B288900858C36 /* meme.png */, 78A341191D1B283D00858C36 /* AppDelegate.h */, 78A3411A1D1B283D00858C36 /* AppDelegate.m */, 78A3411C1D1B283D00858C36 /* ViewController.h */, 78A3411D1D1B283D00858C36 /* ViewController.m */, 78A3411F1D1B283D00858C36 /* Main.storyboard */, 78A341221D1B283D00858C36 /* Assets.xcassets */, 78A341241D1B283D00858C36 /* LaunchScreen.storyboard */, 78A341271D1B283D00858C36 /* Info.plist */, 78A341161D1B283D00858C36 /* Supporting Files */, ); path = UIImageWithDataMultithreaded; sourceTree = ""; }; 78A341161D1B283D00858C36 /* Supporting Files */ = { isa = PBXGroup; children = ( 78A341171D1B283D00858C36 /* main.m */, ); name = "Supporting Files"; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 78A341121D1B283D00858C36 /* UIImageWithDataMultithreaded */ = { isa = PBXNativeTarget; buildConfigurationList = 78A3412A1D1B283D00858C36 /* Build configuration list for PBXNativeTarget "UIImageWithDataMultithreaded" */; buildPhases = ( 78A3410F1D1B283D00858C36 /* Sources */, 78A341101D1B283D00858C36 /* Frameworks */, 78A341111D1B283D00858C36 /* Resources */, ); buildRules = ( ); dependencies = ( ); name = UIImageWithDataMultithreaded; productName = UIImageWithDataMultithreaded; productReference = 78A341131D1B283D00858C36 /* UIImageWithDataMultithreaded.app */; productType = "com.apple.product-type.application"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 78A3410B1D1B283D00858C36 /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0730; ORGANIZATIONNAME = "PSPDFKit GmbH"; TargetAttributes = { 78A341121D1B283D00858C36 = { CreatedOnToolsVersion = 7.3.1; }; }; }; buildConfigurationList = 78A3410E1D1B283D00858C36 /* Build configuration list for PBXProject "UIImageWithDataMultithreaded" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 78A3410A1D1B283D00858C36; productRefGroup = 78A341141D1B283D00858C36 /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 78A341121D1B283D00858C36 /* UIImageWithDataMultithreaded */, ); }; /* End PBXProject section */ /* Begin PBXResourcesBuildPhase section */ 78A341111D1B283D00858C36 /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; files = ( 78A341261D1B283D00858C36 /* LaunchScreen.storyboard in Resources */, 78A341231D1B283D00858C36 /* Assets.xcassets in Resources */, 78A341211D1B283D00858C36 /* Main.storyboard in Resources */, 78A3412E1D1B288900858C36 /* meme.png in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ 78A3410F1D1B283D00858C36 /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 78A3411E1D1B283D00858C36 /* ViewController.m in Sources */, 78A3411B1D1B283D00858C36 /* AppDelegate.m in Sources */, 7881AA7F1D1B7AE4005EC1FF /* PSTModernizer.mm in Sources */, 78A341181D1B283D00858C36 /* main.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin PBXVariantGroup section */ 78A3411F1D1B283D00858C36 /* Main.storyboard */ = { isa = PBXVariantGroup; children = ( 78A341201D1B283D00858C36 /* Base */, ); name = Main.storyboard; sourceTree = ""; }; 78A341241D1B283D00858C36 /* LaunchScreen.storyboard */ = { isa = PBXVariantGroup; children = ( 78A341251D1B283D00858C36 /* Base */, ); name = LaunchScreen.storyboard; sourceTree = ""; }; /* End PBXVariantGroup section */ /* Begin XCBuildConfiguration section */ 78A341281D1B283D00858C36 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; 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; 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.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; }; name = Debug; }; 78A341291D1B283D00858C36 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; 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; 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.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; VALIDATE_PRODUCT = YES; }; name = Release; }; 78A3412B1D1B283D00858C36 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = UIImageWithDataMultithreaded/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = PSPDFKit.UIImageWithDataMultithreaded; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Debug; }; 78A3412C1D1B283D00858C36 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = UIImageWithDataMultithreaded/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = PSPDFKit.UIImageWithDataMultithreaded; PRODUCT_NAME = "$(TARGET_NAME)"; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 78A3410E1D1B283D00858C36 /* Build configuration list for PBXProject "UIImageWithDataMultithreaded" */ = { isa = XCConfigurationList; buildConfigurations = ( 78A341281D1B283D00858C36 /* Debug */, 78A341291D1B283D00858C36 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 78A3412A1D1B283D00858C36 /* Build configuration list for PBXNativeTarget "UIImageWithDataMultithreaded" */ = { isa = XCConfigurationList; buildConfigurations = ( 78A3412B1D1B283D00858C36 /* Debug */, 78A3412C1D1B283D00858C36 /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 78A3410B1D1B283D00858C36 /* Project object */; } ================================================ FILE: Example/26954460 - UIImageWithDataMultithreaded/UIImageWithDataMultithreaded.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: LICENSE ================================================ The MIT License (MIT) Copyright (c) 2016 Peter Steinberger, PSPDFKit GmbH. 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. ================================================ FILE: PSTModernizer/1.0.0/PSTModernizer.podspec ================================================ # # Be sure to run `pod lib lint PSTModernizer.podspec' to ensure this is a # valid spec before submitting. # Pod::Spec.new do |s| s.name = 'PSTModernizer' s.version = '1.0.0' s.summary = 'Makes it easier to support older versions of iOS by fixing things and adding missing methods' s.description = <<-DESC PSTModernizer carefully applies patches to UIKit and related Apple frameworks to fix known radars with the least impact. The current set of patches just applies to iOS 9 and nothing is executed on iOS 10, as the bugs have been fixed there. DESC s.homepage = 'https://github.com/PSPDFKit-labs/PSTModernizer' s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'Peter Steinberger, PSPDFKit' => 'https://pspdfkit.com/' } s.source = { :git => 'https://github.com/PSPDFKit-labs/PSTModernizer.git', :tag => s.version.to_s } s.source_files = 'PSTModernizer/**/*' s.social_media_url = 'https://twitter.com/steipete' s.ios.deployment_target = '9.0' s.tvos.deployment_target = '9.0' s.xcconfig = { 'CLANG_MODULES_AUTOLINK' => 'YES' } end ================================================ FILE: PSTModernizer/PSTModernizer.h ================================================ // // PSTModernizer.h // PSTModernizer // // Created by Peter Steinberger on 23/06/16. // Copyright © 2016 PSPDFKit GmbH. All rights reserved. // #import /// Patches the runtime as soon as this class is linked within the `load` path. @interface PSTModernizer : NSObject /// Call this early enough - ideally in your AppDelegate. + (void)installModernizer; /// Returns the version of the modernizer. + (double)version; @end ================================================ FILE: PSTModernizer/PSTModernizer.mm ================================================ // // PSTModernizer.mm // PSTModernizer // // Created by Peter Steinberger on 23/06/16. // Copyright © 2016 PSPDFKit GmbH. All rights reserved. // #import "PSTModernizer.h" #import #import #import #import // Hello, Swift :) #if defined(__cplusplus) #define let const auto #else // Works as of Xcode 8 #define let const __auto_type #endif #define PSTClassObfuscate(...) NSClassFromString([NSString stringWithFormat:__VA_ARGS__]) #define PSTSELObfuscate(...) NSSelectorFromString([NSString stringWithFormat:__VA_ARGS__]) // iOS 10 compatibility #ifndef kCFCoreFoundationVersionNumber_iOS_10_0 #define kCFCoreFoundationVersionNumber_iOS_10_0 1300.0 #endif #define PST_IS_IOS10_0_OR_GREATER (kCFCoreFoundationVersionNumber >= kCFCoreFoundationVersionNumber_iOS_10_0) #if defined(__IPHONE_OS_VERSION_MAX_ALLOWED) && __IPHONE_OS_VERSION_MAX_ALLOWED >= 100000 #define PST_IF_IOS10_0_OR_GREATER(...) \ if (PST_IS_IOS10_0_OR_GREATER) { \ PST_PARTIAL_AVAILABILITY_BEGIN \ __VA_ARGS__ \ PST_PARTIAL_AVAILABILITY_END } #else #define PST_IF_IOS10_0_OR_GREATER(...) #endif #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 100000 #define PST_IF_PRE_IOS10_0(...) \ if (kCFCoreFoundationVersionNumber < kCFCoreFoundationVersionNumber_iOS_10_0) { \ PST_PARTIAL_AVAILABILITY_BEGIN \ __VA_ARGS__ \ PST_PARTIAL_AVAILABILITY_END } #else #define PST_IF_PRE_IOS10_0(...) #endif #define PSTLogError NSLog #define PSTLogWarning NSLog @implementation PSTModernizer + (double)version { return 1000.0; } + (void)installModernizer { static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ [self installModernizerOnce]; }); } + (void)installModernizerOnce { // Define this class in the runtime to block the modernizer being called. if (NSClassFromString(@"PSTModernizerDisabled")) { return; } #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 100000 // Fixes rdar://26295020: Action sheets presented for links don’t work in presented view controllers. // This has been fixed in iOS 10b1. PSTInstallWorkaroundForSheetPresentationRdar26295020(); // UIImage has threading issues under iOS 9. // See https://github.com/AFNetworking/AFNetworking/issues/2572#issuecomment-227895102 // This has been fixed in iOS 10b1 PSTAddLockingToUIImageRdar26954460(); #endif // In anticipation that we'll find bugs in iOS 10 that we run as well, not everything is blocked when you compile with iOS 10 only. NSLog(@"%@ version %.0f installed.", NSStringFromClass(self.class), self.version); } #if defined(__IPHONE_OS_VERSION_MIN_REQUIRED) && __IPHONE_OS_VERSION_MIN_REQUIRED < 100000 static void PSTInstallWorkaroundForSheetPresentationRdar26295020() { // This has been fixed in iOS 10b1 so it's only necessary for older versions of iOS. PST_IF_IOS10_0_OR_GREATER(return;) __block auto removeWorkaround = ^{}; let installWorkaround = ^{ let presentSEL = @selector(presentViewController:animated:completion:); const __block IMP origIMP = pst_swizzleSelectorWithBlock(UIViewController.class, presentSEL, ^(UIViewController *_self, id vC, BOOL animated, id completion) { while (_self.presentedViewController) { _self = _self.presentedViewController; } ((void (*)(id, SEL, id, BOOL, id))origIMP)(_self, presentSEL, vC, animated, completion); }); if (origIMP) { removeWorkaround = ^{ pst_swizzleSelector(UIViewController.class, presentSEL, origIMP); }; } }; let presentSheetSEL = PSTSELObfuscate(@"present%@FromRect:", @"Sheet"); let swizzleOnClass = ^(Class klass) { if (!klass) { PSTLogWarning(@"Unable to install workaround for rdar://26295020."); return; } __block IMP origIMP = pst_swizzleSelectorWithBlock(klass, presentSheetSEL, ^(id _self, CGRect rect) { // Before calling the original implementation, we swizzle the presentation logic on UIViewController installWorkaround(); // UIKit later presents the sheet on [view.window rootViewController]; // See https://github.com/WebKit/webkit/blob/1aceb9ed7a42d0a5ed11558c72bcd57068b642e7/Source/WebKit2/UIProcess/ios/WKActionSheet.mm#L102 // Our workaround forwards this to the topmost presentedViewController instead. ((void (*)(id, SEL, CGRect))origIMP)(_self, presentSheetSEL, rect); // Cleaning up again - this workaround would swallow bugs if we let it be there. removeWorkaround(); }); }; swizzleOnClass(PSTClassObfuscate(@"_%@%@AlertController", @"UI", @"Rotating")); // WKWebView might not be loaded, then we can't patch it. if (let wkWebViewClass = PSTClassObfuscate(@"%@ActionSheet", @"WK")) { swizzleOnClass(wkWebViewClass); } } static void PSTAddLockingToUIImageRdar26954460() { // This has been fixed in iOS 10b1 so it's only necessary for older versions of iOS. PST_IF_IOS10_0_OR_GREATER(return;) // The dictionary that UITraitCollectionCacheForBuiltinStorage returns // is not thread safe. We can't easily hook C methods, so we lock the main initializer // where the cache is being used. This will not cover all races around UITraitCollection, // however with this level of granularity UIImage creation will work as expected. // // Overriding all calls of UITraitCollectionCacheForBuiltinStorage would require // using private API. static pthread_mutex_t mutex = PTHREAD_RECURSIVE_MUTEX_INITIALIZER; let displayScaleSEL = @selector(traitCollectionWithDisplayScale:); __block IMP origIMP = pst_swizzleSelectorWithBlock(object_getClass(UITraitCollection.class), displayScaleSEL, ^id(id _self, CGFloat scale) { pthread_mutex_lock(&mutex); id result = ((id (*)(id, SEL, CGFloat))origIMP)(_self, displayScaleSEL, scale); pthread_mutex_unlock(&mutex); return result; }); } #endif /////////////////////////////////////////////////////////////////////////////////////////// #pragma mark - Swizzle static IMP pst_swizzleSelectorWithBlock(Class clazz, SEL selector, id newImplementationBlock) { const IMP newImplementation = imp_implementationWithBlock(newImplementationBlock); return pst_swizzleSelector(clazz, selector, newImplementation); } static IMP pst_swizzleSelector(Class clazz, SEL selector, IMP newImplementation) { NSCParameterAssert(clazz); NSCParameterAssert(selector); NSCParameterAssert(newImplementation); // If the method does not exist for this class, do nothing. Method method = class_getInstanceMethod(clazz, selector); if (!method) { PSTLogError(@"%@ doesn't exist in %@.", NSStringFromSelector(selector), NSStringFromClass(clazz)); // Cannot swizzle methods which are not implemented by the class or one of its parents. return NULL; } // Make sure the class implements the method. If this is not the case, inject an implementation, only calling 'super'. const char *types = method_getTypeEncoding(method); @synchronized (clazz) { // class_addMethod will simply return NO if the method is already implemented. #if !defined(__arm64__) // Sufficiently large struct typedef struct LargeStruct_ { char dummy[16]; } LargeStruct; NSUInteger retSize = 0; NSGetSizeAndAlignment(types, &retSize, NULL); // Large structs on 32-bit architectures if (sizeof(void *) == 4 && types[0] == _C_STRUCT_B && retSize != 1 && retSize != 2 && retSize != 4 && retSize != 8) { class_addMethod(clazz, selector, imp_implementationWithBlock(^(__unsafe_unretained id self, va_list argp) { struct objc_super super = {.receiver = self, .super_class = class_getSuperclass(clazz)}; return ((LargeStruct (*)(struct objc_super *, SEL, va_list))objc_msgSendSuper_stret)(&super, selector, argp); }), types); } // All other cases else { #endif class_addMethod(clazz, selector, imp_implementationWithBlock(^(__unsafe_unretained id self, va_list argp) { struct objc_super super = {.receiver = self, .super_class = class_getSuperclass(clazz)}; return ((id (*)(struct objc_super *, SEL, va_list))objc_msgSendSuper)(&super, selector, argp); }), types); #if !defined(__arm64__) } #endif // Swizzling return class_replaceMethod(clazz, selector, newImplementation, types); } } @end ================================================ FILE: PSTModernizer.podspec ================================================ # # Be sure to run `pod lib lint PSTModernizer.podspec' to ensure this is a # valid spec before submitting. # Pod::Spec.new do |s| s.name = 'PSTModernizer' s.version = '1.0.0' s.summary = 'Makes it easier to support older versions of iOS by fixing things and adding missing methods' s.description = <<-DESC PSTModernizer carefully applies patches to UIKit and related Apple frameworks to fix known radars with the least impact. The current set of patches just applies to iOS 9 and nothing is executed on iOS 10, as the bugs have been fixed there. DESC s.homepage = 'https://github.com/PSPDFKit-labs/PSTModernizer' s.license = { :type => 'MIT', :file => 'LICENSE' } s.author = { 'Peter Steinberger, PSPDFKit' => 'https://pspdfkit.com/' } s.source = { :git => 'https://github.com/PSPDFKit-labs/PSTModernizer.git', :tag => s.version.to_s } s.source_files = 'PSTModernizer/**/*' s.social_media_url = 'https://twitter.com/steipete' s.ios.deployment_target = '9.0' s.tvos.deployment_target = '9.0' s.xcconfig = { 'CLANG_MODULES_AUTOLINK' => 'YES' } end ================================================ FILE: PSTModernizer.xcodeproj/project.pbxproj ================================================ // !$*UTF8*$! { archiveVersion = 1; classes = { }; objectVersion = 46; objects = { /* Begin PBXBuildFile section */ 7877A4441D1B672B005AEBAC /* PSTModernizer.h in CopyFiles */ = {isa = PBXBuildFile; fileRef = 7877A4431D1B672B005AEBAC /* PSTModernizer.h */; }; 7877A4461D1B672B005AEBAC /* PSTModernizer.mm in Sources */ = {isa = PBXBuildFile; fileRef = 7877A4451D1B672B005AEBAC /* PSTModernizer.mm */; settings = {COMPILER_FLAGS = "-fno-exceptions"; }; }; /* End PBXBuildFile section */ /* Begin PBXCopyFilesBuildPhase section */ 7877A43E1D1B672B005AEBAC /* CopyFiles */ = { isa = PBXCopyFilesBuildPhase; buildActionMask = 2147483647; dstPath = "include/$(PRODUCT_NAME)"; dstSubfolderSpec = 16; files = ( 7877A4441D1B672B005AEBAC /* PSTModernizer.h in CopyFiles */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXCopyFilesBuildPhase section */ /* Begin PBXFileReference section */ 7877A4401D1B672B005AEBAC /* libPSTModernizer.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libPSTModernizer.a; sourceTree = BUILT_PRODUCTS_DIR; }; 7877A4431D1B672B005AEBAC /* PSTModernizer.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = PSTModernizer.h; sourceTree = ""; }; 7877A4451D1B672B005AEBAC /* PSTModernizer.mm */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.cpp.objcpp; path = PSTModernizer.mm; sourceTree = ""; }; 7881AA3A1D1B761E005EC1FF /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; }; 7881AA3C1D1B7622005EC1FF /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ 7877A43D1D1B672B005AEBAC /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ 7877A4371D1B672B005AEBAC = { isa = PBXGroup; children = ( 7881AA3C1D1B7622005EC1FF /* Foundation.framework */, 7881AA3A1D1B761E005EC1FF /* UIKit.framework */, 7877A4421D1B672B005AEBAC /* PSTModernizer */, 7877A4411D1B672B005AEBAC /* Products */, ); sourceTree = ""; }; 7877A4411D1B672B005AEBAC /* Products */ = { isa = PBXGroup; children = ( 7877A4401D1B672B005AEBAC /* libPSTModernizer.a */, ); name = Products; sourceTree = ""; }; 7877A4421D1B672B005AEBAC /* PSTModernizer */ = { isa = PBXGroup; children = ( 7877A4431D1B672B005AEBAC /* PSTModernizer.h */, 7877A4451D1B672B005AEBAC /* PSTModernizer.mm */, ); path = PSTModernizer; sourceTree = ""; }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ 7877A43F1D1B672B005AEBAC /* PSTModernizer */ = { isa = PBXNativeTarget; buildConfigurationList = 7877A4491D1B672B005AEBAC /* Build configuration list for PBXNativeTarget "PSTModernizer" */; buildPhases = ( 7877A43C1D1B672B005AEBAC /* Sources */, 7877A43D1D1B672B005AEBAC /* Frameworks */, 7877A43E1D1B672B005AEBAC /* CopyFiles */, ); buildRules = ( ); dependencies = ( ); name = PSTModernizer; productName = PSTModernizer; productReference = 7877A4401D1B672B005AEBAC /* libPSTModernizer.a */; productType = "com.apple.product-type.library.static"; }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ 7877A4381D1B672B005AEBAC /* Project object */ = { isa = PBXProject; attributes = { LastUpgradeCheck = 0730; ORGANIZATIONNAME = "PSPDFKit GmbH"; TargetAttributes = { 7877A43F1D1B672B005AEBAC = { CreatedOnToolsVersion = 7.3.1; }; }; }; buildConfigurationList = 7877A43B1D1B672B005AEBAC /* Build configuration list for PBXProject "PSTModernizer" */; compatibilityVersion = "Xcode 3.2"; developmentRegion = English; hasScannedForEncodings = 0; knownRegions = ( en, Base, ); mainGroup = 7877A4371D1B672B005AEBAC; productRefGroup = 7877A4411D1B672B005AEBAC /* Products */; projectDirPath = ""; projectRoot = ""; targets = ( 7877A43F1D1B672B005AEBAC /* PSTModernizer */, ); }; /* End PBXProject section */ /* Begin PBXSourcesBuildPhase section */ 7877A43C1D1B672B005AEBAC /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( 7877A4461D1B672B005AEBAC /* PSTModernizer.mm in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXSourcesBuildPhase section */ /* Begin XCBuildConfiguration section */ 7877A4471D1B672B005AEBAC /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; 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; 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.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; OTHER_LDFLAGS = "-lc++"; SDKROOT = iphoneos; }; name = Debug; }; 7877A4481D1B672B005AEBAC /* Release */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; CLANG_ANALYZER_NONNULL = YES; 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; 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.3; MTL_ENABLE_DEBUG_INFO = NO; OTHER_LDFLAGS = "-lc++"; SDKROOT = iphoneos; VALIDATE_PRODUCT = YES; }; name = Release; }; 7877A44A1D1B672B005AEBAC /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; name = Debug; }; 7877A44B1D1B672B005AEBAC /* Release */ = { isa = XCBuildConfiguration; buildSettings = { OTHER_LDFLAGS = "-ObjC"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; }; name = Release; }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ 7877A43B1D1B672B005AEBAC /* Build configuration list for PBXProject "PSTModernizer" */ = { isa = XCConfigurationList; buildConfigurations = ( 7877A4471D1B672B005AEBAC /* Debug */, 7877A4481D1B672B005AEBAC /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; 7877A4491D1B672B005AEBAC /* Build configuration list for PBXNativeTarget "PSTModernizer" */ = { isa = XCConfigurationList; buildConfigurations = ( 7877A44A1D1B672B005AEBAC /* Debug */, 7877A44B1D1B672B005AEBAC /* Release */, ); defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; /* End XCConfigurationList section */ }; rootObject = 7877A4381D1B672B005AEBAC /* Project object */; } ================================================ FILE: PSTModernizer.xcodeproj/project.xcworkspace/contents.xcworkspacedata ================================================ ================================================ FILE: README.md ================================================ # PSTModernizer PSTModernizer carefully applies patches to UIKit and related Apple frameworks to fix known radars with the least impact. The current set of patches just applies to iOS 9 and nothing is executed on iOS 10, as the bugs have been fixed there. This project later on might also patch-add a few essential missing elements in iOS 10 if there's need - currently the focus is just to fix various bugs. ## Installation Simply copy `PSTModernizer.h/mm` into your project, then call `[PSTModernizer installModernizer];` somewhere early, ideally in your app delegate. Currently covers following radars (all of them have been fixed in iOS 10) * [26954460 - UIImage creation has a race conditon on background threads.](https://openradar.appspot.com/26954460)
The radar is actually for fixing the documentation, [the original issue is explained here.](https://pspdfkit.com/blog/2016/investigating-thread-saftey-of-UIImage/) * [26295020 - Action sheets presented for links/numbers don’t work in presented view controllers](https://openradar.appspot.com/26295020) You can simply delete the workarounds that do not affect you - every workaround is self-contained and can be individually removed. ## FAQ Q: *Why?*
A: Because we need to support older UIKit versions. [At PSPDFKit we support n-1](https://pspdfkit.com/guides/ios/current/announcements/version-support/), so we're just about to drop iOS 8 and will likely use something like this for our next major release. This project should make it easier to patch up the system so you need to write less ugly code. Q: *Isn't that partly using private API?*
A: Partly. The goal is to write workarounds using just public API, but it's not always possible or would lead to much more scary code. If we revert to private API, we use it for good, not evil. You decide. Since we restrict API usage to versions that have been already released and don't apply it to unknown versions, the risk is minimal. If you do find a way to patch things without private API that are similary effective and not 10x the code, please submit a pull request. We also only use it to work around bugs, not for accessing new features. Of course I can't make any guarantees if Apple accepts this on app review. (but so far we have not gotten a report that blocks this, and worst case you disable the parts that are private and just have a slightly more broken app.) ## License The MIT License (MIT) Copyright (c) 2016 Peter Steinberger, PSPDFKit GmbH. 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. ## About This project is maintained and funded by [PSPDFKit](https://pspdfkit.com/). See [our other open source projects](https://github.com/PSPDFKit-labs), read [our blog](https://pspdfkit.com/blog/) or say hello on Twitter ([@PSPDFKit](https://twitter.com/pspdfkit)).